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 DECLSPEC_HIDDEN
;
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
);
162 static inline void variant_init_bool(VARIANT
*v
, BOOL val
)
165 V_BOOL(v
) = val
? VARIANT_TRUE
: VARIANT_FALSE
;
168 static inline void variant_init_i4(VARIANT
*v
, int val
)
174 static inline void get_variant_for_node(HUIANODE node
, VARIANT
*v
)
178 V_I8(v
) = (UINT64
)node
;
181 V_I4(v
) = (UINT32
)node
;
185 static inline BOOL
uia_array_reserve(void **elements
, SIZE_T
*capacity
, SIZE_T count
, SIZE_T size
)
187 SIZE_T max_capacity
, new_capacity
;
190 if (count
<= *capacity
)
193 max_capacity
= ~(SIZE_T
)0 / size
;
194 if (count
> max_capacity
)
197 new_capacity
= max(1, *capacity
);
198 while (new_capacity
< count
&& new_capacity
<= max_capacity
/ 2)
200 if (new_capacity
< count
)
201 new_capacity
= count
;
203 new_elements
= _recalloc(*elements
, new_capacity
, size
);
207 *elements
= new_elements
;
208 *capacity
= new_capacity
;
213 int get_node_provider_type_at_idx(struct uia_node
*node
, int idx
) DECLSPEC_HIDDEN
;
214 HRESULT
respond_to_win_event_on_node_provider(IWineUiaNode
*node
, int idx
, DWORD win_event
, HWND hwnd
, LONG obj_id
,
215 LONG child_id
, IProxyProviderWinEventSink
*sink
) DECLSPEC_HIDDEN
;
216 HRESULT
attach_event_to_uia_node(HUIANODE node
, struct uia_event
*event
) DECLSPEC_HIDDEN
;
217 HRESULT
clone_uia_node(HUIANODE in_node
, HUIANODE
*out_node
) DECLSPEC_HIDDEN
;
218 HRESULT
navigate_uia_node(struct uia_node
*node
, int nav_dir
, HUIANODE
*out_node
) DECLSPEC_HIDDEN
;
219 HRESULT
create_uia_node_from_elprov(IRawElementProviderSimple
*elprov
, HUIANODE
*out_node
,
220 BOOL get_hwnd_providers
, int node_flags
) DECLSPEC_HIDDEN
;
221 HRESULT
uia_node_from_lresult(LRESULT lr
, HUIANODE
*huianode
) DECLSPEC_HIDDEN
;
222 HRESULT
uia_condition_check(HUIANODE node
, struct UiaCondition
*condition
) DECLSPEC_HIDDEN
;
223 BOOL
uia_condition_matched(HRESULT hr
) DECLSPEC_HIDDEN
;
225 /* uia_com_client.c */
226 HRESULT
create_uia_iface(IUnknown
**iface
, BOOL is_cui8
) DECLSPEC_HIDDEN
;
229 HRESULT
uia_event_add_win_event_hwnd(struct uia_event
*event
, HWND hwnd
) DECLSPEC_HIDDEN
;
230 HRESULT
create_serverside_uia_event(struct uia_event
**out_event
, LONG process_id
, LONG event_cookie
) DECLSPEC_HIDDEN
;
231 HRESULT
uia_event_add_provider_event_adviser(IRawElementProviderAdviseEvents
*advise_events
,
232 struct uia_event
*event
) DECLSPEC_HIDDEN
;
233 HRESULT
uia_event_add_serverside_event_adviser(IWineUiaEvent
*serverside_event
, struct uia_event
*event
) DECLSPEC_HIDDEN
;
234 HRESULT
uia_add_clientside_event(HUIANODE huianode
, EVENTID event_id
, enum TreeScope scope
, PROPERTYID
*prop_ids
,
235 int prop_ids_count
, struct UiaCacheRequest
*cache_req
, SAFEARRAY
*rt_id
, UiaWineEventCallback
*cback
,
236 void *cback_data
, HUIAEVENT
*huiaevent
) DECLSPEC_HIDDEN
;
239 const struct uia_prop_info
*uia_prop_info_from_id(PROPERTYID prop_id
) DECLSPEC_HIDDEN
;
240 const struct uia_event_info
*uia_event_info_from_id(EVENTID event_id
) DECLSPEC_HIDDEN
;
241 const struct uia_pattern_info
*uia_pattern_info_from_id(PATTERNID pattern_id
) DECLSPEC_HIDDEN
;
242 const struct uia_control_type_info
*uia_control_type_info_from_id(CONTROLTYPEID control_type_id
) DECLSPEC_HIDDEN
;
245 HRESULT
create_base_hwnd_provider(HWND hwnd
, IRawElementProviderSimple
**elprov
) DECLSPEC_HIDDEN
;
246 void uia_stop_provider_thread(void) DECLSPEC_HIDDEN
;
247 void uia_provider_thread_remove_node(HUIANODE node
) DECLSPEC_HIDDEN
;
248 LRESULT
uia_lresult_from_node(HUIANODE huianode
) DECLSPEC_HIDDEN
;
249 HRESULT
create_msaa_provider(IAccessible
*acc
, LONG child_id
, HWND hwnd
, BOOL root_acc_known
,
250 BOOL is_root_acc
, IRawElementProviderSimple
**elprov
) DECLSPEC_HIDDEN
;
253 HRESULT
register_interface_in_git(IUnknown
*iface
, REFIID riid
, DWORD
*ret_cookie
) DECLSPEC_HIDDEN
;
254 HRESULT
unregister_interface_in_git(DWORD git_cookie
) DECLSPEC_HIDDEN
;
255 HRESULT
get_interface_in_git(REFIID riid
, DWORD git_cookie
, IUnknown
**ret_iface
) DECLSPEC_HIDDEN
;
256 HRESULT
write_runtime_id_base(SAFEARRAY
*sa
, HWND hwnd
) DECLSPEC_HIDDEN
;
257 void uia_cache_request_destroy(struct UiaCacheRequest
*cache_req
) DECLSPEC_HIDDEN
;
258 HRESULT
uia_cache_request_clone(struct UiaCacheRequest
*dst
, struct UiaCacheRequest
*src
) DECLSPEC_HIDDEN
;
259 HRESULT
get_safearray_dim_bounds(SAFEARRAY
*sa
, UINT dim
, LONG
*lbound
, LONG
*elems
) DECLSPEC_HIDDEN
;
260 HRESULT
get_safearray_bounds(SAFEARRAY
*sa
, LONG
*lbound
, LONG
*elems
) DECLSPEC_HIDDEN
;
261 int uia_compare_safearrays(SAFEARRAY
*sa1
, SAFEARRAY
*sa2
, int prop_type
) DECLSPEC_HIDDEN
;
262 BOOL
uia_hwnd_is_visible(HWND hwnd
) DECLSPEC_HIDDEN
;
263 BOOL
uia_is_top_level_hwnd(HWND hwnd
) DECLSPEC_HIDDEN
;
264 BOOL
uia_hwnd_map_check_hwnd(struct rb_tree
*hwnd_map
, HWND hwnd
) DECLSPEC_HIDDEN
;
265 HRESULT
uia_hwnd_map_add_hwnd(struct rb_tree
*hwnd_map
, HWND hwnd
) DECLSPEC_HIDDEN
;
266 void uia_hwnd_map_init(struct rb_tree
*hwnd_map
) DECLSPEC_HIDDEN
;
267 void uia_hwnd_map_destroy(struct rb_tree
*hwnd_map
) DECLSPEC_HIDDEN
;