2 * Copyright 2022 Connor McAdams for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "uiautomation.h"
22 #include "uia_classes.h"
23 #include "wine/list.h"
24 #include "wine/rbtree.h"
27 extern HMODULE huia_module
;
33 PROP_TYPE_PATTERN_PROP
,
37 * HUIANODEs that have an associated HWND are able to pull data from up to 4
38 * different providers:
40 * - Override providers are used to override values from all other providers.
41 * - Main providers are the base provider for an HUIANODE.
42 * - Nonclient providers are used to represent the nonclient area of the HWND.
43 * - HWND providers are used to represent data from the HWND as a whole, such
44 * as the bounding box.
46 * When a property is requested from the node, each provider is queried in
47 * descending order starting with the override provider until either one
48 * returns a property or there are no more providers to query.
50 enum uia_node_prov_type
{
59 NODE_FLAG_IGNORE_CLIENTSIDE_HWND_PROVS
= 0x01,
60 NODE_FLAG_NO_PREPARE
= 0x02,
61 NODE_FLAG_IGNORE_COM_THREADING
= 0x04,
65 IWineUiaNode IWineUiaNode_iface
;
68 IWineUiaProvider
*prov
[PROV_TYPE_COUNT
];
69 DWORD git_cookie
[PROV_TYPE_COUNT
];
78 int creator_prov_type
;
79 BOOL ignore_com_threading
;
80 BOOL ignore_clientside_hwnd_provs
;
82 struct list prov_thread_list_entry
;
83 struct list node_map_list_entry
;
84 struct uia_provider_thread_map_entry
*map
;
87 static inline struct uia_node
*impl_from_IWineUiaNode(IWineUiaNode
*iface
)
89 return CONTAINING_RECORD(iface
, struct uia_node
, IWineUiaNode_iface
);
93 IWineUiaProvider IWineUiaProvider_iface
;
96 IRawElementProviderSimple
*elprov
;
97 BOOL refuse_hwnd_node_providers
;
98 BOOL return_nested_node
;
99 BOOL parent_check_ran
;
104 static inline struct uia_provider
*impl_from_IWineUiaProvider(IWineUiaProvider
*iface
)
106 return CONTAINING_RECORD(iface
, struct uia_provider
, IWineUiaProvider_iface
);
109 struct uia_event_args
111 struct UiaEventArgs simple_args
;
115 enum uia_event_type
{
116 EVENT_TYPE_CLIENTSIDE
,
117 EVENT_TYPE_SERVERSIDE
,
122 IWineUiaEvent IWineUiaEvent_iface
;
125 BOOL desktop_subtree_event
;
126 SAFEARRAY
*runtime_id
;
130 IWineUiaEventAdviser
**event_advisers
;
131 int event_advisers_count
;
132 SIZE_T event_advisers_arr_size
;
134 struct list event_list_entry
;
135 struct uia_event_map_entry
*event_map_entry
;
143 struct UiaCacheRequest cache_req
;
144 HRESULT (*event_callback
)(struct uia_event
*, struct uia_event_args
*, SAFEARRAY
*, BSTR
);
147 struct rb_tree win_event_hwnd_map
;
148 BOOL event_thread_started
;
152 IWineUiaEvent
*event_iface
;
154 struct rb_entry serverside_event_entry
;
160 typedef HRESULT
UiaWineEventCallback(struct uia_event
*, struct uia_event_args
*, SAFEARRAY
*, BSTR
);
161 typedef HRESULT
UiaWineEventForEachCallback(struct uia_event
*, void *);
163 static inline void variant_init_bool(VARIANT
*v
, BOOL val
)
166 V_BOOL(v
) = val
? VARIANT_TRUE
: VARIANT_FALSE
;
169 static inline void variant_init_i4(VARIANT
*v
, int val
)
175 static inline void get_variant_for_node(HUIANODE node
, VARIANT
*v
)
179 V_I8(v
) = (UINT64
)node
;
182 V_I4(v
) = (UINT32
)node
;
186 static inline BOOL
uia_array_reserve(void **elements
, SIZE_T
*capacity
, SIZE_T count
, SIZE_T size
)
188 SIZE_T max_capacity
, new_capacity
;
191 if (count
<= *capacity
)
194 max_capacity
= ~(SIZE_T
)0 / size
;
195 if (count
> max_capacity
)
198 new_capacity
= max(1, *capacity
);
199 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
201 if (new_capacity
< count
)
202 new_capacity
= count
;
204 new_elements
= _recalloc(*elements
, new_capacity
, size
);
208 *elements
= new_elements
;
209 *capacity
= new_capacity
;
213 enum provider_method_flags
{
214 PROV_METHOD_FLAG_RETURN_NODE_LRES
= 0x0001,
218 int get_node_provider_type_at_idx(struct uia_node
*node
, int idx
);
219 HRESULT
get_focus_from_node_provider(IWineUiaNode
*node
, int idx
, LONG flags
, VARIANT
*ret_val
);
220 HRESULT
respond_to_win_event_on_node_provider(IWineUiaNode
*node
, int idx
, DWORD win_event
, HWND hwnd
, LONG obj_id
,
221 LONG child_id
, IProxyProviderWinEventSink
*sink
);
222 HRESULT
create_node_from_node_provider(IWineUiaNode
*node
, int idx
, LONG flags
, VARIANT
*ret_val
);
223 HRESULT
attach_event_to_uia_node(HUIANODE node
, struct uia_event
*event
);
224 HRESULT
clone_uia_node(HUIANODE in_node
, HUIANODE
*out_node
);
225 HRESULT
navigate_uia_node(struct uia_node
*node
, int nav_dir
, HUIANODE
*out_node
);
226 HRESULT
create_uia_node_from_elprov(IRawElementProviderSimple
*elprov
, HUIANODE
*out_node
,
227 BOOL get_hwnd_providers
, int node_flags
);
228 HRESULT
uia_node_from_lresult(LRESULT lr
, HUIANODE
*huianode
, int node_flags
);
229 void uia_node_lresult_release(LRESULT lr
);
230 HRESULT
create_uia_node_from_hwnd(HWND hwnd
, HUIANODE
*out_node
, int node_flags
);
231 HRESULT
uia_condition_check(HUIANODE node
, struct UiaCondition
*condition
);
232 BOOL
uia_condition_matched(HRESULT hr
);
234 /* uia_com_client.c */
235 HRESULT
uia_com_win_event_callback(DWORD event_id
, HWND hwnd
, LONG obj_id
, LONG child_id
, DWORD thread_id
,
237 HRESULT
create_uia_iface(IUnknown
**iface
, BOOL is_cui8
);
240 HRESULT
uia_event_add_win_event_hwnd(struct uia_event
*event
, HWND hwnd
);
241 HRESULT
uia_event_for_each(int event_id
, UiaWineEventForEachCallback
*callback
, void *user_data
,
242 BOOL clientside_only
);
243 BOOL
uia_clientside_event_start_event_thread(struct uia_event
*event
);
244 HRESULT
create_msaa_provider_from_hwnd(HWND hwnd
, int in_child_id
, IRawElementProviderSimple
**ret_elprov
);
245 HRESULT
create_serverside_uia_event(struct uia_event
**out_event
, LONG process_id
, LONG event_cookie
);
246 HRESULT
uia_event_add_provider_event_adviser(IRawElementProviderAdviseEvents
*advise_events
,
247 struct uia_event
*event
);
248 HRESULT
uia_event_add_serverside_event_adviser(IWineUiaEvent
*serverside_event
, struct uia_event
*event
);
249 HRESULT
uia_event_advise_node(struct uia_event
*event
, HUIANODE node
);
250 HRESULT
uia_add_clientside_event(HUIANODE huianode
, EVENTID event_id
, enum TreeScope scope
, PROPERTYID
*prop_ids
,
251 int prop_ids_count
, struct UiaCacheRequest
*cache_req
, SAFEARRAY
*rt_id
, UiaWineEventCallback
*cback
,
252 void *cback_data
, HUIAEVENT
*huiaevent
);
253 HRESULT
uia_event_invoke(HUIANODE node
, HUIANODE nav_start_node
, struct uia_event_args
*args
,
254 struct uia_event
*event
);
255 HRESULT
uia_event_check_node_within_event_scope(struct uia_event
*event
, HUIANODE node
, SAFEARRAY
*rt_id
,
256 HUIANODE
*clientside_nav_node_out
);
259 const struct uia_prop_info
*uia_prop_info_from_id(PROPERTYID prop_id
);
260 const struct uia_event_info
*uia_event_info_from_id(EVENTID event_id
);
261 const struct uia_pattern_info
*uia_pattern_info_from_id(PATTERNID pattern_id
);
262 const struct uia_control_type_info
*uia_control_type_info_from_id(CONTROLTYPEID control_type_id
);
265 HRESULT
create_base_hwnd_provider(HWND hwnd
, IRawElementProviderSimple
**elprov
);
266 void uia_stop_provider_thread(void);
267 void uia_provider_thread_remove_node(HUIANODE node
);
268 LRESULT
uia_lresult_from_node(HUIANODE huianode
);
269 HRESULT
create_msaa_provider(IAccessible
*acc
, LONG child_id
, HWND hwnd
, BOOL root_acc_known
,
270 BOOL is_root_acc
, IRawElementProviderSimple
**elprov
);
273 HRESULT
register_interface_in_git(IUnknown
*iface
, REFIID riid
, DWORD
*ret_cookie
);
274 HRESULT
unregister_interface_in_git(DWORD git_cookie
);
275 HRESULT
get_interface_in_git(REFIID riid
, DWORD git_cookie
, IUnknown
**ret_iface
);
276 HRESULT
write_runtime_id_base(SAFEARRAY
*sa
, HWND hwnd
);
277 void uia_cache_request_destroy(struct UiaCacheRequest
*cache_req
);
278 HRESULT
uia_cache_request_clone(struct UiaCacheRequest
*dst
, struct UiaCacheRequest
*src
);
279 HRESULT
get_safearray_dim_bounds(SAFEARRAY
*sa
, UINT dim
, LONG
*lbound
, LONG
*elems
);
280 HRESULT
get_safearray_bounds(SAFEARRAY
*sa
, LONG
*lbound
, LONG
*elems
);
281 int uia_compare_safearrays(SAFEARRAY
*sa1
, SAFEARRAY
*sa2
, int prop_type
);
282 BOOL
uia_hwnd_is_visible(HWND hwnd
);
283 BOOL
uia_is_top_level_hwnd(HWND hwnd
);
284 BOOL
uia_hwnd_map_check_hwnd(struct rb_tree
*hwnd_map
, HWND hwnd
);
285 HRESULT
uia_hwnd_map_add_hwnd(struct rb_tree
*hwnd_map
, HWND hwnd
);
286 void uia_hwnd_map_remove_hwnd(struct rb_tree
*hwnd_map
, HWND hwnd
);
287 void uia_hwnd_map_init(struct rb_tree
*hwnd_map
);
288 void uia_hwnd_map_destroy(struct rb_tree
*hwnd_map
);