mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-01 06:45:36 +00:00
3939 lines
121 KiB
C
3939 lines
121 KiB
C
/*
|
|
* Copyright 2022 Connor McAdams for CodeWeavers
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
*/
|
|
|
|
#include "uia_private.h"
|
|
|
|
#include "wine/debug.h"
|
|
|
|
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
|
|
|
|
static HRESULT get_uia_condition_struct_from_iface(IUIAutomationCondition *condition, struct UiaCondition **cond_struct);
|
|
|
|
/*
|
|
* IUIAutomationOrCondition interface.
|
|
*/
|
|
struct uia_or_condition {
|
|
IUIAutomationOrCondition IUIAutomationOrCondition_iface;
|
|
LONG ref;
|
|
|
|
IUIAutomationCondition **child_ifaces;
|
|
int child_count;
|
|
|
|
struct UiaAndOrCondition condition;
|
|
};
|
|
|
|
static inline struct uia_or_condition *impl_from_IUIAutomationOrCondition(IUIAutomationOrCondition *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_or_condition, IUIAutomationOrCondition_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_or_condition_QueryInterface(IUIAutomationOrCondition *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
if (IsEqualIID(riid, &IID_IUIAutomationOrCondition) || IsEqualIID(riid, &IID_IUIAutomationCondition) ||
|
|
IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationOrCondition_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_or_condition_AddRef(IUIAutomationOrCondition *iface)
|
|
{
|
|
struct uia_or_condition *uia_or_condition = impl_from_IUIAutomationOrCondition(iface);
|
|
ULONG ref = InterlockedIncrement(&uia_or_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_or_condition, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_or_condition_Release(IUIAutomationOrCondition *iface)
|
|
{
|
|
struct uia_or_condition *uia_or_condition = impl_from_IUIAutomationOrCondition(iface);
|
|
ULONG ref = InterlockedDecrement(&uia_or_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_or_condition, ref);
|
|
|
|
if (!ref)
|
|
{
|
|
if (uia_or_condition->child_ifaces)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < uia_or_condition->child_count; i++)
|
|
{
|
|
if (uia_or_condition->child_ifaces[i])
|
|
IUIAutomationCondition_Release(uia_or_condition->child_ifaces[i]);
|
|
}
|
|
}
|
|
|
|
heap_free(uia_or_condition->child_ifaces);
|
|
heap_free(uia_or_condition->condition.ppConditions);
|
|
heap_free(uia_or_condition);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_or_condition_get_ChildCount(IUIAutomationOrCondition *iface, int *child_count)
|
|
{
|
|
struct uia_or_condition *uia_or_condition = impl_from_IUIAutomationOrCondition(iface);
|
|
|
|
TRACE("%p, %p\n", iface, child_count);
|
|
|
|
if (!child_count)
|
|
return E_POINTER;
|
|
|
|
*child_count = uia_or_condition->child_count;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_or_condition_GetChildrenAsNativeArray(IUIAutomationOrCondition *iface,
|
|
IUIAutomationCondition ***out_children, int *out_children_count)
|
|
{
|
|
struct uia_or_condition *uia_or_condition = impl_from_IUIAutomationOrCondition(iface);
|
|
IUIAutomationCondition **children;
|
|
int i;
|
|
|
|
TRACE("%p, %p, %p\n", iface, out_children, out_children_count);
|
|
|
|
if (!out_children)
|
|
return E_POINTER;
|
|
|
|
*out_children = NULL;
|
|
|
|
if (!out_children_count)
|
|
return E_POINTER;
|
|
|
|
if (!(children = CoTaskMemAlloc(uia_or_condition->child_count * sizeof(*children))))
|
|
return E_OUTOFMEMORY;
|
|
|
|
for (i = 0; i < uia_or_condition->child_count; i++)
|
|
{
|
|
children[i] = uia_or_condition->child_ifaces[i];
|
|
IUIAutomationCondition_AddRef(uia_or_condition->child_ifaces[i]);
|
|
}
|
|
|
|
*out_children = children;
|
|
*out_children_count = uia_or_condition->child_count;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_or_condition_GetChildren(IUIAutomationOrCondition *iface, SAFEARRAY **out_children)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_children);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IUIAutomationOrConditionVtbl uia_or_condition_vtbl = {
|
|
uia_or_condition_QueryInterface,
|
|
uia_or_condition_AddRef,
|
|
uia_or_condition_Release,
|
|
uia_or_condition_get_ChildCount,
|
|
uia_or_condition_GetChildrenAsNativeArray,
|
|
uia_or_condition_GetChildren,
|
|
};
|
|
|
|
static HRESULT create_uia_or_condition_iface(IUIAutomationCondition **out_cond, IUIAutomationCondition **in_conds,
|
|
int in_cond_count)
|
|
{
|
|
struct uia_or_condition *uia_or_condition;
|
|
int i;
|
|
|
|
if (!out_cond)
|
|
return E_POINTER;
|
|
|
|
*out_cond = NULL;
|
|
|
|
uia_or_condition = heap_alloc_zero(sizeof(*uia_or_condition));
|
|
if (!uia_or_condition)
|
|
return E_OUTOFMEMORY;
|
|
|
|
uia_or_condition->IUIAutomationOrCondition_iface.lpVtbl = &uia_or_condition_vtbl;
|
|
uia_or_condition->ref = 1;
|
|
|
|
uia_or_condition->child_ifaces = heap_alloc_zero(sizeof(*in_conds) * in_cond_count);
|
|
if (!uia_or_condition->child_ifaces)
|
|
{
|
|
IUIAutomationOrCondition_Release(&uia_or_condition->IUIAutomationOrCondition_iface);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
uia_or_condition->condition.ppConditions = heap_alloc_zero(sizeof(*uia_or_condition->condition.ppConditions) * in_cond_count);
|
|
if (!uia_or_condition->condition.ppConditions)
|
|
{
|
|
IUIAutomationOrCondition_Release(&uia_or_condition->IUIAutomationOrCondition_iface);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
uia_or_condition->condition.ConditionType = ConditionType_Or;
|
|
uia_or_condition->child_count = uia_or_condition->condition.cConditions = in_cond_count;
|
|
for (i = 0; i < in_cond_count; i++)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = get_uia_condition_struct_from_iface(in_conds[i], &uia_or_condition->condition.ppConditions[i]);
|
|
if (FAILED(hr))
|
|
{
|
|
IUIAutomationOrCondition_Release(&uia_or_condition->IUIAutomationOrCondition_iface);
|
|
return hr;
|
|
}
|
|
|
|
uia_or_condition->child_ifaces[i] = in_conds[i];
|
|
IUIAutomationCondition_AddRef(in_conds[i]);
|
|
}
|
|
|
|
*out_cond = (IUIAutomationCondition *)&uia_or_condition->IUIAutomationOrCondition_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomationNotCondition interface.
|
|
*/
|
|
struct uia_not_condition {
|
|
IUIAutomationNotCondition IUIAutomationNotCondition_iface;
|
|
LONG ref;
|
|
|
|
IUIAutomationCondition *child_iface;
|
|
struct UiaNotCondition condition;
|
|
};
|
|
|
|
static inline struct uia_not_condition *impl_from_IUIAutomationNotCondition(IUIAutomationNotCondition *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_not_condition, IUIAutomationNotCondition_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_not_condition_QueryInterface(IUIAutomationNotCondition *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
if (IsEqualIID(riid, &IID_IUIAutomationNotCondition) || IsEqualIID(riid, &IID_IUIAutomationCondition) ||
|
|
IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationNotCondition_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_not_condition_AddRef(IUIAutomationNotCondition *iface)
|
|
{
|
|
struct uia_not_condition *uia_not_condition = impl_from_IUIAutomationNotCondition(iface);
|
|
ULONG ref = InterlockedIncrement(&uia_not_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_not_condition, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_not_condition_Release(IUIAutomationNotCondition *iface)
|
|
{
|
|
struct uia_not_condition *uia_not_condition = impl_from_IUIAutomationNotCondition(iface);
|
|
ULONG ref = InterlockedDecrement(&uia_not_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_not_condition, ref);
|
|
if (!ref)
|
|
{
|
|
IUIAutomationCondition_Release(uia_not_condition->child_iface);
|
|
heap_free(uia_not_condition);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_not_condition_GetChild(IUIAutomationNotCondition *iface, IUIAutomationCondition **child)
|
|
{
|
|
struct uia_not_condition *uia_not_condition = impl_from_IUIAutomationNotCondition(iface);
|
|
|
|
TRACE("%p, %p\n", iface, child);
|
|
|
|
if (!child)
|
|
return E_POINTER;
|
|
|
|
IUIAutomationCondition_AddRef(uia_not_condition->child_iface);
|
|
*child = uia_not_condition->child_iface;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IUIAutomationNotConditionVtbl uia_not_condition_vtbl = {
|
|
uia_not_condition_QueryInterface,
|
|
uia_not_condition_AddRef,
|
|
uia_not_condition_Release,
|
|
uia_not_condition_GetChild,
|
|
};
|
|
|
|
static HRESULT create_uia_not_condition_iface(IUIAutomationCondition **out_cond, IUIAutomationCondition *in_cond)
|
|
{
|
|
struct uia_not_condition *uia_not_condition;
|
|
struct UiaCondition *cond_struct;
|
|
HRESULT hr;
|
|
|
|
if (!out_cond)
|
|
return E_POINTER;
|
|
|
|
*out_cond = NULL;
|
|
hr = get_uia_condition_struct_from_iface(in_cond, &cond_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
uia_not_condition = heap_alloc_zero(sizeof(*uia_not_condition));
|
|
if (!uia_not_condition)
|
|
return E_OUTOFMEMORY;
|
|
|
|
uia_not_condition->IUIAutomationNotCondition_iface.lpVtbl = &uia_not_condition_vtbl;
|
|
uia_not_condition->condition.ConditionType = ConditionType_Not;
|
|
uia_not_condition->condition.pConditions = cond_struct;
|
|
uia_not_condition->ref = 1;
|
|
uia_not_condition->child_iface = in_cond;
|
|
IUIAutomationCondition_AddRef(in_cond);
|
|
|
|
*out_cond = (IUIAutomationCondition *)&uia_not_condition->IUIAutomationNotCondition_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomationPropertyCondition interface.
|
|
*/
|
|
struct uia_property_condition {
|
|
IUIAutomationPropertyCondition IUIAutomationPropertyCondition_iface;
|
|
LONG ref;
|
|
|
|
struct UiaPropertyCondition condition;
|
|
};
|
|
|
|
static inline struct uia_property_condition *impl_from_IUIAutomationPropertyCondition(IUIAutomationPropertyCondition *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_property_condition, IUIAutomationPropertyCondition_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_property_condition_QueryInterface(IUIAutomationPropertyCondition *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
if (IsEqualIID(riid, &IID_IUIAutomationPropertyCondition) || IsEqualIID(riid, &IID_IUIAutomationCondition) ||
|
|
IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationPropertyCondition_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_property_condition_AddRef(IUIAutomationPropertyCondition *iface)
|
|
{
|
|
struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface);
|
|
ULONG ref = InterlockedIncrement(&uia_property_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_property_condition, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_property_condition_Release(IUIAutomationPropertyCondition *iface)
|
|
{
|
|
struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface);
|
|
ULONG ref = InterlockedDecrement(&uia_property_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_property_condition, ref);
|
|
|
|
if (!ref)
|
|
{
|
|
VariantClear(&uia_property_condition->condition.Value);
|
|
heap_free(uia_property_condition);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_property_condition_get_PropertyId(IUIAutomationPropertyCondition *iface, PROPERTYID *prop_id)
|
|
{
|
|
struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface);
|
|
|
|
TRACE("%p, %p\n", iface, prop_id);
|
|
|
|
if (!prop_id)
|
|
return E_POINTER;
|
|
|
|
*prop_id = uia_property_condition->condition.PropertyId;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_property_condition_get_PropertyValue(IUIAutomationPropertyCondition *iface, VARIANT *val)
|
|
{
|
|
struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface);
|
|
|
|
TRACE("%p, %p\n", iface, val);
|
|
|
|
if (!val)
|
|
return E_POINTER;
|
|
|
|
VariantCopy(val, &uia_property_condition->condition.Value);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_property_condition_get_PropertyConditionFlags(IUIAutomationPropertyCondition *iface,
|
|
enum PropertyConditionFlags *flags)
|
|
{
|
|
struct uia_property_condition *uia_property_condition = impl_from_IUIAutomationPropertyCondition(iface);
|
|
|
|
TRACE("%p, %p\n", iface, flags);
|
|
|
|
if (!flags)
|
|
return E_POINTER;
|
|
|
|
*flags = uia_property_condition->condition.Flags;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IUIAutomationPropertyConditionVtbl uia_property_condition_vtbl = {
|
|
uia_property_condition_QueryInterface,
|
|
uia_property_condition_AddRef,
|
|
uia_property_condition_Release,
|
|
uia_property_condition_get_PropertyId,
|
|
uia_property_condition_get_PropertyValue,
|
|
uia_property_condition_get_PropertyConditionFlags,
|
|
};
|
|
|
|
static HRESULT create_uia_property_condition_iface(IUIAutomationCondition **out_cond, PROPERTYID prop_id, VARIANT val,
|
|
enum PropertyConditionFlags prop_flags)
|
|
{
|
|
const struct uia_prop_info *prop_info = uia_prop_info_from_id(prop_id);
|
|
struct uia_property_condition *uia_property_condition;
|
|
|
|
if (!out_cond)
|
|
return E_POINTER;
|
|
|
|
*out_cond = NULL;
|
|
if (!prop_info)
|
|
return E_INVALIDARG;
|
|
|
|
switch (prop_info->type)
|
|
{
|
|
case UIAutomationType_Bool:
|
|
if (V_VT(&val) != VT_BOOL)
|
|
return E_INVALIDARG;
|
|
break;
|
|
|
|
case UIAutomationType_IntArray:
|
|
if (V_VT(&val) != (VT_I4 | VT_ARRAY))
|
|
return E_INVALIDARG;
|
|
break;
|
|
|
|
default:
|
|
FIXME("Property condition evaluation for property type %#x unimplemented\n", prop_info->type);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
uia_property_condition = heap_alloc_zero(sizeof(*uia_property_condition));
|
|
if (!uia_property_condition)
|
|
return E_OUTOFMEMORY;
|
|
|
|
uia_property_condition->IUIAutomationPropertyCondition_iface.lpVtbl = &uia_property_condition_vtbl;
|
|
uia_property_condition->condition.ConditionType = ConditionType_Property;
|
|
uia_property_condition->condition.PropertyId = prop_id;
|
|
VariantCopy(&uia_property_condition->condition.Value, &val);
|
|
uia_property_condition->condition.Flags = prop_flags;
|
|
uia_property_condition->ref = 1;
|
|
|
|
*out_cond = (IUIAutomationCondition *)&uia_property_condition->IUIAutomationPropertyCondition_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomationBoolCondition interface.
|
|
*/
|
|
struct uia_bool_condition {
|
|
IUIAutomationBoolCondition IUIAutomationBoolCondition_iface;
|
|
LONG ref;
|
|
|
|
struct UiaCondition condition;
|
|
};
|
|
|
|
static inline struct uia_bool_condition *impl_from_IUIAutomationBoolCondition(IUIAutomationBoolCondition *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_bool_condition, IUIAutomationBoolCondition_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_bool_condition_QueryInterface(IUIAutomationBoolCondition *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
if (IsEqualIID(riid, &IID_IUIAutomationBoolCondition) || IsEqualIID(riid, &IID_IUIAutomationCondition) ||
|
|
IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationBoolCondition_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_bool_condition_AddRef(IUIAutomationBoolCondition *iface)
|
|
{
|
|
struct uia_bool_condition *uia_bool_condition = impl_from_IUIAutomationBoolCondition(iface);
|
|
ULONG ref = InterlockedIncrement(&uia_bool_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_bool_condition, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_bool_condition_Release(IUIAutomationBoolCondition *iface)
|
|
{
|
|
struct uia_bool_condition *uia_bool_condition = impl_from_IUIAutomationBoolCondition(iface);
|
|
ULONG ref = InterlockedDecrement(&uia_bool_condition->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_bool_condition, ref);
|
|
if (!ref)
|
|
heap_free(uia_bool_condition);
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_bool_condition_get_BooleanValue(IUIAutomationBoolCondition *iface, BOOL *ret_val)
|
|
{
|
|
struct uia_bool_condition *uia_bool_condition = impl_from_IUIAutomationBoolCondition(iface);
|
|
|
|
TRACE("%p, %p\n", iface, ret_val);
|
|
|
|
if (!ret_val)
|
|
return E_POINTER;
|
|
|
|
if (uia_bool_condition->condition.ConditionType == ConditionType_True)
|
|
*ret_val = TRUE;
|
|
else
|
|
*ret_val = FALSE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IUIAutomationBoolConditionVtbl uia_bool_condition_vtbl = {
|
|
uia_bool_condition_QueryInterface,
|
|
uia_bool_condition_AddRef,
|
|
uia_bool_condition_Release,
|
|
uia_bool_condition_get_BooleanValue,
|
|
};
|
|
|
|
static HRESULT create_uia_bool_condition_iface(IUIAutomationCondition **out_cond, enum ConditionType cond_type)
|
|
{
|
|
struct uia_bool_condition *uia_bool_condition;
|
|
|
|
if (!out_cond)
|
|
return E_POINTER;
|
|
|
|
uia_bool_condition = heap_alloc_zero(sizeof(*uia_bool_condition));
|
|
if (!uia_bool_condition)
|
|
return E_OUTOFMEMORY;
|
|
|
|
uia_bool_condition->IUIAutomationBoolCondition_iface.lpVtbl = &uia_bool_condition_vtbl;
|
|
uia_bool_condition->condition.ConditionType = cond_type;
|
|
uia_bool_condition->ref = 1;
|
|
|
|
*out_cond = (IUIAutomationCondition *)&uia_bool_condition->IUIAutomationBoolCondition_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT get_uia_condition_struct_from_iface(IUIAutomationCondition *condition, struct UiaCondition **cond_struct)
|
|
{
|
|
*cond_struct = NULL;
|
|
if (!condition)
|
|
return E_POINTER;
|
|
|
|
if (condition->lpVtbl == (IUIAutomationConditionVtbl *)&uia_bool_condition_vtbl)
|
|
{
|
|
struct uia_bool_condition *cond;
|
|
|
|
cond = impl_from_IUIAutomationBoolCondition((IUIAutomationBoolCondition *)condition);
|
|
*cond_struct = &cond->condition;
|
|
}
|
|
else if (condition->lpVtbl == (IUIAutomationConditionVtbl *)&uia_property_condition_vtbl)
|
|
{
|
|
struct uia_property_condition *cond;
|
|
|
|
cond = impl_from_IUIAutomationPropertyCondition((IUIAutomationPropertyCondition *)condition);
|
|
*cond_struct = (struct UiaCondition *)&cond->condition;
|
|
}
|
|
else if (condition->lpVtbl == (IUIAutomationConditionVtbl *)&uia_not_condition_vtbl)
|
|
{
|
|
struct uia_not_condition *cond;
|
|
|
|
cond = impl_from_IUIAutomationNotCondition((IUIAutomationNotCondition *)condition);
|
|
*cond_struct = (struct UiaCondition *)&cond->condition;
|
|
}
|
|
else if (condition->lpVtbl == (IUIAutomationConditionVtbl *)&uia_or_condition_vtbl)
|
|
{
|
|
struct uia_or_condition *cond;
|
|
|
|
cond = impl_from_IUIAutomationOrCondition((IUIAutomationOrCondition *)condition);
|
|
*cond_struct = (struct UiaCondition *)&cond->condition;
|
|
}
|
|
else
|
|
return E_FAIL;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT create_control_view_condition_iface(IUIAutomationCondition **out_condition)
|
|
{
|
|
IUIAutomationCondition *prop_cond, *not_cond;
|
|
HRESULT hr;
|
|
VARIANT v;
|
|
|
|
if (!out_condition)
|
|
return E_POINTER;
|
|
|
|
*out_condition = NULL;
|
|
|
|
VariantInit(&v);
|
|
V_VT(&v) = VT_BOOL;
|
|
V_BOOL(&v) = VARIANT_FALSE;
|
|
hr = create_uia_property_condition_iface(&prop_cond, UIA_IsControlElementPropertyId, v, PropertyConditionFlags_None);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = create_uia_not_condition_iface(¬_cond, prop_cond);
|
|
if (FAILED(hr))
|
|
{
|
|
IUIAutomationCondition_Release(prop_cond);
|
|
return hr;
|
|
}
|
|
|
|
*out_condition = not_cond;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomationCacheRequest interface.
|
|
*/
|
|
struct uia_cache_request {
|
|
IUIAutomationCacheRequest IUIAutomationCacheRequest_iface;
|
|
LONG ref;
|
|
|
|
IUIAutomationCondition *view_condition;
|
|
struct UiaCacheRequest cache_req;
|
|
|
|
int *prop_ids;
|
|
int prop_ids_count;
|
|
SIZE_T prop_ids_arr_size;
|
|
};
|
|
|
|
static inline struct uia_cache_request *impl_from_IUIAutomationCacheRequest(IUIAutomationCacheRequest *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_cache_request, IUIAutomationCacheRequest_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_QueryInterface(IUIAutomationCacheRequest *iface, REFIID riid, void **ppv)
|
|
{
|
|
*ppv = NULL;
|
|
if (IsEqualIID(riid, &IID_IUIAutomationCacheRequest) || IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationCacheRequest_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_cache_request_AddRef(IUIAutomationCacheRequest *iface)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
ULONG ref = InterlockedIncrement(&uia_cache_request->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_cache_request, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_cache_request_Release(IUIAutomationCacheRequest *iface)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
ULONG ref = InterlockedDecrement(&uia_cache_request->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_cache_request, ref);
|
|
|
|
if (!ref)
|
|
{
|
|
IUIAutomationCondition_Release(uia_cache_request->view_condition);
|
|
heap_free(uia_cache_request->prop_ids);
|
|
heap_free(uia_cache_request);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_AddProperty(IUIAutomationCacheRequest *iface, PROPERTYID prop_id)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
const struct uia_prop_info *prop_info = uia_prop_info_from_id(prop_id);
|
|
int i;
|
|
|
|
TRACE("%p, %d\n", iface, prop_id);
|
|
|
|
if (!prop_info)
|
|
return E_INVALIDARG;
|
|
|
|
/* Don't add a duplicate property to the cache request. */
|
|
for (i = 0; i < uia_cache_request->prop_ids_count; i++)
|
|
{
|
|
if (uia_cache_request->prop_ids[i] == prop_id)
|
|
return S_OK;
|
|
}
|
|
|
|
if (!uia_array_reserve((void **)&uia_cache_request->prop_ids, &uia_cache_request->prop_ids_arr_size,
|
|
uia_cache_request->prop_ids_count + 1, sizeof(*uia_cache_request->prop_ids)))
|
|
return E_OUTOFMEMORY;
|
|
|
|
uia_cache_request->prop_ids[uia_cache_request->prop_ids_count] = prop_id;
|
|
uia_cache_request->prop_ids_count++;
|
|
|
|
uia_cache_request->cache_req.pProperties = uia_cache_request->prop_ids;
|
|
uia_cache_request->cache_req.cProperties = uia_cache_request->prop_ids_count;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_AddPattern(IUIAutomationCacheRequest *iface, PATTERNID pattern_id)
|
|
{
|
|
FIXME("%p, %d: stub\n", iface, pattern_id);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_Clone(IUIAutomationCacheRequest *iface, IUIAutomationCacheRequest **out_req)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_req);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_get_TreeScope(IUIAutomationCacheRequest *iface, enum TreeScope *scope)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
|
|
TRACE("%p, %p\n", iface, scope);
|
|
|
|
if (!scope)
|
|
return E_POINTER;
|
|
|
|
*scope = uia_cache_request->cache_req.Scope;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_put_TreeScope(IUIAutomationCacheRequest *iface, enum TreeScope scope)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
|
|
TRACE("%p, %#x\n", iface, scope);
|
|
|
|
if (!scope || (scope & ~TreeScope_SubTree))
|
|
return E_INVALIDARG;
|
|
|
|
if ((scope & TreeScope_Children) || (scope & TreeScope_Descendants))
|
|
{
|
|
FIXME("Unimplemented TreeScope %#x\n", scope);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
uia_cache_request->cache_req.Scope = scope;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_get_TreeFilter(IUIAutomationCacheRequest *iface,
|
|
IUIAutomationCondition **filter)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
|
|
TRACE("%p, %p\n", iface, filter);
|
|
|
|
if (!filter)
|
|
return E_POINTER;
|
|
|
|
IUIAutomationCondition_AddRef(uia_cache_request->view_condition);
|
|
*filter = uia_cache_request->view_condition;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_put_TreeFilter(IUIAutomationCacheRequest *iface, IUIAutomationCondition *filter)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
struct UiaCondition *cond_struct;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", iface, filter);
|
|
|
|
if (!filter)
|
|
return E_POINTER;
|
|
|
|
hr = get_uia_condition_struct_from_iface(filter, &cond_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
uia_cache_request->cache_req.pViewCondition = cond_struct;
|
|
IUIAutomationCondition_Release(uia_cache_request->view_condition);
|
|
uia_cache_request->view_condition = filter;
|
|
IUIAutomationCondition_AddRef(filter);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_get_AutomationElementMode(IUIAutomationCacheRequest *iface,
|
|
enum AutomationElementMode *mode)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
|
|
TRACE("%p, %p\n", iface, mode);
|
|
|
|
if (!mode)
|
|
return E_POINTER;
|
|
|
|
*mode = uia_cache_request->cache_req.automationElementMode;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_cache_request_put_AutomationElementMode(IUIAutomationCacheRequest *iface,
|
|
enum AutomationElementMode mode)
|
|
{
|
|
struct uia_cache_request *uia_cache_request = impl_from_IUIAutomationCacheRequest(iface);
|
|
|
|
TRACE("%p, %d\n", iface, mode);
|
|
|
|
if ((mode != AutomationElementMode_Full) && (mode != AutomationElementMode_None))
|
|
return E_INVALIDARG;
|
|
|
|
if (mode == AutomationElementMode_None)
|
|
{
|
|
FIXME("AutomationElementMode_None unsupported\n");
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
uia_cache_request->cache_req.automationElementMode = mode;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IUIAutomationCacheRequestVtbl uia_cache_request_vtbl = {
|
|
uia_cache_request_QueryInterface,
|
|
uia_cache_request_AddRef,
|
|
uia_cache_request_Release,
|
|
uia_cache_request_AddProperty,
|
|
uia_cache_request_AddPattern,
|
|
uia_cache_request_Clone,
|
|
uia_cache_request_get_TreeScope,
|
|
uia_cache_request_put_TreeScope,
|
|
uia_cache_request_get_TreeFilter,
|
|
uia_cache_request_put_TreeFilter,
|
|
uia_cache_request_get_AutomationElementMode,
|
|
uia_cache_request_put_AutomationElementMode,
|
|
};
|
|
|
|
static HRESULT create_uia_cache_request_iface(IUIAutomationCacheRequest **out_cache_req)
|
|
{
|
|
struct uia_cache_request *uia_cache_request;
|
|
IUIAutomationCondition *view_condition;
|
|
HRESULT hr;
|
|
|
|
if (!out_cache_req)
|
|
return E_POINTER;
|
|
|
|
*out_cache_req = NULL;
|
|
hr = create_control_view_condition_iface(&view_condition);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
uia_cache_request = heap_alloc_zero(sizeof(*uia_cache_request));
|
|
if (!uia_cache_request)
|
|
{
|
|
IUIAutomationCondition_Release(view_condition);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
uia_cache_request->IUIAutomationCacheRequest_iface.lpVtbl = &uia_cache_request_vtbl;
|
|
uia_cache_request->ref = 1;
|
|
|
|
uia_cache_request->view_condition = view_condition;
|
|
get_uia_condition_struct_from_iface(view_condition, &uia_cache_request->cache_req.pViewCondition);
|
|
uia_cache_request->cache_req.Scope = TreeScope_Element;
|
|
uia_cache_request->cache_req.automationElementMode = AutomationElementMode_Full;
|
|
|
|
*out_cache_req = &uia_cache_request->IUIAutomationCacheRequest_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT get_uia_cache_request_struct_from_iface(IUIAutomationCacheRequest *cache_request,
|
|
struct UiaCacheRequest **cache_req_struct)
|
|
{
|
|
struct uia_cache_request *cache_req_data;
|
|
|
|
*cache_req_struct = NULL;
|
|
if (!cache_request)
|
|
return E_POINTER;
|
|
|
|
if (cache_request->lpVtbl != &uia_cache_request_vtbl)
|
|
return E_FAIL;
|
|
|
|
cache_req_data = impl_from_IUIAutomationCacheRequest(cache_request);
|
|
*cache_req_struct = &cache_req_data->cache_req;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* COM API UI Automation event related functions.
|
|
*/
|
|
static struct uia_com_event_handlers
|
|
{
|
|
struct rb_tree handler_map;
|
|
|
|
LONG handler_count;
|
|
} com_event_handlers;
|
|
|
|
static CRITICAL_SECTION com_event_handlers_cs;
|
|
static CRITICAL_SECTION_DEBUG com_event_handlers_cs_debug =
|
|
{
|
|
0, 0, &com_event_handlers_cs,
|
|
{ &com_event_handlers_cs_debug.ProcessLocksList, &com_event_handlers_cs_debug.ProcessLocksList },
|
|
0, 0, { (DWORD_PTR)(__FILE__ ": com_event_handlers_cs") }
|
|
};
|
|
static CRITICAL_SECTION com_event_handlers_cs = { &com_event_handlers_cs_debug, -1, 0, 0, 0, 0 };
|
|
|
|
struct uia_event_handler_identifier {
|
|
IUnknown *handler_iface;
|
|
SAFEARRAY *runtime_id;
|
|
int event_id;
|
|
};
|
|
|
|
struct uia_event_handler_map_entry
|
|
{
|
|
struct rb_entry entry;
|
|
|
|
IUnknown *handler_iface;
|
|
SAFEARRAY *runtime_id;
|
|
int event_id;
|
|
|
|
struct list handlers_list;
|
|
};
|
|
|
|
static int uia_com_event_handler_id_compare(const void *key, const struct rb_entry *entry)
|
|
{
|
|
struct uia_event_handler_map_entry *map_entry = RB_ENTRY_VALUE(entry, struct uia_event_handler_map_entry, entry);
|
|
struct uia_event_handler_identifier *event_id = (struct uia_event_handler_identifier *)key;
|
|
|
|
if (event_id->event_id != map_entry->event_id)
|
|
return (event_id->event_id > map_entry->event_id) - (event_id->event_id < map_entry->event_id);
|
|
else if (event_id->handler_iface != map_entry->handler_iface)
|
|
return (event_id->handler_iface > map_entry->handler_iface) - (event_id->handler_iface < map_entry->handler_iface);
|
|
else if (event_id->runtime_id && map_entry->runtime_id)
|
|
return uia_compare_safearrays(event_id->runtime_id, map_entry->runtime_id, UIAutomationType_IntArray);
|
|
else
|
|
return (event_id->runtime_id > map_entry->runtime_id) - (event_id->runtime_id < map_entry->runtime_id);
|
|
}
|
|
|
|
struct uia_com_event {
|
|
DWORD git_cookie;
|
|
HUIAEVENT event;
|
|
BOOL from_cui8;
|
|
|
|
struct list event_handler_map_list_entry;
|
|
struct uia_event_handler_map_entry *handler_map;
|
|
};
|
|
|
|
static HRESULT uia_event_handlers_add_handler(IUnknown *handler_iface, SAFEARRAY *runtime_id, int event_id,
|
|
struct uia_com_event *event)
|
|
{
|
|
struct uia_event_handler_identifier event_ident = { handler_iface, runtime_id, event_id };
|
|
struct uia_event_handler_map_entry *event_map;
|
|
struct rb_entry *rb_entry;
|
|
HRESULT hr = S_OK;
|
|
|
|
EnterCriticalSection(&com_event_handlers_cs);
|
|
|
|
if (!com_event_handlers.handler_count)
|
|
rb_init(&com_event_handlers.handler_map, uia_com_event_handler_id_compare);
|
|
|
|
if ((rb_entry = rb_get(&com_event_handlers.handler_map, &event_ident)))
|
|
event_map = RB_ENTRY_VALUE(rb_entry, struct uia_event_handler_map_entry, entry);
|
|
else
|
|
{
|
|
if (!(event_map = heap_alloc_zero(sizeof(*event_map))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
hr = SafeArrayCopy(runtime_id, &event_map->runtime_id);
|
|
if (FAILED(hr))
|
|
{
|
|
heap_free(event_map);
|
|
goto exit;
|
|
}
|
|
|
|
event_map->event_id = event_id;
|
|
event_map->handler_iface = handler_iface;
|
|
IUnknown_AddRef(event_map->handler_iface);
|
|
|
|
list_init(&event_map->handlers_list);
|
|
rb_put(&com_event_handlers.handler_map, &event_ident, &event_map->entry);
|
|
}
|
|
|
|
list_add_tail(&event_map->handlers_list, &event->event_handler_map_list_entry);
|
|
event->handler_map = event_map;
|
|
com_event_handlers.handler_count++;
|
|
|
|
exit:
|
|
LeaveCriticalSection(&com_event_handlers_cs);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static void uia_event_handler_destroy(struct uia_com_event *event)
|
|
{
|
|
list_remove(&event->event_handler_map_list_entry);
|
|
if (event->event)
|
|
UiaRemoveEvent(event->event);
|
|
if (event->git_cookie)
|
|
unregister_interface_in_git(event->git_cookie);
|
|
heap_free(event);
|
|
}
|
|
|
|
static void uia_event_handler_map_entry_destroy(struct uia_event_handler_map_entry *entry)
|
|
{
|
|
struct uia_com_event *event, *event2;
|
|
|
|
LIST_FOR_EACH_ENTRY_SAFE(event, event2, &entry->handlers_list, struct uia_com_event, event_handler_map_list_entry)
|
|
{
|
|
uia_event_handler_destroy(event);
|
|
com_event_handlers.handler_count--;
|
|
}
|
|
|
|
rb_remove(&com_event_handlers.handler_map, &entry->entry);
|
|
IUnknown_Release(entry->handler_iface);
|
|
SafeArrayDestroy(entry->runtime_id);
|
|
heap_free(entry);
|
|
}
|
|
|
|
static void uia_event_handlers_remove_handlers(IUnknown *handler_iface, SAFEARRAY *runtime_id, int event_id)
|
|
{
|
|
struct uia_event_handler_identifier event_ident = { handler_iface, runtime_id, event_id };
|
|
struct rb_entry *rb_entry;
|
|
|
|
EnterCriticalSection(&com_event_handlers_cs);
|
|
|
|
if (com_event_handlers.handler_count && (rb_entry = rb_get(&com_event_handlers.handler_map, &event_ident)))
|
|
uia_event_handler_map_entry_destroy(RB_ENTRY_VALUE(rb_entry, struct uia_event_handler_map_entry, entry));
|
|
|
|
LeaveCriticalSection(&com_event_handlers_cs);
|
|
}
|
|
|
|
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8,
|
|
struct UiaCacheRequest *cache_req, LONG start_idx, SAFEARRAY *req_data, BSTR tree_struct);
|
|
static HRESULT uia_com_event_callback(struct uia_event *event, struct uia_event_args *args,
|
|
SAFEARRAY *cache_req, BSTR tree_struct)
|
|
{
|
|
struct uia_com_event *com_event = (struct uia_com_event *)event->u.clientside.callback_data;
|
|
IUIAutomationElement *elem;
|
|
BSTR tree_struct2;
|
|
HRESULT hr;
|
|
|
|
/* Nothing matches the cache request view condition, do nothing. */
|
|
if (!cache_req)
|
|
return S_OK;
|
|
|
|
/* create_uia_element_from_cache_req frees the passed in BSTR. */
|
|
tree_struct2 = SysAllocString(tree_struct);
|
|
hr = create_uia_element_from_cache_req(&elem, com_event->from_cui8, &event->u.clientside.cache_req, 0, cache_req,
|
|
tree_struct2);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
switch (event->event_id)
|
|
{
|
|
case UIA_AutomationFocusChangedEventId:
|
|
{
|
|
IUIAutomationFocusChangedEventHandler *handler;
|
|
|
|
hr = get_interface_in_git(&IID_IUIAutomationFocusChangedEventHandler, com_event->git_cookie, (IUnknown **)&handler);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = IUIAutomationFocusChangedEventHandler_HandleFocusChangedEvent(handler, elem);
|
|
IUIAutomationFocusChangedEventHandler_Release(handler);
|
|
}
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
IUIAutomationEventHandler *handler;
|
|
|
|
hr = get_interface_in_git(&IID_IUIAutomationEventHandler, com_event->git_cookie, (IUnknown **)&handler);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = IUIAutomationEventHandler_HandleAutomationEvent(handler, elem, event->event_id);
|
|
IUIAutomationEventHandler_Release(handler);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
IUIAutomationElement_Release(elem);
|
|
|
|
return hr;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomationElementArray interface.
|
|
*/
|
|
struct uia_element_array {
|
|
IUIAutomationElementArray IUIAutomationElementArray_iface;
|
|
LONG ref;
|
|
|
|
IUIAutomationElement **elements;
|
|
int elements_count;
|
|
};
|
|
|
|
static inline struct uia_element_array *impl_from_IUIAutomationElementArray(IUIAutomationElementArray *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_element_array, IUIAutomationElementArray_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_array_QueryInterface(IUIAutomationElementArray *iface, REFIID riid, void **ppv)
|
|
{
|
|
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IUIAutomationElementArray))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationElementArray_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_element_array_AddRef(IUIAutomationElementArray *iface)
|
|
{
|
|
struct uia_element_array *element = impl_from_IUIAutomationElementArray(iface);
|
|
ULONG ref = InterlockedIncrement(&element->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", element, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_element_array_Release(IUIAutomationElementArray *iface)
|
|
{
|
|
struct uia_element_array *element_arr = impl_from_IUIAutomationElementArray(iface);
|
|
ULONG ref = InterlockedDecrement(&element_arr->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", element_arr, ref);
|
|
if (!ref)
|
|
{
|
|
if (element_arr->elements_count)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < element_arr->elements_count; i++)
|
|
{
|
|
if (element_arr->elements[i])
|
|
IUIAutomationElement_Release(element_arr->elements[i]);
|
|
}
|
|
}
|
|
heap_free(element_arr->elements);
|
|
heap_free(element_arr);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_array_get_Length(IUIAutomationElementArray *iface, int *out_length)
|
|
{
|
|
struct uia_element_array *element_arr = impl_from_IUIAutomationElementArray(iface);
|
|
|
|
TRACE("%p, %p\n", iface, out_length);
|
|
|
|
if (!out_length)
|
|
return E_POINTER;
|
|
|
|
*out_length = element_arr->elements_count;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_array_GetElement(IUIAutomationElementArray *iface, int idx,
|
|
IUIAutomationElement **out_elem)
|
|
{
|
|
struct uia_element_array *element_arr = impl_from_IUIAutomationElementArray(iface);
|
|
|
|
TRACE("%p, %p\n", iface, out_elem);
|
|
|
|
if (!out_elem)
|
|
return E_POINTER;
|
|
|
|
if ((idx < 0) || (idx >= element_arr->elements_count))
|
|
return E_INVALIDARG;
|
|
|
|
*out_elem = element_arr->elements[idx];
|
|
IUIAutomationElement_AddRef(element_arr->elements[idx]);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IUIAutomationElementArrayVtbl uia_element_array_vtbl = {
|
|
uia_element_array_QueryInterface,
|
|
uia_element_array_AddRef,
|
|
uia_element_array_Release,
|
|
uia_element_array_get_Length,
|
|
uia_element_array_GetElement,
|
|
};
|
|
|
|
static HRESULT create_uia_element_array_iface(IUIAutomationElementArray **iface, int elements_count)
|
|
{
|
|
struct uia_element_array *element_arr = heap_alloc_zero(sizeof(*element_arr));
|
|
|
|
*iface = NULL;
|
|
if (!element_arr)
|
|
return E_OUTOFMEMORY;
|
|
|
|
element_arr->IUIAutomationElementArray_iface.lpVtbl = &uia_element_array_vtbl;
|
|
element_arr->ref = 1;
|
|
element_arr->elements_count = elements_count;
|
|
if (!(element_arr->elements = heap_alloc_zero(sizeof(*element_arr->elements) * elements_count)))
|
|
{
|
|
heap_free(element_arr);
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
*iface = &element_arr->IUIAutomationElementArray_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
struct uia_cache_property {
|
|
int prop_id;
|
|
VARIANT prop_val;
|
|
};
|
|
|
|
/*
|
|
* IUIAutomationElement interface.
|
|
*/
|
|
struct uia_element {
|
|
IUIAutomationElement9 IUIAutomationElement9_iface;
|
|
LONG ref;
|
|
|
|
BOOL from_cui8;
|
|
HUIANODE node;
|
|
|
|
struct uia_cache_property *cached_props;
|
|
int cached_props_count;
|
|
|
|
IUnknown *marshal;
|
|
};
|
|
|
|
static inline struct uia_element *impl_from_IUIAutomationElement9(IUIAutomationElement9 *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_element, IUIAutomationElement9_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_QueryInterface(IUIAutomationElement9 *iface, REFIID riid, void **ppv)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
|
|
if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IUIAutomationElement) || (element->from_cui8 &&
|
|
(IsEqualIID(riid, &IID_IUIAutomationElement2) || IsEqualIID(riid, &IID_IUIAutomationElement3) ||
|
|
IsEqualIID(riid, &IID_IUIAutomationElement4) || IsEqualIID(riid, &IID_IUIAutomationElement5) ||
|
|
IsEqualIID(riid, &IID_IUIAutomationElement6) || IsEqualIID(riid, &IID_IUIAutomationElement7) ||
|
|
IsEqualIID(riid, &IID_IUIAutomationElement8) || IsEqualIID(riid, &IID_IUIAutomationElement9))))
|
|
*ppv = iface;
|
|
else if (IsEqualIID(riid, &IID_IMarshal))
|
|
return IUnknown_QueryInterface(element->marshal, riid, ppv);
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationElement9_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_element_AddRef(IUIAutomationElement9 *iface)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
ULONG ref = InterlockedIncrement(&element->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", element, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_element_Release(IUIAutomationElement9 *iface)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
ULONG ref = InterlockedDecrement(&element->ref);
|
|
|
|
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);
|
|
}
|
|
|
|
IUnknown_Release(element->marshal);
|
|
heap_free(element->cached_props);
|
|
UiaNodeRelease(element->node);
|
|
heap_free(element);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_SetFocus(IUIAutomationElement9 *iface)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetRuntimeId(IUIAutomationElement9 *iface, SAFEARRAY **runtime_id)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindFirst(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, IUIAutomationElement **found)
|
|
{
|
|
IUIAutomationCacheRequest *cache_req;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %#x, %p, %p\n", iface, scope, condition, found);
|
|
|
|
if (!found)
|
|
return E_POINTER;
|
|
|
|
*found = NULL;
|
|
hr = create_uia_cache_request_iface(&cache_req);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IUIAutomationElement9_FindFirstBuildCache(iface, scope, condition, cache_req, found);
|
|
IUIAutomationCacheRequest_Release(cache_req);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindAll(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, IUIAutomationElementArray **found)
|
|
{
|
|
IUIAutomationCacheRequest *cache_req;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %#x, %p, %p\n", iface, scope, condition, found);
|
|
|
|
if (!found)
|
|
return E_POINTER;
|
|
|
|
*found = NULL;
|
|
hr = create_uia_cache_request_iface(&cache_req);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IUIAutomationElement9_FindAllBuildCache(iface, scope, condition, cache_req, found);
|
|
IUIAutomationCacheRequest_Release(cache_req);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT set_find_params_struct(struct UiaFindParams *params, IUIAutomationCondition *cond, int scope,
|
|
BOOL find_first)
|
|
{
|
|
HRESULT hr;
|
|
|
|
hr = get_uia_condition_struct_from_iface(cond, ¶ms->pFindCondition);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!scope || (scope & (~TreeScope_SubTree)))
|
|
return E_INVALIDARG;
|
|
|
|
params->FindFirst = find_first;
|
|
if (scope & TreeScope_Element)
|
|
params->ExcludeRoot = FALSE;
|
|
else
|
|
params->ExcludeRoot = TRUE;
|
|
|
|
if (scope & TreeScope_Descendants)
|
|
params->MaxDepth = -1;
|
|
else if (scope & TreeScope_Children)
|
|
params->MaxDepth = 1;
|
|
else
|
|
params->MaxDepth = 0;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindFirstBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **found)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
LONG lbound_offsets, lbound_tree_structs, elems_count, offset_idx;
|
|
struct UiaFindParams find_params = { 0 };
|
|
struct UiaCacheRequest *cache_req_struct;
|
|
SAFEARRAY *sa, *tree_structs, *offsets;
|
|
IUIAutomationElement *elem;
|
|
BSTR tree_struct_str;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %#x, %p, %p, %p\n", iface, scope, condition, cache_req, found);
|
|
|
|
if (!found)
|
|
return E_POINTER;
|
|
|
|
*found = elem = NULL;
|
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = set_find_params_struct(&find_params, condition, scope, TRUE);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
sa = offsets = tree_structs = NULL;
|
|
hr = UiaFind(element->node, &find_params, cache_req_struct, &sa, &offsets, &tree_structs);
|
|
if (FAILED(hr) || !sa)
|
|
goto exit;
|
|
|
|
hr = get_safearray_bounds(tree_structs, &lbound_tree_structs, &elems_count);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = SafeArrayGetElement(tree_structs, &lbound_tree_structs, &tree_struct_str);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = get_safearray_bounds(offsets, &lbound_offsets, &elems_count);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = SafeArrayGetElement(offsets, &lbound_offsets, &offset_idx);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = create_uia_element_from_cache_req(&elem, element->from_cui8, cache_req_struct, offset_idx, sa, tree_struct_str);
|
|
if (SUCCEEDED(hr))
|
|
*found = elem;
|
|
|
|
exit:
|
|
SafeArrayDestroy(tree_structs);
|
|
SafeArrayDestroy(offsets);
|
|
SafeArrayDestroy(sa);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindAllBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, IUIAutomationElementArray **found)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
LONG lbound_offsets, lbound_tree_structs, elems_count;
|
|
struct uia_element_array *element_array_data;
|
|
struct UiaFindParams find_params = { 0 };
|
|
struct UiaCacheRequest *cache_req_struct;
|
|
SAFEARRAY *sa, *tree_structs, *offsets;
|
|
IUIAutomationElementArray *array;
|
|
HRESULT hr;
|
|
int i;
|
|
|
|
TRACE("%p, %#x, %p, %p, %p\n", iface, scope, condition, cache_req, found);
|
|
|
|
if (!found)
|
|
return E_POINTER;
|
|
|
|
*found = array = NULL;
|
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = set_find_params_struct(&find_params, condition, scope, FALSE);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
sa = offsets = tree_structs = NULL;
|
|
hr = UiaFind(element->node, &find_params, cache_req_struct, &sa, &offsets, &tree_structs);
|
|
if (FAILED(hr) || !sa)
|
|
goto exit;
|
|
|
|
hr = get_safearray_bounds(tree_structs, &lbound_tree_structs, &elems_count);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = get_safearray_bounds(offsets, &lbound_offsets, &elems_count);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = create_uia_element_array_iface(&array, elems_count);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
element_array_data = impl_from_IUIAutomationElementArray(array);
|
|
for (i = 0; i < elems_count; i++)
|
|
{
|
|
BSTR tree_struct_str;
|
|
LONG offset_idx, idx;
|
|
|
|
idx = lbound_offsets + i;
|
|
hr = SafeArrayGetElement(offsets, &idx, &offset_idx);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
idx = lbound_tree_structs + i;
|
|
hr = SafeArrayGetElement(tree_structs, &idx, &tree_struct_str);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = create_uia_element_from_cache_req(&element_array_data->elements[i], element->from_cui8,
|
|
cache_req_struct, offset_idx, sa, tree_struct_str);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
}
|
|
|
|
*found = array;
|
|
|
|
exit:
|
|
if (FAILED(hr) && array)
|
|
IUIAutomationElementArray_Release(array);
|
|
|
|
SafeArrayDestroy(tree_structs);
|
|
SafeArrayDestroy(offsets);
|
|
SafeArrayDestroy(sa);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_BuildUpdatedCache(IUIAutomationElement9 *iface, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationElement **updated_elem)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
struct UiaCacheRequest *cache_req_struct;
|
|
IUIAutomationElement *cache_elem;
|
|
BSTR tree_struct;
|
|
SAFEARRAY *sa;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p, %p\n", iface, cache_req, updated_elem);
|
|
|
|
if (!updated_elem)
|
|
return E_POINTER;
|
|
|
|
*updated_elem = NULL;
|
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = UiaGetUpdatedCache(element->node, cache_req_struct, NormalizeState_None, NULL, &sa, &tree_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = create_uia_element_from_cache_req(&cache_elem, element->from_cui8, cache_req_struct, 0, sa, tree_struct);
|
|
if (SUCCEEDED(hr))
|
|
*updated_elem = cache_elem;
|
|
|
|
SafeArrayDestroy(sa);
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCurrentPropertyValue(IUIAutomationElement9 *iface, PROPERTYID prop_id,
|
|
VARIANT *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8, HUIANODE node);
|
|
static HRESULT get_element_variant_from_node_variant(VARIANT *var, BOOL from_cui8, int prop_type)
|
|
{
|
|
HUIANODE node;
|
|
HRESULT hr;
|
|
|
|
/* ReservedNotSupported interface, just return it. */
|
|
if (V_VT(var) == VT_UNKNOWN)
|
|
return S_OK;
|
|
|
|
if (prop_type & UIAutomationType_Array)
|
|
{
|
|
struct uia_element_array *elem_arr_data;
|
|
IUIAutomationElementArray *elem_arr;
|
|
LONG idx, lbound, elems, i;
|
|
|
|
hr = get_safearray_bounds(V_ARRAY(var), &lbound, &elems);
|
|
if (FAILED(hr))
|
|
{
|
|
VariantClear(var);
|
|
return hr;
|
|
}
|
|
|
|
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
|
|
{
|
|
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;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCurrentPropertyValueEx(IUIAutomationElement9 *iface, PROPERTYID prop_id,
|
|
BOOL ignore_default, VARIANT *ret_val)
|
|
{
|
|
const struct uia_prop_info *prop_info = uia_prop_info_from_id(prop_id);
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %d, %d, %p\n", iface, prop_id, ignore_default, ret_val);
|
|
|
|
if (!ret_val)
|
|
return E_POINTER;
|
|
|
|
VariantInit(ret_val);
|
|
if (!prop_info)
|
|
return E_INVALIDARG;
|
|
|
|
if (!ignore_default)
|
|
FIXME("Default values currently unimplemented\n");
|
|
|
|
hr = UiaGetPropertyValue(element->node, prop_id, ret_val);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
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;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCachedPropertyValue(IUIAutomationElement9 *iface, PROPERTYID prop_id,
|
|
VARIANT *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
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)
|
|
{
|
|
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,
|
|
REFIID riid, void **out_pattern)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCachedPatternAs(IUIAutomationElement9 *iface, PATTERNID pattern_id,
|
|
REFIID riid, void **out_pattern)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCurrentPattern(IUIAutomationElement9 *iface, PATTERNID pattern_id,
|
|
IUnknown **out_pattern)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCachedPattern(IUIAutomationElement9 *iface, PATTERNID pattern_id,
|
|
IUnknown **patternObject)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCachedParent(IUIAutomationElement9 *iface, IUIAutomationElement **parent)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCachedChildren(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **children)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentProcessId(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
const struct uia_control_type_info *control_type_info = NULL;
|
|
HRESULT hr;
|
|
VARIANT v;
|
|
|
|
TRACE("%p, %p\n", iface, ret_val);
|
|
|
|
VariantInit(&v);
|
|
*ret_val = UIA_CustomControlTypeId;
|
|
hr = UiaGetPropertyValue(element->node, UIA_ControlTypePropertyId, &v);
|
|
if (SUCCEEDED(hr) && V_VT(&v) == VT_I4)
|
|
{
|
|
if ((control_type_info = uia_control_type_info_from_id(V_I4(&v))))
|
|
*ret_val = control_type_info->control_type_id;
|
|
else
|
|
WARN("Provider returned invalid control type ID %ld\n", V_I4(&v));
|
|
}
|
|
|
|
VariantClear(&v);
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentLocalizedControlType(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentName(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
HRESULT hr;
|
|
VARIANT v;
|
|
|
|
TRACE("%p, %p\n", iface, ret_val);
|
|
|
|
VariantInit(&v);
|
|
hr = UiaGetPropertyValue(element->node, UIA_NamePropertyId, &v);
|
|
if (SUCCEEDED(hr) && V_VT(&v) == VT_BSTR && V_BSTR(&v))
|
|
*ret_val = SysAllocString(V_BSTR(&v));
|
|
else
|
|
*ret_val = SysAllocString(L"");
|
|
|
|
VariantClear(&v);
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAcceleratorKey(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAccessKey(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentHasKeyboardFocus(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsKeyboardFocusable(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsEnabled(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAutomationId(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentClassName(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentHelpText(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentCulture(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsControlElement(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsContentElement(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsPassword(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentNativeWindowHandle(IUIAutomationElement9 *iface, UIA_HWND *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentItemType(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsOffscreen(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentOrientation(IUIAutomationElement9 *iface, enum OrientationType *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentFrameworkId(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsRequiredForForm(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentItemStatus(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val)
|
|
{
|
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
|
HRESULT hr;
|
|
VARIANT v;
|
|
|
|
TRACE("%p, %p\n", element, ret_val);
|
|
|
|
memset(ret_val, 0, sizeof(*ret_val));
|
|
VariantInit(&v);
|
|
hr = UiaGetPropertyValue(element->node, UIA_BoundingRectanglePropertyId, &v);
|
|
if (SUCCEEDED(hr) && V_VT(&v) == (VT_R8 | VT_ARRAY))
|
|
{
|
|
double vals[4];
|
|
LONG idx;
|
|
|
|
for (idx = 0; idx < ARRAY_SIZE(vals); idx++)
|
|
SafeArrayGetElement(V_ARRAY(&v), &idx, &vals[idx]);
|
|
|
|
ret_val->left = vals[0];
|
|
ret_val->top = vals[1];
|
|
ret_val->right = ret_val->left + vals[2];
|
|
ret_val->bottom = ret_val->top + vals[3];
|
|
}
|
|
|
|
VariantClear(&v);
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAriaRole(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAriaProperties(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsDataValidForForm(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentControllerFor(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentDescribedBy(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentFlowsTo(IUIAutomationElement9 *iface, IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentProviderDescription(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedProcessId(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedLocalizedControlType(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedName(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAcceleratorKey(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAccessKey(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedHasKeyboardFocus(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsKeyboardFocusable(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsEnabled(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAutomationId(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedClassName(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedHelpText(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedCulture(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsControlElement(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsContentElement(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsPassword(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedNativeWindowHandle(IUIAutomationElement9 *iface, UIA_HWND *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedItemType(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsOffscreen(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedOrientation(IUIAutomationElement9 *iface,
|
|
enum OrientationType *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedFrameworkId(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsRequiredForForm(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedItemStatus(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAriaRole(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAriaProperties(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsDataValidForForm(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedControllerFor(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedDescribedBy(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedFlowsTo(IUIAutomationElement9 *iface, IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedProviderDescription(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetClickablePoint(IUIAutomationElement9 *iface, POINT *clickable, BOOL *got_clickable)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentOptimizeForVisualContent(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedOptimizeForVisualContent(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentLiveSetting(IUIAutomationElement9 *iface, enum LiveSetting *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedLiveSetting(IUIAutomationElement9 *iface, enum LiveSetting *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentFlowsFrom(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedFlowsFrom(IUIAutomationElement9 *iface, IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_ShowContextMenu(IUIAutomationElement9 *iface)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsPeripheral(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsPeripheral(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentPositionInSet(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentSizeOfSet(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentLevel(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAnnotationTypes(IUIAutomationElement9 *iface, SAFEARRAY **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentAnnotationObjects(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedPositionInSet(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedSizeOfSet(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedLevel(IUIAutomationElement9 *iface, int *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAnnotationTypes(IUIAutomationElement9 *iface, SAFEARRAY **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedAnnotationObjects(IUIAutomationElement9 *iface,
|
|
IUIAutomationElementArray **ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentLandmarkType(IUIAutomationElement9 *iface, LANDMARKTYPEID *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentLocalizedLandmarkType(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedLandmarkType(IUIAutomationElement9 *iface, LANDMARKTYPEID *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedLocalizedLandmarkType(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentFullDescription(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedFullDescription(IUIAutomationElement9 *iface, BSTR *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindFirstWithOptions(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root,
|
|
IUIAutomationElement **found)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindAllWithOptions(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root,
|
|
IUIAutomationElementArray **found)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindFirstWithOptionsBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req,
|
|
enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root, IUIAutomationElement **found)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_FindAllWithOptionsBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
|
IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req,
|
|
enum TreeTraversalOptions traversal_opts, IUIAutomationElement *root, IUIAutomationElementArray **found)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_GetCurrentMetadataValue(IUIAutomationElement9 *iface, int target_id,
|
|
METADATAID metadata_id, VARIANT *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentHeadingLevel(IUIAutomationElement9 *iface, HEADINGLEVELID *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedHeadingLevel(IUIAutomationElement9 *iface, HEADINGLEVELID *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CurrentIsDialog(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_element_get_CachedIsDialog(IUIAutomationElement9 *iface, BOOL *ret_val)
|
|
{
|
|
FIXME("%p: stub\n", iface);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IUIAutomationElement9Vtbl uia_element_vtbl = {
|
|
uia_element_QueryInterface,
|
|
uia_element_AddRef,
|
|
uia_element_Release,
|
|
uia_element_SetFocus,
|
|
uia_element_GetRuntimeId,
|
|
uia_element_FindFirst,
|
|
uia_element_FindAll,
|
|
uia_element_FindFirstBuildCache,
|
|
uia_element_FindAllBuildCache,
|
|
uia_element_BuildUpdatedCache,
|
|
uia_element_GetCurrentPropertyValue,
|
|
uia_element_GetCurrentPropertyValueEx,
|
|
uia_element_GetCachedPropertyValue,
|
|
uia_element_GetCachedPropertyValueEx,
|
|
uia_element_GetCurrentPatternAs,
|
|
uia_element_GetCachedPatternAs,
|
|
uia_element_GetCurrentPattern,
|
|
uia_element_GetCachedPattern,
|
|
uia_element_GetCachedParent,
|
|
uia_element_GetCachedChildren,
|
|
uia_element_get_CurrentProcessId,
|
|
uia_element_get_CurrentControlType,
|
|
uia_element_get_CurrentLocalizedControlType,
|
|
uia_element_get_CurrentName,
|
|
uia_element_get_CurrentAcceleratorKey,
|
|
uia_element_get_CurrentAccessKey,
|
|
uia_element_get_CurrentHasKeyboardFocus,
|
|
uia_element_get_CurrentIsKeyboardFocusable,
|
|
uia_element_get_CurrentIsEnabled,
|
|
uia_element_get_CurrentAutomationId,
|
|
uia_element_get_CurrentClassName,
|
|
uia_element_get_CurrentHelpText,
|
|
uia_element_get_CurrentCulture,
|
|
uia_element_get_CurrentIsControlElement,
|
|
uia_element_get_CurrentIsContentElement,
|
|
uia_element_get_CurrentIsPassword,
|
|
uia_element_get_CurrentNativeWindowHandle,
|
|
uia_element_get_CurrentItemType,
|
|
uia_element_get_CurrentIsOffscreen,
|
|
uia_element_get_CurrentOrientation,
|
|
uia_element_get_CurrentFrameworkId,
|
|
uia_element_get_CurrentIsRequiredForForm,
|
|
uia_element_get_CurrentItemStatus,
|
|
uia_element_get_CurrentBoundingRectangle,
|
|
uia_element_get_CurrentLabeledBy,
|
|
uia_element_get_CurrentAriaRole,
|
|
uia_element_get_CurrentAriaProperties,
|
|
uia_element_get_CurrentIsDataValidForForm,
|
|
uia_element_get_CurrentControllerFor,
|
|
uia_element_get_CurrentDescribedBy,
|
|
uia_element_get_CurrentFlowsTo,
|
|
uia_element_get_CurrentProviderDescription,
|
|
uia_element_get_CachedProcessId,
|
|
uia_element_get_CachedControlType,
|
|
uia_element_get_CachedLocalizedControlType,
|
|
uia_element_get_CachedName,
|
|
uia_element_get_CachedAcceleratorKey,
|
|
uia_element_get_CachedAccessKey,
|
|
uia_element_get_CachedHasKeyboardFocus,
|
|
uia_element_get_CachedIsKeyboardFocusable,
|
|
uia_element_get_CachedIsEnabled,
|
|
uia_element_get_CachedAutomationId,
|
|
uia_element_get_CachedClassName,
|
|
uia_element_get_CachedHelpText,
|
|
uia_element_get_CachedCulture,
|
|
uia_element_get_CachedIsControlElement,
|
|
uia_element_get_CachedIsContentElement,
|
|
uia_element_get_CachedIsPassword,
|
|
uia_element_get_CachedNativeWindowHandle,
|
|
uia_element_get_CachedItemType,
|
|
uia_element_get_CachedIsOffscreen,
|
|
uia_element_get_CachedOrientation,
|
|
uia_element_get_CachedFrameworkId,
|
|
uia_element_get_CachedIsRequiredForForm,
|
|
uia_element_get_CachedItemStatus,
|
|
uia_element_get_CachedBoundingRectangle,
|
|
uia_element_get_CachedLabeledBy,
|
|
uia_element_get_CachedAriaRole,
|
|
uia_element_get_CachedAriaProperties,
|
|
uia_element_get_CachedIsDataValidForForm,
|
|
uia_element_get_CachedControllerFor,
|
|
uia_element_get_CachedDescribedBy,
|
|
uia_element_get_CachedFlowsTo,
|
|
uia_element_get_CachedProviderDescription,
|
|
uia_element_GetClickablePoint,
|
|
uia_element_get_CurrentOptimizeForVisualContent,
|
|
uia_element_get_CachedOptimizeForVisualContent,
|
|
uia_element_get_CurrentLiveSetting,
|
|
uia_element_get_CachedLiveSetting,
|
|
uia_element_get_CurrentFlowsFrom,
|
|
uia_element_get_CachedFlowsFrom,
|
|
uia_element_ShowContextMenu,
|
|
uia_element_get_CurrentIsPeripheral,
|
|
uia_element_get_CachedIsPeripheral,
|
|
uia_element_get_CurrentPositionInSet,
|
|
uia_element_get_CurrentSizeOfSet,
|
|
uia_element_get_CurrentLevel,
|
|
uia_element_get_CurrentAnnotationTypes,
|
|
uia_element_get_CurrentAnnotationObjects,
|
|
uia_element_get_CachedPositionInSet,
|
|
uia_element_get_CachedSizeOfSet,
|
|
uia_element_get_CachedLevel,
|
|
uia_element_get_CachedAnnotationTypes,
|
|
uia_element_get_CachedAnnotationObjects,
|
|
uia_element_get_CurrentLandmarkType,
|
|
uia_element_get_CurrentLocalizedLandmarkType,
|
|
uia_element_get_CachedLandmarkType,
|
|
uia_element_get_CachedLocalizedLandmarkType,
|
|
uia_element_get_CurrentFullDescription,
|
|
uia_element_get_CachedFullDescription,
|
|
uia_element_FindFirstWithOptions,
|
|
uia_element_FindAllWithOptions,
|
|
uia_element_FindFirstWithOptionsBuildCache,
|
|
uia_element_FindAllWithOptionsBuildCache,
|
|
uia_element_GetCurrentMetadataValue,
|
|
uia_element_get_CurrentHeadingLevel,
|
|
uia_element_get_CachedHeadingLevel,
|
|
uia_element_get_CurrentIsDialog,
|
|
uia_element_get_CachedIsDialog,
|
|
};
|
|
|
|
static HRESULT create_uia_element(IUIAutomationElement **iface, BOOL from_cui8, HUIANODE node)
|
|
{
|
|
struct uia_element *element = heap_alloc_zero(sizeof(*element));
|
|
HRESULT hr;
|
|
|
|
*iface = NULL;
|
|
if (!element)
|
|
return E_OUTOFMEMORY;
|
|
|
|
element->IUIAutomationElement9_iface.lpVtbl = &uia_element_vtbl;
|
|
element->ref = 1;
|
|
element->from_cui8 = from_cui8;
|
|
element->node = node;
|
|
|
|
hr = CoCreateFreeThreadedMarshaler((IUnknown *)&element->IUIAutomationElement9_iface, &element->marshal);
|
|
if (FAILED(hr))
|
|
{
|
|
heap_free(element);
|
|
return hr;
|
|
}
|
|
|
|
*iface = (IUIAutomationElement *)&element->IUIAutomationElement9_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
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, LONG start_idx, SAFEARRAY *req_data, BSTR tree_struct)
|
|
{
|
|
IUIAutomationElement *element = NULL;
|
|
struct uia_element *elem_data;
|
|
HUIANODE node;
|
|
LONG idx[2];
|
|
HRESULT hr;
|
|
VARIANT v;
|
|
|
|
*iface = NULL;
|
|
|
|
VariantInit(&v);
|
|
idx[0] = start_idx;
|
|
idx[1] = 0;
|
|
hr = SafeArrayGetElement(req_data, idx, &v);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = UiaHUiaNodeFromVariant(&v, &node);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
VariantClear(&v);
|
|
|
|
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] = start_idx;
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomationTreeWalker interface.
|
|
*/
|
|
struct uia_tree_walker {
|
|
IUIAutomationTreeWalker IUIAutomationTreeWalker_iface;
|
|
LONG ref;
|
|
|
|
IUIAutomationCacheRequest *default_cache_req;
|
|
IUIAutomationCondition *nav_cond;
|
|
struct UiaCondition *cond_struct;
|
|
};
|
|
|
|
static inline struct uia_tree_walker *impl_from_IUIAutomationTreeWalker(IUIAutomationTreeWalker *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_tree_walker, IUIAutomationTreeWalker_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_QueryInterface(IUIAutomationTreeWalker *iface, REFIID riid, void **ppv)
|
|
{
|
|
if (IsEqualIID(riid, &IID_IUIAutomationTreeWalker) || IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomationTreeWalker_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_tree_walker_AddRef(IUIAutomationTreeWalker *iface)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
ULONG ref = InterlockedIncrement(&tree_walker->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", tree_walker, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_tree_walker_Release(IUIAutomationTreeWalker *iface)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
ULONG ref = InterlockedDecrement(&tree_walker->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", tree_walker, ref);
|
|
if (!ref)
|
|
{
|
|
if (tree_walker->default_cache_req)
|
|
IUIAutomationCacheRequest_Release(tree_walker->default_cache_req);
|
|
IUIAutomationCondition_Release(tree_walker->nav_cond);
|
|
heap_free(tree_walker);
|
|
}
|
|
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetParentElement(IUIAutomationTreeWalker *iface, IUIAutomationElement *elem,
|
|
IUIAutomationElement **parent)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
|
|
TRACE("%p, %p, %p\n", iface, elem, parent);
|
|
|
|
return IUIAutomationTreeWalker_GetParentElementBuildCache(iface, elem, tree_walker->default_cache_req, parent);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetFirstChildElement(IUIAutomationTreeWalker *iface, IUIAutomationElement *elem,
|
|
IUIAutomationElement **first)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
|
|
TRACE("%p, %p, %p\n", iface, elem, first);
|
|
|
|
return IUIAutomationTreeWalker_GetFirstChildElementBuildCache(iface, elem, tree_walker->default_cache_req, first);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetLastChildElement(IUIAutomationTreeWalker *iface, IUIAutomationElement *elem,
|
|
IUIAutomationElement **last)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
|
|
TRACE("%p, %p, %p\n", iface, elem, last);
|
|
|
|
return IUIAutomationTreeWalker_GetLastChildElementBuildCache(iface, elem, tree_walker->default_cache_req, last);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetNextSiblingElement(IUIAutomationTreeWalker *iface, IUIAutomationElement *elem,
|
|
IUIAutomationElement **next)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
|
|
TRACE("%p, %p, %p\n", iface, elem, next);
|
|
|
|
return IUIAutomationTreeWalker_GetNextSiblingElementBuildCache(iface, elem, tree_walker->default_cache_req, next);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetPreviousSiblingElement(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationElement **prev)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
|
|
TRACE("%p, %p, %p\n", iface, elem, prev);
|
|
|
|
return IUIAutomationTreeWalker_GetPreviousSiblingElementBuildCache(iface, elem, tree_walker->default_cache_req, prev);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_NormalizeElement(IUIAutomationTreeWalker *iface, IUIAutomationElement *elem,
|
|
IUIAutomationElement **normalized)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, normalized);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT uia_tree_walker_navigate(IUIAutomationTreeWalker *walker, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationElement *start_elem, int nav_dir, IUIAutomationElement **out_elem)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(walker);
|
|
struct UiaCacheRequest *cache_req_struct;
|
|
struct uia_element *element;
|
|
BSTR tree_struct = NULL;
|
|
SAFEARRAY *sa = NULL;
|
|
HRESULT hr;
|
|
|
|
if (!out_elem)
|
|
return E_POINTER;
|
|
|
|
*out_elem = NULL;
|
|
if (!start_elem)
|
|
return E_POINTER;
|
|
|
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
element = impl_from_IUIAutomationElement9((IUIAutomationElement9 *)start_elem);
|
|
hr = UiaNavigate(element->node, nav_dir, tree_walker->cond_struct, cache_req_struct, &sa, &tree_struct);
|
|
if (SUCCEEDED(hr) && sa)
|
|
{
|
|
hr = create_uia_element_from_cache_req(out_elem, element->from_cui8, cache_req_struct, 0, sa, tree_struct);
|
|
tree_struct = NULL;
|
|
}
|
|
|
|
SysFreeString(tree_struct);
|
|
SafeArrayDestroy(sa);
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetParentElementBuildCache(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **parent)
|
|
{
|
|
TRACE("%p, %p, %p, %p\n", iface, elem, cache_req, parent);
|
|
|
|
return uia_tree_walker_navigate(iface, cache_req, elem, NavigateDirection_Parent, parent);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetFirstChildElementBuildCache(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **first)
|
|
{
|
|
TRACE("%p, %p, %p, %p\n", iface, elem, cache_req, first);
|
|
|
|
return uia_tree_walker_navigate(iface, cache_req, elem, NavigateDirection_FirstChild, first);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetLastChildElementBuildCache(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **last)
|
|
{
|
|
TRACE("%p, %p, %p, %p\n", iface, elem, cache_req, last);
|
|
|
|
return uia_tree_walker_navigate(iface, cache_req, elem, NavigateDirection_LastChild, last);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetNextSiblingElementBuildCache(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **next)
|
|
{
|
|
TRACE("%p, %p, %p, %p\n", iface, elem, cache_req, next);
|
|
|
|
return uia_tree_walker_navigate(iface, cache_req, elem, NavigateDirection_NextSibling, next);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_GetPreviousSiblingElementBuildCache(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **prev)
|
|
{
|
|
TRACE("%p, %p, %p, %p\n", iface, elem, cache_req, prev);
|
|
|
|
return uia_tree_walker_navigate(iface, cache_req, elem, NavigateDirection_PreviousSibling, prev);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_NormalizeElementBuildCache(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationElement *elem, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **normalized)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, elem, cache_req, normalized);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_tree_walker_get_Condition(IUIAutomationTreeWalker *iface,
|
|
IUIAutomationCondition **condition)
|
|
{
|
|
struct uia_tree_walker *tree_walker = impl_from_IUIAutomationTreeWalker(iface);
|
|
|
|
TRACE("%p, %p\n", iface, condition);
|
|
|
|
if (!condition)
|
|
return E_POINTER;
|
|
|
|
IUIAutomationCondition_AddRef(tree_walker->nav_cond);
|
|
*condition = tree_walker->nav_cond;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static const IUIAutomationTreeWalkerVtbl uia_tree_walker_vtbl = {
|
|
uia_tree_walker_QueryInterface,
|
|
uia_tree_walker_AddRef,
|
|
uia_tree_walker_Release,
|
|
uia_tree_walker_GetParentElement,
|
|
uia_tree_walker_GetFirstChildElement,
|
|
uia_tree_walker_GetLastChildElement,
|
|
uia_tree_walker_GetNextSiblingElement,
|
|
uia_tree_walker_GetPreviousSiblingElement,
|
|
uia_tree_walker_NormalizeElement,
|
|
uia_tree_walker_GetParentElementBuildCache,
|
|
uia_tree_walker_GetFirstChildElementBuildCache,
|
|
uia_tree_walker_GetLastChildElementBuildCache,
|
|
uia_tree_walker_GetNextSiblingElementBuildCache,
|
|
uia_tree_walker_GetPreviousSiblingElementBuildCache,
|
|
uia_tree_walker_NormalizeElementBuildCache,
|
|
uia_tree_walker_get_Condition,
|
|
};
|
|
|
|
static HRESULT create_uia_tree_walker(IUIAutomationTreeWalker **out_tree_walker, IUIAutomationCondition *nav_cond)
|
|
{
|
|
struct uia_tree_walker *tree_walker;
|
|
struct UiaCondition *cond_struct;
|
|
HRESULT hr;
|
|
|
|
if (!out_tree_walker)
|
|
return E_POINTER;
|
|
|
|
*out_tree_walker = NULL;
|
|
hr = get_uia_condition_struct_from_iface(nav_cond, &cond_struct);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
tree_walker = heap_alloc_zero(sizeof(*tree_walker));
|
|
if (!tree_walker)
|
|
return E_OUTOFMEMORY;
|
|
|
|
tree_walker->IUIAutomationTreeWalker_iface.lpVtbl = &uia_tree_walker_vtbl;
|
|
tree_walker->ref = 1;
|
|
tree_walker->nav_cond = nav_cond;
|
|
IUIAutomationCondition_AddRef(nav_cond);
|
|
tree_walker->cond_struct = cond_struct;
|
|
|
|
hr = create_uia_cache_request_iface(&tree_walker->default_cache_req);
|
|
if (FAILED(hr))
|
|
{
|
|
IUIAutomationTreeWalker_Release(&tree_walker->IUIAutomationTreeWalker_iface);
|
|
return hr;
|
|
}
|
|
|
|
*out_tree_walker = &tree_walker->IUIAutomationTreeWalker_iface;
|
|
return S_OK;
|
|
}
|
|
|
|
/*
|
|
* IUIAutomation interface.
|
|
*/
|
|
struct uia_iface {
|
|
IUIAutomation6 IUIAutomation6_iface;
|
|
LONG ref;
|
|
|
|
BOOL is_cui8;
|
|
};
|
|
|
|
static inline struct uia_iface *impl_from_IUIAutomation6(IUIAutomation6 *iface)
|
|
{
|
|
return CONTAINING_RECORD(iface, struct uia_iface, IUIAutomation6_iface);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_QueryInterface(IUIAutomation6 *iface, REFIID riid, void **ppv)
|
|
{
|
|
struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
|
|
|
|
*ppv = NULL;
|
|
if (IsEqualIID(riid, &IID_IUIAutomation) || IsEqualIID(riid, &IID_IUnknown))
|
|
*ppv = iface;
|
|
else if (uia_iface->is_cui8 &&
|
|
(IsEqualIID(riid, &IID_IUIAutomation2) ||
|
|
IsEqualIID(riid, &IID_IUIAutomation3) ||
|
|
IsEqualIID(riid, &IID_IUIAutomation4) ||
|
|
IsEqualIID(riid, &IID_IUIAutomation5) ||
|
|
IsEqualIID(riid, &IID_IUIAutomation6)))
|
|
*ppv = iface;
|
|
else
|
|
return E_NOINTERFACE;
|
|
|
|
IUIAutomation6_AddRef(iface);
|
|
return S_OK;
|
|
}
|
|
|
|
static ULONG WINAPI uia_iface_AddRef(IUIAutomation6 *iface)
|
|
{
|
|
struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
|
|
ULONG ref = InterlockedIncrement(&uia_iface->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_iface, ref);
|
|
return ref;
|
|
}
|
|
|
|
static ULONG WINAPI uia_iface_Release(IUIAutomation6 *iface)
|
|
{
|
|
struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
|
|
ULONG ref = InterlockedDecrement(&uia_iface->ref);
|
|
|
|
TRACE("%p, refcount %ld\n", uia_iface, ref);
|
|
if (!ref)
|
|
heap_free(uia_iface);
|
|
return ref;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CompareElements(IUIAutomation6 *iface, IUIAutomationElement *elem1,
|
|
IUIAutomationElement *elem2, BOOL *match)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, elem1, elem2, match);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CompareRuntimeIds(IUIAutomation6 *iface, SAFEARRAY *rt_id1, SAFEARRAY *rt_id2,
|
|
BOOL *match)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, rt_id1, rt_id2, match);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_GetRootElement(IUIAutomation6 *iface, IUIAutomationElement **root)
|
|
{
|
|
struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
|
|
HUIANODE node;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", iface, root);
|
|
|
|
if (!root)
|
|
return E_POINTER;
|
|
|
|
*root = NULL;
|
|
hr = UiaGetRootNode(&node);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
return create_uia_element(root, uia_iface->is_cui8, node);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_ElementFromHandle(IUIAutomation6 *iface, UIA_HWND hwnd, IUIAutomationElement **out_elem)
|
|
{
|
|
struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
|
|
HUIANODE node;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p, %p\n", iface, hwnd, out_elem);
|
|
|
|
hr = UiaNodeFromHandle((HWND)hwnd, &node);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
return create_uia_element(out_elem, uia_iface->is_cui8, node);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_ElementFromPoint(IUIAutomation6 *iface, POINT pt, IUIAutomationElement **out_elem)
|
|
{
|
|
FIXME("%p, %s, %p: stub\n", iface, wine_dbgstr_point(&pt), out_elem);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT uia_get_focused_element(IUIAutomation6 *iface, IUIAutomationCacheRequest *cache_req,
|
|
BOOL use_default_cache_req, IUIAutomationElement **out_elem)
|
|
{
|
|
struct uia_iface *uia_iface = impl_from_IUIAutomation6(iface);
|
|
struct UiaCacheRequest *cache_req_struct;
|
|
BSTR tree_struct;
|
|
SAFEARRAY *sa;
|
|
HRESULT hr;
|
|
|
|
if (!out_elem)
|
|
return E_POINTER;
|
|
|
|
*out_elem = NULL;
|
|
if (use_default_cache_req)
|
|
{
|
|
hr = create_uia_cache_request_iface(&cache_req);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
}
|
|
|
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = UiaNodeFromFocus(cache_req_struct, &sa, &tree_struct);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (!sa)
|
|
{
|
|
/*
|
|
* Failure to get a focused element returns E_FAIL from the BuildCache
|
|
* method, but UIA_E_ELEMENTNOTAVAILABLE from the default cache
|
|
* request method.
|
|
*/
|
|
hr = use_default_cache_req ? UIA_E_ELEMENTNOTAVAILABLE : E_FAIL;
|
|
SysFreeString(tree_struct);
|
|
goto exit;
|
|
}
|
|
|
|
hr = create_uia_element_from_cache_req(out_elem, uia_iface->is_cui8, cache_req_struct, 0, sa, tree_struct);
|
|
SafeArrayDestroy(sa);
|
|
}
|
|
|
|
exit:
|
|
if (use_default_cache_req)
|
|
IUIAutomationCacheRequest_Release(cache_req);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_GetFocusedElement(IUIAutomation6 *iface, IUIAutomationElement **out_elem)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_elem);
|
|
|
|
return uia_get_focused_element(iface, NULL, TRUE, out_elem);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_GetRootElementBuildCache(IUIAutomation6 *iface, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationElement **out_root)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, cache_req, out_root);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_ElementFromHandleBuildCache(IUIAutomation6 *iface, UIA_HWND hwnd,
|
|
IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, hwnd, cache_req, out_elem);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_ElementFromPointBuildCache(IUIAutomation6 *iface, POINT pt,
|
|
IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem)
|
|
{
|
|
FIXME("%p, %s, %p, %p: stub\n", iface, wine_dbgstr_point(&pt), cache_req, out_elem);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_GetFocusedElementBuildCache(IUIAutomation6 *iface,
|
|
IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem)
|
|
{
|
|
TRACE("%p, %p, %p\n", iface, cache_req, out_elem);
|
|
|
|
return uia_get_focused_element(iface, cache_req, FALSE, out_elem);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateTreeWalker(IUIAutomation6 *iface, IUIAutomationCondition *cond,
|
|
IUIAutomationTreeWalker **out_walker)
|
|
{
|
|
TRACE("%p, %p, %p\n", iface, cond, out_walker);
|
|
|
|
return create_uia_tree_walker(out_walker, cond);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ControlViewWalker(IUIAutomation6 *iface, IUIAutomationTreeWalker **out_walker)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_walker);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ContentViewWalker(IUIAutomation6 *iface, IUIAutomationTreeWalker **out_walker)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_walker);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_RawViewWalker(IUIAutomation6 *iface, IUIAutomationTreeWalker **out_walker)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_walker);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_RawViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_condition);
|
|
|
|
return create_uia_bool_condition_iface(out_condition, ConditionType_True);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ControlViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_condition);
|
|
|
|
return create_control_view_condition_iface(out_condition);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ContentViewCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateCacheRequest(IUIAutomation6 *iface, IUIAutomationCacheRequest **out_cache_req)
|
|
{
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", iface, out_cache_req);
|
|
|
|
hr = create_uia_cache_request_iface(out_cache_req);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IUIAutomationCacheRequest_AddProperty(*out_cache_req, UIA_RuntimeIdPropertyId);
|
|
if (FAILED(hr))
|
|
{
|
|
IUIAutomationCacheRequest_Release(*out_cache_req);
|
|
*out_cache_req = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateTrueCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_condition);
|
|
|
|
return create_uia_bool_condition_iface(out_condition, ConditionType_True);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateFalseCondition(IUIAutomation6 *iface, IUIAutomationCondition **out_condition)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_condition);
|
|
|
|
return create_uia_bool_condition_iface(out_condition, ConditionType_False);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreatePropertyCondition(IUIAutomation6 *iface, PROPERTYID prop_id, VARIANT val,
|
|
IUIAutomationCondition **out_condition)
|
|
{
|
|
TRACE("%p, %d, %s, %p\n", iface, prop_id, debugstr_variant(&val), out_condition);
|
|
|
|
return create_uia_property_condition_iface(out_condition, prop_id, val, PropertyConditionFlags_None);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreatePropertyConditionEx(IUIAutomation6 *iface, PROPERTYID prop_id, VARIANT val,
|
|
enum PropertyConditionFlags flags, IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %d, %s, %#x, %p: stub\n", iface, prop_id, debugstr_variant(&val), flags, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateAndCondition(IUIAutomation6 *iface, IUIAutomationCondition *cond1,
|
|
IUIAutomationCondition *cond2, IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, cond1, cond2, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateAndConditionFromArray(IUIAutomation6 *iface, SAFEARRAY *conds,
|
|
IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, conds, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateAndConditionFromNativeArray(IUIAutomation6 *iface, IUIAutomationCondition **conds,
|
|
int conds_count, IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %p, %d, %p: stub\n", iface, conds, conds_count, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateOrCondition(IUIAutomation6 *iface, IUIAutomationCondition *cond1,
|
|
IUIAutomationCondition *cond2, IUIAutomationCondition **out_condition)
|
|
{
|
|
IUIAutomationCondition *cond_arr[2] = { cond1, cond2 };
|
|
|
|
TRACE("%p, %p, %p, %p\n", iface, cond1, cond2, out_condition);
|
|
|
|
return create_uia_or_condition_iface(out_condition, cond_arr, ARRAY_SIZE(cond_arr));
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateOrConditionFromArray(IUIAutomation6 *iface, SAFEARRAY *conds,
|
|
IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, conds, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateOrConditionFromNativeArray(IUIAutomation6 *iface, IUIAutomationCondition **conds,
|
|
int conds_count, IUIAutomationCondition **out_condition)
|
|
{
|
|
FIXME("%p, %p, %d, %p: stub\n", iface, conds, conds_count, out_condition);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateNotCondition(IUIAutomation6 *iface, IUIAutomationCondition *cond,
|
|
IUIAutomationCondition **out_condition)
|
|
{
|
|
TRACE("%p, %p, %p\n", iface, cond, out_condition);
|
|
|
|
return create_uia_not_condition_iface(out_condition, cond);
|
|
}
|
|
|
|
static HRESULT uia_add_com_event_handler(IUIAutomation6 *iface, EVENTID event_id, IUIAutomationElement *elem,
|
|
enum TreeScope scope, IUIAutomationCacheRequest *cache_req, REFIID handler_riid, IUnknown *handler_unk)
|
|
{
|
|
struct UiaCacheRequest *cache_req_struct;
|
|
struct uia_com_event *com_event = NULL;
|
|
SAFEARRAY *runtime_id = NULL;
|
|
struct uia_element *element;
|
|
IUnknown *handler_iface;
|
|
HRESULT hr;
|
|
|
|
element = impl_from_IUIAutomationElement9((IUIAutomationElement9 *)elem);
|
|
hr = UiaGetRuntimeId(element->node, &runtime_id);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!cache_req)
|
|
{
|
|
hr = create_uia_cache_request_iface(&cache_req);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
}
|
|
else
|
|
IUIAutomationCacheRequest_AddRef(cache_req);
|
|
|
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
if (!(com_event = heap_alloc_zero(sizeof(*com_event))))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
goto exit;
|
|
}
|
|
|
|
com_event->from_cui8 = element->from_cui8;
|
|
list_init(&com_event->event_handler_map_list_entry);
|
|
|
|
hr = IUnknown_QueryInterface(handler_unk, handler_riid, (void **)&handler_iface);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = register_interface_in_git(handler_iface, handler_riid, &com_event->git_cookie);
|
|
IUnknown_Release(handler_iface);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = uia_add_clientside_event(element->node, event_id, scope, NULL, 0, cache_req_struct, runtime_id,
|
|
uia_com_event_callback, (void *)com_event, &com_event->event);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
hr = uia_event_handlers_add_handler(handler_unk, runtime_id, event_id, com_event);
|
|
|
|
exit:
|
|
if (FAILED(hr) && com_event)
|
|
uia_event_handler_destroy(com_event);
|
|
if (cache_req)
|
|
IUIAutomationCacheRequest_Release(cache_req);
|
|
SafeArrayDestroy(runtime_id);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddAutomationEventHandler(IUIAutomation6 *iface, EVENTID event_id,
|
|
IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationEventHandler *handler)
|
|
{
|
|
IUnknown *handler_unk;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %d, %p, %#x, %p, %p\n", iface, event_id, elem, scope, cache_req, handler);
|
|
|
|
if (!elem || !handler)
|
|
return E_POINTER;
|
|
|
|
if (event_id == UIA_AutomationFocusChangedEventId)
|
|
return E_INVALIDARG;
|
|
|
|
hr = IUIAutomationEventHandler_QueryInterface(handler, &IID_IUnknown, (void **)&handler_unk);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = uia_add_com_event_handler(iface, event_id, elem, scope, cache_req, &IID_IUIAutomationEventHandler, handler_unk);
|
|
IUnknown_Release(handler_unk);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT uia_remove_com_event_handler(EVENTID event_id, IUIAutomationElement *elem, IUnknown *handler_unk)
|
|
{
|
|
struct uia_element *element;
|
|
SAFEARRAY *runtime_id;
|
|
HRESULT hr;
|
|
|
|
element = impl_from_IUIAutomationElement9((IUIAutomationElement9 *)elem);
|
|
hr = UiaGetRuntimeId(element->node, &runtime_id);
|
|
if (FAILED(hr) || !runtime_id)
|
|
return hr;
|
|
|
|
uia_event_handlers_remove_handlers(handler_unk, runtime_id, event_id);
|
|
SafeArrayDestroy(runtime_id);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveAutomationEventHandler(IUIAutomation6 *iface, EVENTID event_id,
|
|
IUIAutomationElement *elem, IUIAutomationEventHandler *handler)
|
|
{
|
|
IUnknown *handler_unk;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %d, %p, %p\n", iface, event_id, elem, handler);
|
|
|
|
if (!elem || !handler)
|
|
return S_OK;
|
|
|
|
hr = IUIAutomationEventHandler_QueryInterface(handler, &IID_IUnknown, (void **)&handler_unk);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = uia_remove_com_event_handler(event_id, elem, handler_unk);
|
|
IUnknown_Release(handler_unk);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddPropertyChangedEventHandlerNativeArray(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationPropertyChangedEventHandler *handler, PROPERTYID *props, int props_count)
|
|
{
|
|
FIXME("%p, %p, %#x, %p, %p, %p, %d: stub\n", iface, elem, scope, cache_req, handler, props, props_count);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddPropertyChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationPropertyChangedEventHandler *handler, SAFEARRAY *props)
|
|
{
|
|
FIXME("%p, %p, %#x, %p, %p, %p: stub\n", iface, elem, scope, cache_req, handler, props);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemovePropertyChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, IUIAutomationPropertyChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddStructureChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationStructureChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %#x, %p, %p: stub\n", iface, elem, scope, cache_req, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveStructureChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, IUIAutomationStructureChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddFocusChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationCacheRequest *cache_req, IUIAutomationFocusChangedEventHandler *handler)
|
|
{
|
|
IUIAutomationElement *elem;
|
|
IUnknown *handler_unk;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p, %p\n", iface, cache_req, handler);
|
|
|
|
if (!handler)
|
|
return E_POINTER;
|
|
|
|
hr = IUIAutomationFocusChangedEventHandler_QueryInterface(handler, &IID_IUnknown, (void **)&handler_unk);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IUIAutomation6_GetRootElement(iface, &elem);
|
|
if (FAILED(hr))
|
|
{
|
|
IUnknown_Release(handler_unk);
|
|
return hr;
|
|
}
|
|
|
|
hr = uia_add_com_event_handler(iface, UIA_AutomationFocusChangedEventId, elem, TreeScope_SubTree, cache_req,
|
|
&IID_IUIAutomationFocusChangedEventHandler, handler_unk);
|
|
IUIAutomationElement_Release(elem);
|
|
IUnknown_Release(handler_unk);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveFocusChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationFocusChangedEventHandler *handler)
|
|
{
|
|
IUIAutomationElement *elem;
|
|
IUnknown *handler_unk;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p\n", iface, handler);
|
|
|
|
hr = IUIAutomationFocusChangedEventHandler_QueryInterface(handler, &IID_IUnknown, (void **)&handler_unk);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
hr = IUIAutomation6_GetRootElement(iface, &elem);
|
|
if (FAILED(hr))
|
|
{
|
|
IUnknown_Release(handler_unk);
|
|
return hr;
|
|
}
|
|
|
|
hr = uia_remove_com_event_handler(UIA_AutomationFocusChangedEventId, elem, handler_unk);
|
|
IUIAutomationElement_Release(elem);
|
|
IUnknown_Release(handler_unk);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveAllEventHandlers(IUIAutomation6 *iface)
|
|
{
|
|
struct uia_event_handler_map_entry *entry, *cursor;
|
|
|
|
TRACE("%p\n", iface);
|
|
|
|
EnterCriticalSection(&com_event_handlers_cs);
|
|
if (!com_event_handlers.handler_count)
|
|
goto exit;
|
|
|
|
RB_FOR_EACH_ENTRY_DESTRUCTOR(entry, cursor, &com_event_handlers.handler_map, struct uia_event_handler_map_entry, entry)
|
|
{
|
|
uia_event_handler_map_entry_destroy(entry);
|
|
}
|
|
|
|
exit:
|
|
LeaveCriticalSection(&com_event_handlers_cs);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_IntNativeArrayToSafeArray(IUIAutomation6 *iface, int *arr, int arr_count,
|
|
SAFEARRAY **out_sa)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
SAFEARRAY *sa;
|
|
int *sa_arr;
|
|
|
|
TRACE("%p, %p, %d, %p\n", iface, arr, arr_count, out_sa);
|
|
|
|
if (!out_sa || !arr || !arr_count)
|
|
return E_INVALIDARG;
|
|
|
|
*out_sa = NULL;
|
|
if (!(sa = SafeArrayCreateVector(VT_I4, 0, arr_count)))
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = SafeArrayAccessData(sa, (void **)&sa_arr);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
memcpy(sa_arr, arr, sizeof(*arr) * arr_count);
|
|
hr = SafeArrayUnaccessData(sa);
|
|
if (SUCCEEDED(hr))
|
|
*out_sa = sa;
|
|
|
|
exit:
|
|
if (FAILED(hr))
|
|
SafeArrayDestroy(sa);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_IntSafeArrayToNativeArray(IUIAutomation6 *iface, SAFEARRAY *sa, int **out_arr,
|
|
int *out_arr_count)
|
|
{
|
|
LONG lbound, elems;
|
|
int *arr, *sa_arr;
|
|
VARTYPE vt;
|
|
HRESULT hr;
|
|
|
|
TRACE("%p, %p, %p, %p\n", iface, sa, out_arr, out_arr_count);
|
|
|
|
if (!sa || !out_arr || !out_arr_count)
|
|
return E_INVALIDARG;
|
|
|
|
*out_arr = NULL;
|
|
hr = SafeArrayGetVartype(sa, &vt);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (vt != VT_I4)
|
|
return E_INVALIDARG;
|
|
|
|
hr = get_safearray_bounds(sa, &lbound, &elems);
|
|
if (FAILED(hr))
|
|
return hr;
|
|
|
|
if (!(arr = CoTaskMemAlloc(elems * sizeof(*arr))))
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = SafeArrayAccessData(sa, (void **)&sa_arr);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
memcpy(arr, sa_arr, sizeof(*arr) * elems);
|
|
hr = SafeArrayUnaccessData(sa);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
*out_arr = arr;
|
|
*out_arr_count = elems;
|
|
|
|
exit:
|
|
if (FAILED(hr))
|
|
CoTaskMemFree(arr);
|
|
|
|
return hr;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RectToVariant(IUIAutomation6 *iface, RECT rect, VARIANT *out_var)
|
|
{
|
|
FIXME("%p, %s, %p: stub\n", iface, wine_dbgstr_rect(&rect), out_var);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_VariantToRect(IUIAutomation6 *iface, VARIANT var, RECT *out_rect)
|
|
{
|
|
FIXME("%p, %s, %p: stub\n", iface, debugstr_variant(&var), out_rect);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_SafeArrayToRectNativeArray(IUIAutomation6 *iface, SAFEARRAY *sa, RECT **out_rect_arr,
|
|
int *out_rect_arr_count)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, sa, out_rect_arr, out_rect_arr_count);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CreateProxyFactoryEntry(IUIAutomation6 *iface, IUIAutomationProxyFactory *factory,
|
|
IUIAutomationProxyFactoryEntry **out_entry)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, factory, out_entry);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ProxyFactoryMapping(IUIAutomation6 *iface,
|
|
IUIAutomationProxyFactoryMapping **out_factory_map)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_factory_map);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_GetPropertyProgrammaticName(IUIAutomation6 *iface, PROPERTYID prop_id, BSTR *out_name)
|
|
{
|
|
FIXME("%p, %d, %p: stub\n", iface, prop_id, out_name);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_GetPatternProgrammaticName(IUIAutomation6 *iface, PATTERNID pattern_id, BSTR *out_name)
|
|
{
|
|
FIXME("%p, %d, %p: stub\n", iface, pattern_id, out_name);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_PollForPotentialSupportedPatterns(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
SAFEARRAY **out_pattern_ids, SAFEARRAY **out_pattern_names)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, elem, out_pattern_ids, out_pattern_names);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_PollForPotentialSupportedProperties(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
SAFEARRAY **out_prop_ids, SAFEARRAY **out_prop_names)
|
|
{
|
|
FIXME("%p, %p, %p, %p: stub\n", iface, elem, out_prop_ids, out_prop_names);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_CheckNotSupported(IUIAutomation6 *iface, VARIANT in_val, BOOL *match)
|
|
{
|
|
IUnknown *unk;
|
|
|
|
TRACE("%p, %s, %p\n", iface, debugstr_variant(&in_val), match);
|
|
|
|
*match = FALSE;
|
|
UiaGetReservedNotSupportedValue(&unk);
|
|
if (V_VT(&in_val) == VT_UNKNOWN && (V_UNKNOWN(&in_val) == unk))
|
|
*match = TRUE;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ReservedNotSupportedValue(IUIAutomation6 *iface, IUnknown **out_unk)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_unk);
|
|
|
|
return UiaGetReservedNotSupportedValue(out_unk);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ReservedMixedAttributeValue(IUIAutomation6 *iface, IUnknown **out_unk)
|
|
{
|
|
TRACE("%p, %p\n", iface, out_unk);
|
|
|
|
return UiaGetReservedMixedAttributeValue(out_unk);
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_ElementFromIAccessible(IUIAutomation6 *iface, IAccessible *acc, int cid,
|
|
IUIAutomationElement **out_elem)
|
|
{
|
|
FIXME("%p, %p, %d, %p: stub\n", iface, acc, cid, out_elem);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_ElementFromIAccessibleBuildCache(IUIAutomation6 *iface, IAccessible *acc, int cid,
|
|
IUIAutomationCacheRequest *cache_req, IUIAutomationElement **out_elem)
|
|
{
|
|
FIXME("%p, %p, %d, %p, %p: stub\n", iface, acc, cid, cache_req, out_elem);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/* IUIAutomation2 methods */
|
|
static HRESULT WINAPI uia_iface_get_AutoSetFocus(IUIAutomation6 *iface, BOOL *out_auto_set_focus)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_auto_set_focus);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_put_AutoSetFocus(IUIAutomation6 *iface, BOOL auto_set_focus)
|
|
{
|
|
FIXME("%p, %d: stub\n", iface, auto_set_focus);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ConnectionTimeout(IUIAutomation6 *iface, DWORD *out_timeout)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_timeout);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_put_ConnectionTimeout(IUIAutomation6 *iface, DWORD timeout)
|
|
{
|
|
FIXME("%p, %ld: stub\n", iface, timeout);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_TransactionTimeout(IUIAutomation6 *iface, DWORD *out_timeout)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_timeout);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_put_TransactionTimeout(IUIAutomation6 *iface, DWORD timeout)
|
|
{
|
|
FIXME("%p, %ld: stub\n", iface, timeout);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/* IUIAutomation3 methods */
|
|
static HRESULT WINAPI uia_iface_AddTextEditTextChangedEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
enum TreeScope scope, enum TextEditChangeType change_type, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationTextEditTextChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %#x, %d, %p, %p: stub\n", iface, elem, scope, change_type, cache_req, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveTextEditTextChangedEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
IUIAutomationTextEditTextChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/* IUIAutomation4 methods */
|
|
static HRESULT WINAPI uia_iface_AddChangesEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
enum TreeScope scope, int *change_types, int change_types_count, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationChangesEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %#x, %p, %d, %p, %p: stub\n", iface, elem, scope, change_types, change_types_count, cache_req,
|
|
handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveChangesEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
IUIAutomationChangesEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/* IUIAutomation5 methods */
|
|
static HRESULT WINAPI uia_iface_AddNotificationEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
enum TreeScope scope, IUIAutomationCacheRequest *cache_req, IUIAutomationNotificationEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %#x, %p, %p: stub\n", iface, elem, scope, cache_req, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveNotificationEventHandler(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
IUIAutomationNotificationEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
/* IUIAutomation6 methods */
|
|
static HRESULT WINAPI uia_iface_CreateEventHandlerGroup(IUIAutomation6 *iface,
|
|
IUIAutomationEventHandlerGroup **out_handler_group)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_handler_group);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddEventHandlerGroup(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
IUIAutomationEventHandlerGroup *handler_group)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler_group);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveEventHandlerGroup(IUIAutomation6 *iface, IUIAutomationElement *elem,
|
|
IUIAutomationEventHandlerGroup *handler_group)
|
|
{
|
|
FIXME("%p, %p, %p: stub\n", iface, elem, handler_group);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_ConnectionRecoveryBehavior(IUIAutomation6 *iface,
|
|
enum ConnectionRecoveryBehaviorOptions *out_conn_recovery_opts)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_conn_recovery_opts);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_put_ConnectionRecoveryBehavior(IUIAutomation6 *iface,
|
|
enum ConnectionRecoveryBehaviorOptions conn_recovery_opts)
|
|
{
|
|
FIXME("%p, %#x: stub\n", iface, conn_recovery_opts);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_get_CoalesceEvents(IUIAutomation6 *iface,
|
|
enum CoalesceEventsOptions *out_coalesce_events_opts)
|
|
{
|
|
FIXME("%p, %p: stub\n", iface, out_coalesce_events_opts);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_put_CoalesceEvents(IUIAutomation6 *iface,
|
|
enum CoalesceEventsOptions coalesce_events_opts)
|
|
{
|
|
FIXME("%p, %#x: stub\n", iface, coalesce_events_opts);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_AddActiveTextPositionChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, enum TreeScope scope, IUIAutomationCacheRequest *cache_req,
|
|
IUIAutomationActiveTextPositionChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %#x, %p, %p: stub\n", iface, elem, scope, cache_req, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static HRESULT WINAPI uia_iface_RemoveActiveTextPositionChangedEventHandler(IUIAutomation6 *iface,
|
|
IUIAutomationElement *elem, IUIAutomationActiveTextPositionChangedEventHandler *handler)
|
|
{
|
|
FIXME("%p, %p, %p\n", iface, elem, handler);
|
|
return E_NOTIMPL;
|
|
}
|
|
|
|
static const IUIAutomation6Vtbl uia_iface_vtbl = {
|
|
uia_iface_QueryInterface,
|
|
uia_iface_AddRef,
|
|
uia_iface_Release,
|
|
/* IUIAutomation methods */
|
|
uia_iface_CompareElements,
|
|
uia_iface_CompareRuntimeIds,
|
|
uia_iface_GetRootElement,
|
|
uia_iface_ElementFromHandle,
|
|
uia_iface_ElementFromPoint,
|
|
uia_iface_GetFocusedElement,
|
|
uia_iface_GetRootElementBuildCache,
|
|
uia_iface_ElementFromHandleBuildCache,
|
|
uia_iface_ElementFromPointBuildCache,
|
|
uia_iface_GetFocusedElementBuildCache,
|
|
uia_iface_CreateTreeWalker,
|
|
uia_iface_get_ControlViewWalker,
|
|
uia_iface_get_ContentViewWalker,
|
|
uia_iface_get_RawViewWalker,
|
|
uia_iface_get_RawViewCondition,
|
|
uia_iface_get_ControlViewCondition,
|
|
uia_iface_get_ContentViewCondition,
|
|
uia_iface_CreateCacheRequest,
|
|
uia_iface_CreateTrueCondition,
|
|
uia_iface_CreateFalseCondition,
|
|
uia_iface_CreatePropertyCondition,
|
|
uia_iface_CreatePropertyConditionEx,
|
|
uia_iface_CreateAndCondition,
|
|
uia_iface_CreateAndConditionFromArray,
|
|
uia_iface_CreateAndConditionFromNativeArray,
|
|
uia_iface_CreateOrCondition,
|
|
uia_iface_CreateOrConditionFromArray,
|
|
uia_iface_CreateOrConditionFromNativeArray,
|
|
uia_iface_CreateNotCondition,
|
|
uia_iface_AddAutomationEventHandler,
|
|
uia_iface_RemoveAutomationEventHandler,
|
|
uia_iface_AddPropertyChangedEventHandlerNativeArray,
|
|
uia_iface_AddPropertyChangedEventHandler,
|
|
uia_iface_RemovePropertyChangedEventHandler,
|
|
uia_iface_AddStructureChangedEventHandler,
|
|
uia_iface_RemoveStructureChangedEventHandler,
|
|
uia_iface_AddFocusChangedEventHandler,
|
|
uia_iface_RemoveFocusChangedEventHandler,
|
|
uia_iface_RemoveAllEventHandlers,
|
|
uia_iface_IntNativeArrayToSafeArray,
|
|
uia_iface_IntSafeArrayToNativeArray,
|
|
uia_iface_RectToVariant,
|
|
uia_iface_VariantToRect,
|
|
uia_iface_SafeArrayToRectNativeArray,
|
|
uia_iface_CreateProxyFactoryEntry,
|
|
uia_iface_get_ProxyFactoryMapping,
|
|
uia_iface_GetPropertyProgrammaticName,
|
|
uia_iface_GetPatternProgrammaticName,
|
|
uia_iface_PollForPotentialSupportedPatterns,
|
|
uia_iface_PollForPotentialSupportedProperties,
|
|
uia_iface_CheckNotSupported,
|
|
uia_iface_get_ReservedNotSupportedValue,
|
|
uia_iface_get_ReservedMixedAttributeValue,
|
|
uia_iface_ElementFromIAccessible,
|
|
uia_iface_ElementFromIAccessibleBuildCache,
|
|
/* IUIAutomation2 methods */
|
|
uia_iface_get_AutoSetFocus,
|
|
uia_iface_put_AutoSetFocus,
|
|
uia_iface_get_ConnectionTimeout,
|
|
uia_iface_put_ConnectionTimeout,
|
|
uia_iface_get_TransactionTimeout,
|
|
uia_iface_put_TransactionTimeout,
|
|
/* IUIAutomation3 methods */
|
|
uia_iface_AddTextEditTextChangedEventHandler,
|
|
uia_iface_RemoveTextEditTextChangedEventHandler,
|
|
/* IUIAutomation4 methods */
|
|
uia_iface_AddChangesEventHandler,
|
|
uia_iface_RemoveChangesEventHandler,
|
|
/* IUIAutomation5 methods */
|
|
uia_iface_AddNotificationEventHandler,
|
|
uia_iface_RemoveNotificationEventHandler,
|
|
/* IUIAutomation6 methods */
|
|
uia_iface_CreateEventHandlerGroup,
|
|
uia_iface_AddEventHandlerGroup,
|
|
uia_iface_RemoveEventHandlerGroup,
|
|
uia_iface_get_ConnectionRecoveryBehavior,
|
|
uia_iface_put_ConnectionRecoveryBehavior,
|
|
uia_iface_get_CoalesceEvents,
|
|
uia_iface_put_CoalesceEvents,
|
|
uia_iface_AddActiveTextPositionChangedEventHandler,
|
|
uia_iface_RemoveActiveTextPositionChangedEventHandler,
|
|
};
|
|
|
|
HRESULT create_uia_iface(IUnknown **iface, BOOL is_cui8)
|
|
{
|
|
struct uia_iface *uia;
|
|
|
|
uia = heap_alloc_zero(sizeof(*uia));
|
|
if (!uia)
|
|
return E_OUTOFMEMORY;
|
|
|
|
uia->IUIAutomation6_iface.lpVtbl = &uia_iface_vtbl;
|
|
uia->is_cui8 = is_cui8;
|
|
uia->ref = 1;
|
|
|
|
*iface = (IUnknown *)&uia->IUIAutomation6_iface;
|
|
return S_OK;
|
|
}
|