uiautomationcore: Implement IUIAutomation::IntSafeArrayToNativeArray.
[wine.git] / dlls / uiautomationcore / tests / uiautomation.c
blobd5cfccf729f73033c947a77e313b4f8da684de3a
1 /*
2 * UI Automation tests
4 * Copyright 2019 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include "windows.h"
24 #include "initguid.h"
25 #include "uiautomation.h"
26 #include "ocidl.h"
27 #include "wine/iaccessible2.h"
29 #include "wine/test.h"
31 static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, long, DWORD, IRawElementProviderSimple **);
32 static HRESULT (WINAPI *pUiaDisconnectProvider)(IRawElementProviderSimple *);
34 #define DEFINE_EXPECT(func) \
35 static int expect_ ## func = 0, called_ ## func = 0
37 #define SET_EXPECT(func) \
38 do { called_ ## func = 0; expect_ ## func = 1; } while(0)
40 #define SET_EXPECT_MULTI(func, num) \
41 do { called_ ## func = 0; expect_ ## func = num; } while(0)
43 #define CHECK_EXPECT2(func) \
44 do { \
45 ok(expect_ ##func, "unexpected call " #func "\n"); \
46 called_ ## func++; \
47 }while(0)
49 #define CHECK_EXPECT(func) \
50 do { \
51 CHECK_EXPECT2(func); \
52 expect_ ## func--; \
53 }while(0)
55 #define CHECK_CALLED(func) \
56 do { \
57 ok(called_ ## func, "expected " #func "\n"); \
58 expect_ ## func = called_ ## func = 0; \
59 }while(0)
61 #define CHECK_CALLED_MULTI(func, num) \
62 do { \
63 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
64 expect_ ## func = called_ ## func = 0; \
65 }while(0)
67 #define NAVDIR_INTERNAL_HWND 10
68 #define UIA_RUNTIME_ID_PREFIX 42
70 DEFINE_EXPECT(winproc_GETOBJECT_CLIENT);
71 DEFINE_EXPECT(prov_callback_base_hwnd);
72 DEFINE_EXPECT(prov_callback_nonclient);
73 DEFINE_EXPECT(prov_callback_proxy);
74 DEFINE_EXPECT(prov_callback_parent_proxy);
75 DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot);
76 DEFINE_EXPECT(child_winproc_GETOBJECT_UiaRoot);
77 DEFINE_EXPECT(Accessible_accNavigate);
78 DEFINE_EXPECT(Accessible_get_accParent);
79 DEFINE_EXPECT(Accessible_get_accChildCount);
80 DEFINE_EXPECT(Accessible_get_accName);
81 DEFINE_EXPECT(Accessible_get_accRole);
82 DEFINE_EXPECT(Accessible_get_accState);
83 DEFINE_EXPECT(Accessible_accLocation);
84 DEFINE_EXPECT(Accessible_get_accChild);
85 DEFINE_EXPECT(Accessible_get_uniqueID);
86 DEFINE_EXPECT(Accessible2_get_accParent);
87 DEFINE_EXPECT(Accessible2_get_accChildCount);
88 DEFINE_EXPECT(Accessible2_get_accName);
89 DEFINE_EXPECT(Accessible2_get_accRole);
90 DEFINE_EXPECT(Accessible2_get_accState);
91 DEFINE_EXPECT(Accessible2_accLocation);
92 DEFINE_EXPECT(Accessible2_QI_IAccIdentity);
93 DEFINE_EXPECT(Accessible2_get_uniqueID);
94 DEFINE_EXPECT(Accessible_child_accNavigate);
95 DEFINE_EXPECT(Accessible_child_get_accParent);
96 DEFINE_EXPECT(Accessible_child_get_accChildCount);
97 DEFINE_EXPECT(Accessible_child_get_accName);
98 DEFINE_EXPECT(Accessible_child_get_accRole);
99 DEFINE_EXPECT(Accessible_child_get_accState);
100 DEFINE_EXPECT(Accessible_child_accLocation);
101 DEFINE_EXPECT(Accessible_child2_accNavigate);
102 DEFINE_EXPECT(Accessible_child2_get_accParent);
103 DEFINE_EXPECT(Accessible_child2_get_accChildCount);
104 DEFINE_EXPECT(Accessible_child2_get_accName);
105 DEFINE_EXPECT(Accessible_child2_get_accRole);
106 DEFINE_EXPECT(Accessible_child2_get_accState);
107 DEFINE_EXPECT(Accessible_child2_accLocation);
109 static BOOL check_variant_i4(VARIANT *v, int val)
111 if (V_VT(v) == VT_I4 && V_I4(v) == val)
112 return TRUE;
114 return FALSE;
117 static BOOL check_variant_bool(VARIANT *v, BOOL val)
119 if (V_VT(v) == VT_BOOL && V_BOOL(v) == (val ? VARIANT_TRUE : VARIANT_FALSE))
120 return TRUE;
122 return FALSE;
125 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
127 IUnknown *unk1, *unk2;
128 BOOL cmp;
130 IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
131 IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
132 cmp = (unk1 == unk2) ? TRUE : FALSE;
134 IUnknown_Release(unk1);
135 IUnknown_Release(unk2);
136 return cmp;
139 static struct Accessible
141 IAccessible IAccessible_iface;
142 IAccessible2 IAccessible2_iface;
143 IOleWindow IOleWindow_iface;
144 IServiceProvider IServiceProvider_iface;
145 LONG ref;
147 IAccessible *parent;
148 HWND acc_hwnd;
149 HWND ow_hwnd;
150 INT role;
151 INT state;
152 LONG child_count;
153 LPCWSTR name;
154 LONG left, top, width, height;
155 BOOL enable_ia2;
156 LONG unique_id;
157 } Accessible, Accessible2, Accessible_child, Accessible_child2;
159 static inline struct Accessible* impl_from_Accessible(IAccessible *iface)
161 return CONTAINING_RECORD(iface, struct Accessible, IAccessible_iface);
164 static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID riid, void **obj)
166 struct Accessible *This = impl_from_Accessible(iface);
168 *obj = NULL;
169 if (IsEqualIID(riid, &IID_IAccIdentity))
171 if (This == &Accessible2)
172 CHECK_EXPECT(Accessible2_QI_IAccIdentity);
173 ok(This == &Accessible2, "unexpected call\n");
174 return E_NOINTERFACE;
177 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
178 IsEqualIID(riid, &IID_IAccessible))
179 *obj = iface;
180 else if (IsEqualIID(riid, &IID_IOleWindow))
181 *obj = &This->IOleWindow_iface;
182 else if (IsEqualIID(riid, &IID_IServiceProvider))
183 *obj = &This->IServiceProvider_iface;
184 else if (IsEqualIID(riid, &IID_IAccessible2) && This->enable_ia2)
185 *obj = &This->IAccessible2_iface;
186 else
187 return E_NOINTERFACE;
189 IAccessible_AddRef(iface);
190 return S_OK;
193 static ULONG WINAPI Accessible_AddRef(IAccessible *iface)
195 struct Accessible *This = impl_from_Accessible(iface);
196 return InterlockedIncrement(&This->ref);
199 static ULONG WINAPI Accessible_Release(IAccessible *iface)
201 struct Accessible *This = impl_from_Accessible(iface);
202 return InterlockedDecrement(&This->ref);
205 static HRESULT WINAPI Accessible_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
207 ok(0, "unexpected call\n");
208 return E_NOTIMPL;
211 static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface, UINT iTInfo,
212 LCID lcid, ITypeInfo **out_tinfo)
214 ok(0, "unexpected call\n");
215 return E_NOTIMPL;
218 static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID riid,
219 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
221 ok(0, "unexpected call\n");
222 return E_NOTIMPL;
225 static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID disp_id_member,
226 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
227 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
229 ok(0, "unexpected call\n");
230 return E_NOTIMPL;
233 static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **out_parent)
235 struct Accessible *This = impl_from_Accessible(iface);
237 if (This == &Accessible_child)
238 CHECK_EXPECT(Accessible_child_get_accParent);
239 else if (This == &Accessible_child2)
240 CHECK_EXPECT(Accessible_child2_get_accParent);
241 else if (This == &Accessible2)
242 CHECK_EXPECT(Accessible2_get_accParent);
243 else
244 CHECK_EXPECT(Accessible_get_accParent);
246 if (This->parent)
247 return IAccessible_QueryInterface(This->parent, &IID_IDispatch, (void **)out_parent);
249 *out_parent = NULL;
250 return S_FALSE;
253 static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out_count)
255 struct Accessible *This = impl_from_Accessible(iface);
257 if (This == &Accessible_child)
258 CHECK_EXPECT(Accessible_child_get_accChildCount);
259 else if (This == &Accessible_child2)
260 CHECK_EXPECT(Accessible_child2_get_accChildCount);
261 else if (This == &Accessible2)
262 CHECK_EXPECT(Accessible2_get_accChildCount);
263 else
264 CHECK_EXPECT(Accessible_get_accChildCount);
266 if (This->child_count)
268 *out_count = This->child_count;
269 return S_OK;
272 return E_NOTIMPL;
275 static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_id,
276 IDispatch **out_child)
278 struct Accessible *This = impl_from_Accessible(iface);
280 CHECK_EXPECT(Accessible_get_accChild);
281 ok(This == &Accessible, "unexpected call\n");
283 *out_child = NULL;
284 if (V_VT(&child_id) != VT_I4)
285 return E_INVALIDARG;
287 if (This == &Accessible)
289 switch (V_I4(&child_id))
291 case CHILDID_SELF:
292 return IAccessible_QueryInterface(&This->IAccessible_iface, &IID_IDispatch, (void **)out_child);
294 /* Simple element children. */
295 case 1:
296 case 3:
297 return S_FALSE;
299 case 2:
300 return IAccessible_QueryInterface(&Accessible_child.IAccessible_iface, &IID_IDispatch, (void **)out_child);
302 case 4:
303 return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
305 default:
306 break;
310 return E_NOTIMPL;
313 static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_id,
314 BSTR *out_name)
316 struct Accessible *This = impl_from_Accessible(iface);
318 *out_name = NULL;
319 if (This == &Accessible_child)
320 CHECK_EXPECT(Accessible_child_get_accName);
321 else if (This == &Accessible_child2)
322 CHECK_EXPECT(Accessible_child2_get_accName);
323 else if (This == &Accessible2)
324 CHECK_EXPECT(Accessible2_get_accName);
325 else
326 CHECK_EXPECT(Accessible_get_accName);
328 if (This->name)
330 *out_name = SysAllocString(This->name);
331 return S_OK;
334 return E_NOTIMPL;
337 static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface, VARIANT child_id,
338 BSTR *out_value)
340 ok(0, "unexpected call\n");
341 return E_NOTIMPL;
344 static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface, VARIANT child_id,
345 BSTR *out_description)
347 ok(0, "unexpected call\n");
348 return E_NOTIMPL;
351 static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_id,
352 VARIANT *out_role)
354 struct Accessible *This = impl_from_Accessible(iface);
356 if (This == &Accessible_child)
357 CHECK_EXPECT(Accessible_child_get_accRole);
358 else if (This == &Accessible_child2)
359 CHECK_EXPECT(Accessible_child2_get_accRole);
360 else if (This == &Accessible2)
361 CHECK_EXPECT(Accessible2_get_accRole);
362 else
363 CHECK_EXPECT(Accessible_get_accRole);
365 if (This->role)
367 V_VT(out_role) = VT_I4;
368 V_I4(out_role) = This->role;
369 return S_OK;
372 return E_NOTIMPL;
375 static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_id,
376 VARIANT *out_state)
378 struct Accessible *This = impl_from_Accessible(iface);
380 if (This == &Accessible_child)
381 CHECK_EXPECT(Accessible_child_get_accState);
382 else if (This == &Accessible_child2)
383 CHECK_EXPECT(Accessible_child2_get_accState);
384 else if (This == &Accessible2)
385 CHECK_EXPECT(Accessible2_get_accState);
386 else
387 CHECK_EXPECT(Accessible_get_accState);
389 if (V_VT(&child_id) != VT_I4)
390 return E_INVALIDARG;
392 if (This == &Accessible && V_I4(&child_id) != CHILDID_SELF)
394 switch (V_I4(&child_id))
396 case 1:
397 V_VT(out_state) = VT_I4;
398 V_I4(out_state) = STATE_SYSTEM_INVISIBLE;
399 break;
401 case 3:
402 V_VT(out_state) = VT_I4;
403 V_I4(out_state) = STATE_SYSTEM_FOCUSABLE;
404 break;
406 default:
407 return E_INVALIDARG;
410 return S_OK;
413 if (This->state)
415 V_VT(out_state) = VT_I4;
416 V_I4(out_state) = This->state;
417 return S_OK;
420 return E_NOTIMPL;
423 static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface, VARIANT child_id,
424 BSTR *out_help)
426 ok(0, "unexpected call\n");
427 return E_NOTIMPL;
430 static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface,
431 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
433 ok(0, "unexpected call\n");
434 return E_NOTIMPL;
437 static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VARIANT child_id,
438 BSTR *out_kbd_shortcut)
440 ok(0, "unexpected call\n");
441 return E_NOTIMPL;
444 static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pchild_id)
446 ok(0, "unexpected call\n");
447 return E_NOTIMPL;
450 static HRESULT WINAPI Accessible_get_accSelection(IAccessible *iface, VARIANT *out_selection)
452 ok(0, "unexpected call\n");
453 return E_NOTIMPL;
456 static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface, VARIANT child_id,
457 BSTR *out_default_action)
459 ok(0, "unexpected call\n");
460 return E_NOTIMPL;
463 static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, LONG select_flags,
464 VARIANT child_id)
466 ok(0, "unexpected call\n");
467 return E_NOTIMPL;
470 static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *out_left,
471 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
473 struct Accessible *This = impl_from_Accessible(iface);
475 if (This == &Accessible_child)
476 CHECK_EXPECT(Accessible_child_accLocation);
477 else if (This == &Accessible_child2)
478 CHECK_EXPECT(Accessible_child2_accLocation);
479 else if (This == &Accessible2)
480 CHECK_EXPECT(Accessible2_accLocation);
481 else
482 CHECK_EXPECT(Accessible_accLocation);
484 if (This->width && This->height)
486 *out_left = This->left;
487 *out_top = This->top;
488 *out_width = This->width;
489 *out_height = This->height;
490 return S_OK;
493 return E_NOTIMPL;
496 static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface, LONG nav_direction,
497 VARIANT child_id_start, VARIANT *out_var)
499 struct Accessible *This = impl_from_Accessible(iface);
501 if (This == &Accessible_child)
502 CHECK_EXPECT(Accessible_child_accNavigate);
503 else if (This == &Accessible_child2)
504 CHECK_EXPECT(Accessible_child2_accNavigate);
505 else
506 CHECK_EXPECT(Accessible_accNavigate);
507 VariantInit(out_var);
510 * This is an undocumented way for UI Automation to get an HWND for
511 * IAccessible's contained in a Direct Annotation wrapper object.
513 if ((nav_direction == NAVDIR_INTERNAL_HWND) && check_variant_i4(&child_id_start, CHILDID_SELF) &&
514 This->acc_hwnd)
516 V_VT(out_var) = VT_I4;
517 V_I4(out_var) = HandleToUlong(This->acc_hwnd);
518 return S_OK;
520 return S_FALSE;
523 static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface, LONG left, LONG top,
524 VARIANT *out_child_id)
526 ok(0, "unexpected call\n");
527 return E_NOTIMPL;
530 static HRESULT WINAPI Accessible_accDoDefaultAction(IAccessible *iface, VARIANT child_id)
532 ok(0, "unexpected call\n");
533 return E_NOTIMPL;
536 static HRESULT WINAPI Accessible_put_accName(IAccessible *iface, VARIANT child_id,
537 BSTR name)
539 ok(0, "unexpected call\n");
540 return E_NOTIMPL;
543 static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface, VARIANT child_id,
544 BSTR value)
546 ok(0, "unexpected call\n");
547 return E_NOTIMPL;
550 static IAccessibleVtbl AccessibleVtbl = {
551 Accessible_QueryInterface,
552 Accessible_AddRef,
553 Accessible_Release,
554 Accessible_GetTypeInfoCount,
555 Accessible_GetTypeInfo,
556 Accessible_GetIDsOfNames,
557 Accessible_Invoke,
558 Accessible_get_accParent,
559 Accessible_get_accChildCount,
560 Accessible_get_accChild,
561 Accessible_get_accName,
562 Accessible_get_accValue,
563 Accessible_get_accDescription,
564 Accessible_get_accRole,
565 Accessible_get_accState,
566 Accessible_get_accHelp,
567 Accessible_get_accHelpTopic,
568 Accessible_get_accKeyboardShortcut,
569 Accessible_get_accFocus,
570 Accessible_get_accSelection,
571 Accessible_get_accDefaultAction,
572 Accessible_accSelect,
573 Accessible_accLocation,
574 Accessible_accNavigate,
575 Accessible_accHitTest,
576 Accessible_accDoDefaultAction,
577 Accessible_put_accName,
578 Accessible_put_accValue
581 static inline struct Accessible* impl_from_Accessible2(IAccessible2 *iface)
583 return CONTAINING_RECORD(iface, struct Accessible, IAccessible2_iface);
586 static HRESULT WINAPI Accessible2_QueryInterface(IAccessible2 *iface, REFIID riid, void **obj)
588 struct Accessible *This = impl_from_Accessible2(iface);
589 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
592 static ULONG WINAPI Accessible2_AddRef(IAccessible2 *iface)
594 struct Accessible *This = impl_from_Accessible2(iface);
595 return IAccessible_AddRef(&This->IAccessible_iface);
598 static ULONG WINAPI Accessible2_Release(IAccessible2 *iface)
600 struct Accessible *This = impl_from_Accessible2(iface);
601 return IAccessible_Release(&This->IAccessible_iface);
604 static HRESULT WINAPI Accessible2_GetTypeInfoCount(IAccessible2 *iface, UINT *pctinfo)
606 struct Accessible *This = impl_from_Accessible2(iface);
607 return IAccessible_GetTypeInfoCount(&This->IAccessible_iface, pctinfo);
610 static HRESULT WINAPI Accessible2_GetTypeInfo(IAccessible2 *iface, UINT iTInfo,
611 LCID lcid, ITypeInfo **out_tinfo)
613 struct Accessible *This = impl_from_Accessible2(iface);
614 return IAccessible_GetTypeInfo(&This->IAccessible_iface, iTInfo, lcid, out_tinfo);
617 static HRESULT WINAPI Accessible2_GetIDsOfNames(IAccessible2 *iface, REFIID riid,
618 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
620 struct Accessible *This = impl_from_Accessible2(iface);
621 return IAccessible_GetIDsOfNames(&This->IAccessible_iface, riid, rg_names, name_count,
622 lcid, rg_disp_id);
625 static HRESULT WINAPI Accessible2_Invoke(IAccessible2 *iface, DISPID disp_id_member,
626 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
627 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
629 struct Accessible *This = impl_from_Accessible2(iface);
630 return IAccessible_Invoke(&This->IAccessible_iface, disp_id_member, riid, lcid, flags,
631 disp_params, var_result, excep_info, arg_err);
634 static HRESULT WINAPI Accessible2_get_accParent(IAccessible2 *iface, IDispatch **out_parent)
636 struct Accessible *This = impl_from_Accessible2(iface);
637 return IAccessible_get_accParent(&This->IAccessible_iface, out_parent);
640 static HRESULT WINAPI Accessible2_get_accChildCount(IAccessible2 *iface, LONG *out_count)
642 struct Accessible *This = impl_from_Accessible2(iface);
643 return IAccessible_get_accChildCount(&This->IAccessible_iface, out_count);
646 static HRESULT WINAPI Accessible2_get_accChild(IAccessible2 *iface, VARIANT child_id,
647 IDispatch **out_child)
649 struct Accessible *This = impl_from_Accessible2(iface);
650 return IAccessible_get_accChild(&This->IAccessible_iface, child_id, out_child);
653 static HRESULT WINAPI Accessible2_get_accName(IAccessible2 *iface, VARIANT child_id,
654 BSTR *out_name)
656 struct Accessible *This = impl_from_Accessible2(iface);
657 return IAccessible_get_accName(&This->IAccessible_iface, child_id, out_name);
660 static HRESULT WINAPI Accessible2_get_accValue(IAccessible2 *iface, VARIANT child_id,
661 BSTR *out_value)
663 struct Accessible *This = impl_from_Accessible2(iface);
664 return IAccessible_get_accValue(&This->IAccessible_iface, child_id, out_value);
667 static HRESULT WINAPI Accessible2_get_accDescription(IAccessible2 *iface, VARIANT child_id,
668 BSTR *out_description)
670 struct Accessible *This = impl_from_Accessible2(iface);
671 return IAccessible_get_accDescription(&This->IAccessible_iface, child_id, out_description);
674 static HRESULT WINAPI Accessible2_get_accRole(IAccessible2 *iface, VARIANT child_id,
675 VARIANT *out_role)
677 struct Accessible *This = impl_from_Accessible2(iface);
678 return IAccessible_get_accRole(&This->IAccessible_iface, child_id, out_role);
681 static HRESULT WINAPI Accessible2_get_accState(IAccessible2 *iface, VARIANT child_id,
682 VARIANT *out_state)
684 struct Accessible *This = impl_from_Accessible2(iface);
685 return IAccessible_get_accState(&This->IAccessible_iface, child_id, out_state);
688 static HRESULT WINAPI Accessible2_get_accHelp(IAccessible2 *iface, VARIANT child_id,
689 BSTR *out_help)
691 struct Accessible *This = impl_from_Accessible2(iface);
692 return IAccessible_get_accHelp(&This->IAccessible_iface, child_id, out_help);
695 static HRESULT WINAPI Accessible2_get_accHelpTopic(IAccessible2 *iface,
696 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
698 struct Accessible *This = impl_from_Accessible2(iface);
699 return IAccessible_get_accHelpTopic(&This->IAccessible_iface, out_help_file, child_id,
700 out_topic_id);
703 static HRESULT WINAPI Accessible2_get_accKeyboardShortcut(IAccessible2 *iface, VARIANT child_id,
704 BSTR *out_kbd_shortcut)
706 struct Accessible *This = impl_from_Accessible2(iface);
707 return IAccessible_get_accKeyboardShortcut(&This->IAccessible_iface, child_id,
708 out_kbd_shortcut);
711 static HRESULT WINAPI Accessible2_get_accFocus(IAccessible2 *iface, VARIANT *pchild_id)
713 struct Accessible *This = impl_from_Accessible2(iface);
714 return IAccessible_get_accFocus(&This->IAccessible_iface, pchild_id);
717 static HRESULT WINAPI Accessible2_get_accSelection(IAccessible2 *iface, VARIANT *out_selection)
719 struct Accessible *This = impl_from_Accessible2(iface);
720 return IAccessible_get_accSelection(&This->IAccessible_iface, out_selection);
723 static HRESULT WINAPI Accessible2_get_accDefaultAction(IAccessible2 *iface, VARIANT child_id,
724 BSTR *out_default_action)
726 struct Accessible *This = impl_from_Accessible2(iface);
727 return IAccessible_get_accDefaultAction(&This->IAccessible_iface, child_id,
728 out_default_action);
731 static HRESULT WINAPI Accessible2_accSelect(IAccessible2 *iface, LONG select_flags,
732 VARIANT child_id)
734 struct Accessible *This = impl_from_Accessible2(iface);
735 return IAccessible_accSelect(&This->IAccessible_iface, select_flags, child_id);
738 static HRESULT WINAPI Accessible2_accLocation(IAccessible2 *iface, LONG *out_left,
739 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
741 struct Accessible *This = impl_from_Accessible2(iface);
742 return IAccessible_accLocation(&This->IAccessible_iface, out_left, out_top, out_width,
743 out_height, child_id);
746 static HRESULT WINAPI Accessible2_accNavigate(IAccessible2 *iface, LONG nav_direction,
747 VARIANT child_id_start, VARIANT *out_var)
749 struct Accessible *This = impl_from_Accessible2(iface);
750 return IAccessible_accNavigate(&This->IAccessible_iface, nav_direction, child_id_start,
751 out_var);
754 static HRESULT WINAPI Accessible2_accHitTest(IAccessible2 *iface, LONG left, LONG top,
755 VARIANT *out_child_id)
757 struct Accessible *This = impl_from_Accessible2(iface);
758 return IAccessible_accHitTest(&This->IAccessible_iface, left, top, out_child_id);
761 static HRESULT WINAPI Accessible2_accDoDefaultAction(IAccessible2 *iface, VARIANT child_id)
763 struct Accessible *This = impl_from_Accessible2(iface);
764 return IAccessible_accDoDefaultAction(&This->IAccessible_iface, child_id);
767 static HRESULT WINAPI Accessible2_put_accName(IAccessible2 *iface, VARIANT child_id,
768 BSTR name)
770 struct Accessible *This = impl_from_Accessible2(iface);
771 return IAccessible_put_accName(&This->IAccessible_iface, child_id, name);
774 static HRESULT WINAPI Accessible2_put_accValue(IAccessible2 *iface, VARIANT child_id,
775 BSTR value)
777 struct Accessible *This = impl_from_Accessible2(iface);
778 return IAccessible_put_accValue(&This->IAccessible_iface, child_id, value);
781 static HRESULT WINAPI Accessible2_get_nRelations(IAccessible2 *iface, LONG *out_nRelations)
783 ok(0, "unexpected call\n");
784 return E_NOTIMPL;
787 static HRESULT WINAPI Accessible2_get_relation(IAccessible2 *iface, LONG relation_idx,
788 IAccessibleRelation **out_relation)
790 ok(0, "unexpected call\n");
791 return E_NOTIMPL;
794 static HRESULT WINAPI Accessible2_get_relations(IAccessible2 *iface, LONG count,
795 IAccessibleRelation **out_relations, LONG *out_relation_count)
797 ok(0, "unexpected call\n");
798 return E_NOTIMPL;
801 static HRESULT WINAPI Accessible2_role(IAccessible2 *iface, LONG *out_role)
803 ok(0, "unexpected call\n");
804 return E_NOTIMPL;
807 static HRESULT WINAPI Accessible2_scrollTo(IAccessible2 *iface, enum IA2ScrollType scroll_type)
809 ok(0, "unexpected call\n");
810 return E_NOTIMPL;
813 static HRESULT WINAPI Accessible2_scrollToPoint(IAccessible2 *iface,
814 enum IA2CoordinateType coordinate_type, LONG x, LONG y)
816 ok(0, "unexpected call\n");
817 return E_NOTIMPL;
820 static HRESULT WINAPI Accessible2_get_groupPosition(IAccessible2 *iface, LONG *out_group_level,
821 LONG *out_similar_items_in_group, LONG *out_position_in_group)
823 ok(0, "unexpected call\n");
824 return E_NOTIMPL;
827 static HRESULT WINAPI Accessible2_get_states(IAccessible2 *iface, AccessibleStates *out_states)
829 ok(0, "unexpected call\n");
830 return E_NOTIMPL;
833 static HRESULT WINAPI Accessible2_get_extendedRole(IAccessible2 *iface, BSTR *out_extended_role)
835 ok(0, "unexpected call\n");
836 return E_NOTIMPL;
839 static HRESULT WINAPI Accessible2_get_localizedExtendedRole(IAccessible2 *iface,
840 BSTR *out_localized_extended_role)
842 ok(0, "unexpected call\n");
843 return E_NOTIMPL;
846 static HRESULT WINAPI Accessible2_get_nExtendedStates(IAccessible2 *iface, LONG *out_nExtendedStates)
848 ok(0, "unexpected call\n");
849 return E_NOTIMPL;
852 static HRESULT WINAPI Accessible2_get_extendedStates(IAccessible2 *iface, LONG count,
853 BSTR **out_extended_states, LONG *out_extended_states_count)
855 ok(0, "unexpected call\n");
856 return E_NOTIMPL;
859 static HRESULT WINAPI Accessible2_get_localizedExtendedStates(IAccessible2 *iface, LONG count,
860 BSTR **out_localized_extended_states, LONG *out_localized_extended_states_count)
862 ok(0, "unexpected call\n");
863 return E_NOTIMPL;
866 static HRESULT WINAPI Accessible2_get_uniqueID(IAccessible2 *iface, LONG *out_unique_id)
868 struct Accessible *This = impl_from_Accessible2(iface);
870 if (This == &Accessible2)
871 CHECK_EXPECT(Accessible2_get_uniqueID);
872 else
873 CHECK_EXPECT(Accessible_get_uniqueID);
875 *out_unique_id = 0;
876 if (This->unique_id)
878 *out_unique_id = This->unique_id;
879 return S_OK;
882 return E_NOTIMPL;
885 static HRESULT WINAPI Accessible2_get_windowHandle(IAccessible2 *iface, HWND *out_hwnd)
887 ok(0, "unexpected call\n");
888 return E_NOTIMPL;
891 static HRESULT WINAPI Accessible2_get_indexInParent(IAccessible2 *iface, LONG *out_idx_in_parent)
893 ok(0, "unexpected call\n");
894 return E_NOTIMPL;
897 static HRESULT WINAPI Accessible2_get_locale(IAccessible2 *iface, IA2Locale *out_locale)
899 ok(0, "unexpected call\n");
900 return E_NOTIMPL;
903 static HRESULT WINAPI Accessible2_get_attributes(IAccessible2 *iface, BSTR *out_attributes)
905 ok(0, "unexpected call\n");
906 return E_NOTIMPL;
909 static const IAccessible2Vtbl Accessible2Vtbl = {
910 Accessible2_QueryInterface,
911 Accessible2_AddRef,
912 Accessible2_Release,
913 Accessible2_GetTypeInfoCount,
914 Accessible2_GetTypeInfo,
915 Accessible2_GetIDsOfNames,
916 Accessible2_Invoke,
917 Accessible2_get_accParent,
918 Accessible2_get_accChildCount,
919 Accessible2_get_accChild,
920 Accessible2_get_accName,
921 Accessible2_get_accValue,
922 Accessible2_get_accDescription,
923 Accessible2_get_accRole,
924 Accessible2_get_accState,
925 Accessible2_get_accHelp,
926 Accessible2_get_accHelpTopic,
927 Accessible2_get_accKeyboardShortcut,
928 Accessible2_get_accFocus,
929 Accessible2_get_accSelection,
930 Accessible2_get_accDefaultAction,
931 Accessible2_accSelect,
932 Accessible2_accLocation,
933 Accessible2_accNavigate,
934 Accessible2_accHitTest,
935 Accessible2_accDoDefaultAction,
936 Accessible2_put_accName,
937 Accessible2_put_accValue,
938 Accessible2_get_nRelations,
939 Accessible2_get_relation,
940 Accessible2_get_relations,
941 Accessible2_role,
942 Accessible2_scrollTo,
943 Accessible2_scrollToPoint,
944 Accessible2_get_groupPosition,
945 Accessible2_get_states,
946 Accessible2_get_extendedRole,
947 Accessible2_get_localizedExtendedRole,
948 Accessible2_get_nExtendedStates,
949 Accessible2_get_extendedStates,
950 Accessible2_get_localizedExtendedStates,
951 Accessible2_get_uniqueID,
952 Accessible2_get_windowHandle,
953 Accessible2_get_indexInParent,
954 Accessible2_get_locale,
955 Accessible2_get_attributes,
958 static inline struct Accessible* impl_from_OleWindow(IOleWindow *iface)
960 return CONTAINING_RECORD(iface, struct Accessible, IOleWindow_iface);
963 static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **obj)
965 struct Accessible *This = impl_from_OleWindow(iface);
966 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
969 static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
971 struct Accessible *This = impl_from_OleWindow(iface);
972 return IAccessible_AddRef(&This->IAccessible_iface);
975 static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
977 struct Accessible *This = impl_from_OleWindow(iface);
978 return IAccessible_Release(&This->IAccessible_iface);
981 static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd)
983 struct Accessible *This = impl_from_OleWindow(iface);
985 *hwnd = This->ow_hwnd;
986 return *hwnd ? S_OK : E_FAIL;
989 static HRESULT WINAPI OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL f_enter_mode)
991 return E_NOTIMPL;
994 static const IOleWindowVtbl OleWindowVtbl = {
995 OleWindow_QueryInterface,
996 OleWindow_AddRef,
997 OleWindow_Release,
998 OleWindow_GetWindow,
999 OleWindow_ContextSensitiveHelp
1002 static inline struct Accessible* impl_from_ServiceProvider(IServiceProvider *iface)
1004 return CONTAINING_RECORD(iface, struct Accessible, IServiceProvider_iface);
1007 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **obj)
1009 struct Accessible *This = impl_from_ServiceProvider(iface);
1010 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1013 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
1015 struct Accessible *This = impl_from_ServiceProvider(iface);
1016 return IAccessible_AddRef(&This->IAccessible_iface);
1019 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
1021 struct Accessible *This = impl_from_ServiceProvider(iface);
1022 return IAccessible_Release(&This->IAccessible_iface);
1025 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID service_guid,
1026 REFIID riid, void **obj)
1028 struct Accessible *This = impl_from_ServiceProvider(iface);
1030 if (IsEqualIID(riid, &IID_IAccessible2) && IsEqualIID(service_guid, &IID_IAccessible2) &&
1031 This->enable_ia2)
1032 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1034 return E_NOTIMPL;
1037 static const IServiceProviderVtbl ServiceProviderVtbl = {
1038 ServiceProvider_QueryInterface,
1039 ServiceProvider_AddRef,
1040 ServiceProvider_Release,
1041 ServiceProvider_QueryService,
1044 static struct Accessible Accessible =
1046 { &AccessibleVtbl },
1047 { &Accessible2Vtbl },
1048 { &OleWindowVtbl },
1049 { &ServiceProviderVtbl },
1051 NULL,
1052 0, 0,
1053 0, 0, 0, NULL,
1054 0, 0, 0, 0,
1055 FALSE, 0,
1058 static struct Accessible Accessible2 =
1060 { &AccessibleVtbl },
1061 { &Accessible2Vtbl },
1062 { &OleWindowVtbl },
1063 { &ServiceProviderVtbl },
1065 NULL,
1066 0, 0,
1067 0, 0, 0, NULL,
1068 0, 0, 0, 0,
1069 FALSE, 0,
1072 static struct Accessible Accessible_child =
1074 { &AccessibleVtbl },
1075 { &Accessible2Vtbl },
1076 { &OleWindowVtbl },
1077 { &ServiceProviderVtbl },
1079 &Accessible.IAccessible_iface,
1080 0, 0,
1081 0, 0, 0, NULL,
1082 0, 0, 0, 0,
1083 FALSE, 0,
1086 static struct Accessible Accessible_child2 =
1088 { &AccessibleVtbl },
1089 { &Accessible2Vtbl },
1090 { &OleWindowVtbl },
1091 { &ServiceProviderVtbl },
1093 &Accessible.IAccessible_iface,
1094 0, 0,
1095 0, 0, 0, NULL,
1096 0, 0, 0, 0,
1097 FALSE, 0,
1100 struct Provider_prop_override
1102 int prop_id;
1103 VARIANT val;
1106 struct Provider_value_pattern_data
1108 BOOL is_supported;
1109 BOOL is_read_only;
1112 static struct Provider
1114 IRawElementProviderSimple IRawElementProviderSimple_iface;
1115 IRawElementProviderFragment IRawElementProviderFragment_iface;
1116 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface;
1117 IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface;
1118 IValueProvider IValueProvider_iface;
1119 LONG ref;
1121 const char *prov_name;
1122 IRawElementProviderFragment *parent;
1123 IRawElementProviderFragmentRoot *frag_root;
1124 IRawElementProviderFragment *prev_sibling;
1125 IRawElementProviderFragment *next_sibling;
1126 IRawElementProviderFragment *first_child;
1127 IRawElementProviderFragment *last_child;
1128 enum ProviderOptions prov_opts;
1129 HWND hwnd;
1130 BOOL ret_invalid_prop_type;
1131 DWORD expected_tid;
1132 int runtime_id[2];
1133 DWORD last_call_tid;
1134 BOOL ignore_hwnd_prop;
1135 HWND override_hwnd;
1136 struct Provider_prop_override *prop_override;
1137 int prop_override_count;
1138 struct UiaRect bounds_rect;
1139 struct Provider_value_pattern_data value_pattern_data;
1140 } Provider, Provider2, Provider_child, Provider_child2;
1141 static struct Provider Provider_hwnd, Provider_nc, Provider_proxy, Provider_proxy2, Provider_override;
1142 static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links);
1144 static const WCHAR *uia_bstr_prop_str = L"uia-string";
1145 static const ULONG uia_i4_prop_val = 0xdeadbeef;
1146 static const ULONG uia_i4_arr_prop_val[] = { 0xfeedbeef, 0xdeadcafe, 0xfefedede };
1147 static const double uia_r8_prop_val = 128.256f;
1148 static const double uia_r8_arr_prop_val[] = { 2.4, 8.16, 32.64 };
1149 static const IRawElementProviderSimple *uia_unk_arr_prop_val[] = { &Provider_child.IRawElementProviderSimple_iface,
1150 &Provider_child2.IRawElementProviderSimple_iface };
1151 static SAFEARRAY *create_i4_safearray(void)
1153 SAFEARRAY *sa;
1154 LONG idx;
1156 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(uia_i4_arr_prop_val))))
1157 return NULL;
1159 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
1160 SafeArrayPutElement(sa, &idx, (void *)&uia_i4_arr_prop_val[idx]);
1162 return sa;
1165 static SAFEARRAY *create_r8_safearray(void)
1167 SAFEARRAY *sa;
1168 LONG idx;
1170 if (!(sa = SafeArrayCreateVector(VT_R8, 0, ARRAY_SIZE(uia_r8_arr_prop_val))))
1171 return NULL;
1173 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
1174 SafeArrayPutElement(sa, &idx, (void *)&uia_r8_arr_prop_val[idx]);
1176 return sa;
1179 static SAFEARRAY *create_unk_safearray(void)
1181 SAFEARRAY *sa;
1182 LONG idx;
1184 if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, ARRAY_SIZE(uia_unk_arr_prop_val))))
1185 return NULL;
1187 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
1188 SafeArrayPutElement(sa, &idx, (void *)uia_unk_arr_prop_val[idx]);
1190 return sa;
1193 enum {
1194 PROV_GET_PROVIDER_OPTIONS,
1195 PROV_GET_PATTERN_PROV,
1196 PROV_GET_PROPERTY_VALUE,
1197 PROV_GET_HOST_RAW_ELEMENT_PROVIDER,
1198 FRAG_NAVIGATE,
1199 FRAG_GET_RUNTIME_ID,
1200 FRAG_GET_FRAGMENT_ROOT,
1201 FRAG_GET_BOUNDING_RECT,
1202 HWND_OVERRIDE_GET_OVERRIDE_PROVIDER,
1205 static const char *prov_method_str[] = {
1206 "get_ProviderOptions",
1207 "GetPatternProvider",
1208 "GetPropertyValue",
1209 "get_HostRawElementProvider",
1210 "Navigate",
1211 "GetRuntimeId",
1212 "get_FragmentRoot",
1213 "get_BoundingRectangle",
1214 "GetOverrideProviderForHwnd",
1217 static const char *get_prov_method_str(int method)
1219 if (method >= ARRAY_SIZE(prov_method_str))
1220 return NULL;
1221 else
1222 return prov_method_str[method];
1225 enum {
1226 METHOD_OPTIONAL = 0x01,
1227 METHOD_TODO = 0x02,
1230 struct prov_method_sequence {
1231 struct Provider *prov;
1232 int method;
1233 int flags;
1236 static int sequence_cnt, sequence_size;
1237 static struct prov_method_sequence *sequence;
1240 * This sequence of method calls is always used when creating an HUIANODE from
1241 * an IRawElementProviderSimple.
1243 #define NODE_CREATE_SEQ(prov) \
1244 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1245 /* Win10v1507 and below call this. */ \
1246 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1247 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1248 { prov , PROV_GET_PROPERTY_VALUE }, \
1249 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1250 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1253 * This sequence of method calls is always used when creating an HUIANODE from
1254 * an IRawElementProviderSimple that returns an HWND from get_HostRawElementProvider.
1256 #define NODE_CREATE_SEQ2(prov) \
1257 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1258 /* Win10v1507 and below call this. */ \
1259 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1260 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1261 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1262 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1264 #define NODE_CREATE_SEQ2_OPTIONAL(prov) \
1265 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1266 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1267 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1268 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1270 static void flush_method_sequence(void)
1272 HeapFree(GetProcessHeap(), 0, sequence);
1273 sequence = NULL;
1274 sequence_cnt = sequence_size = 0;
1277 static void add_method_call(struct Provider *prov, int method)
1279 struct prov_method_sequence prov_method = {0};
1281 if (!sequence)
1283 sequence_size = 10;
1284 sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
1286 if (sequence_cnt == sequence_size)
1288 sequence_size *= 2;
1289 sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
1292 prov_method.prov = prov;
1293 prov_method.method = method;
1294 prov_method.flags = 0;
1295 sequence[sequence_cnt++] = prov_method;
1298 #define ok_method_sequence( exp, context ) \
1299 ok_method_sequence_( (exp), (context), __FILE__, __LINE__)
1300 static void ok_method_sequence_(const struct prov_method_sequence *expected_list, const char *context,
1301 const char *file, int line)
1303 const struct prov_method_sequence *expected = expected_list;
1304 const struct prov_method_sequence *actual;
1305 unsigned int count = 0;
1307 add_method_call(NULL, 0);
1308 actual = sequence;
1310 if (context)
1311 winetest_push_context("%s", context);
1313 while (expected->prov && actual->prov)
1315 if (expected->prov == actual->prov && expected->method == actual->method)
1317 if (expected->flags & METHOD_TODO)
1318 todo_wine ok_(file, line)(1, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1319 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1320 expected++;
1321 actual++;
1323 else if (expected->flags & METHOD_TODO)
1325 todo_wine ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1326 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1327 expected++;
1329 else if (expected->flags & METHOD_OPTIONAL)
1330 expected++;
1331 else
1333 ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1334 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1335 expected++;
1336 actual++;
1338 count++;
1341 /* Handle trailing optional/todo_wine methods. */
1342 while (expected->prov && ((expected->flags & METHOD_OPTIONAL) ||
1343 ((expected->flags & METHOD_TODO) && !strcmp(winetest_platform, "wine"))))
1345 if (expected->flags & METHOD_TODO)
1346 todo_wine ok_(file, line)(0, "%d: expected %s_%s\n", count, expected->prov->prov_name,
1347 get_prov_method_str(expected->method));
1348 count++;
1349 expected++;
1352 if (expected->prov || actual->prov)
1354 if (expected->prov)
1355 ok_( file, line)(0, "incomplete sequence: expected %s_%s, got nothing\n", expected->prov->prov_name,
1356 get_prov_method_str(expected->method));
1357 else
1358 ok_( file, line)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual->prov->prov_name,
1359 get_prov_method_str(actual->method));
1362 if (context)
1363 winetest_pop_context();
1365 flush_method_sequence();
1369 * Parsing the string returned by UIA_ProviderDescriptionPropertyId is
1370 * the only way to know what an HUIANODE represents internally. It
1371 * returns a formatted string which always starts with:
1372 * "[pid:<process-id>,providerId:0x<hwnd-ptr> "
1373 * On Windows versions 10v1507 and below, "providerId:" is "hwnd:"
1375 * This is followed by strings for each provider it represents. These are
1376 * formatted as:
1377 * "<prov-type>:<prov-desc> (<origin>)"
1378 * and are terminated with ";", the final provider has no ";" terminator,
1379 * instead it has "]".
1381 * If the given provider is the one used for navigation towards a parent, it has
1382 * "(parent link)" as a suffix on "<prov-type>".
1384 * <prov-type> is one of "Annotation", "Main", "Override", "Hwnd", or
1385 * "Nonclient".
1387 * <prov-desc> is the string returned from calling GetPropertyValue on the
1388 * IRawElementProviderSimple being represented with a property ID of
1389 * UIA_ProviderDescriptionPropertyId.
1391 * <origin> is the name of the module that the
1392 * IRawElementProviderSimple comes from. For unmanaged code, it's:
1393 * "unmanaged:<executable>"
1394 * and for managed code, it's:
1395 * "managed:<assembly-qualified-name>"
1397 * An example:
1398 * [pid:1500,providerId:0x2F054C Main:Provider (unmanaged:uiautomation_test.exe); Hwnd(parent link):HWND Proxy (unmanaged:uiautomationcore.dll)]
1400 static BOOL get_provider_desc(BSTR prov_desc, const WCHAR *prov_type, WCHAR *out_name)
1402 const WCHAR *str, *str2;
1404 str = wcsstr(prov_desc, prov_type);
1405 if (!str)
1406 return FALSE;
1408 if (!out_name)
1409 return TRUE;
1411 str += wcslen(prov_type);
1412 str2 = wcschr(str, L'(');
1413 lstrcpynW(out_name, str, ((str2 - str)));
1415 return TRUE;
1418 #define check_node_provider_desc( prov_desc, prov_type, prov_name, parent_link ) \
1419 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), __FILE__, __LINE__)
1420 static void check_node_provider_desc_(BSTR prov_desc, const WCHAR *prov_type, const WCHAR *prov_name,
1421 BOOL parent_link, const char *file, int line)
1423 WCHAR buf[2048];
1425 if (parent_link)
1426 wsprintfW(buf, L"%s(parent link):", prov_type);
1427 else
1428 wsprintfW(buf, L"%s:", prov_type);
1430 if (!get_provider_desc(prov_desc, buf, buf))
1432 if (parent_link)
1433 wsprintfW(buf, L"%s:", prov_type);
1434 else
1435 wsprintfW(buf, L"%s(parent link):", prov_type);
1437 if (!get_provider_desc(prov_desc, buf, buf))
1439 ok_(file, line)(0, "failed to get provider string for %s\n", debugstr_w(prov_type));
1440 return;
1442 else
1444 if (parent_link)
1445 ok_(file, line)(0, "expected parent link provider %s\n", debugstr_w(prov_type));
1446 else
1447 ok_(file, line)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type));
1451 if (prov_name)
1452 ok_(file, line)(!wcscmp(prov_name, buf), "unexpected provider name %s\n", debugstr_w(buf));
1455 #define check_node_provider_desc_prefix( prov_desc, pid, prov_id ) \
1456 check_node_provider_desc_prefix_( (prov_desc), (pid), (prov_id), __FILE__, __LINE__)
1457 static void check_node_provider_desc_prefix_(BSTR prov_desc, DWORD pid, HWND prov_id, const char *file, int line)
1459 const WCHAR *str, *str2;
1460 WCHAR buf[128];
1461 DWORD prov_pid;
1462 HWND prov_hwnd;
1463 WCHAR *end;
1465 str = wcsstr(prov_desc, L"pid:");
1466 str += wcslen(L"pid:");
1467 str2 = wcschr(str, L',');
1468 lstrcpynW(buf, str, (str2 - str) + 1);
1469 prov_pid = wcstoul(buf, &end, 10);
1470 ok_(file, line)(prov_pid == pid, "Unexpected pid %lu\n", prov_pid);
1472 str = wcsstr(prov_desc, L"providerId:");
1473 if (str)
1474 str += wcslen(L"providerId:");
1475 else
1477 str = wcsstr(prov_desc, L"hwnd:");
1478 str += wcslen(L"hwnd:");
1480 str2 = wcschr(str, L' ');
1481 lstrcpynW(buf, str, (str2 - str) + 1);
1482 prov_hwnd = ULongToHandle(wcstoul(buf, &end, 16));
1483 ok_(file, line)(prov_hwnd == prov_id, "Unexpected hwnd %p\n", prov_hwnd);
1487 * For node providers that come from an HWND belonging to another process
1488 * or another thread, the provider is considered 'nested', a node in a node.
1490 static BOOL get_nested_provider_desc(BSTR prov_desc, const WCHAR *prov_type, BOOL parent_link, WCHAR *out_desc)
1492 const WCHAR *str, *str2;
1493 WCHAR buf[1024];
1495 if (!parent_link)
1496 wsprintfW(buf, L"%s:Nested ", prov_type);
1497 else
1498 wsprintfW(buf, L"%s(parent link):Nested ", prov_type);
1499 str = wcsstr(prov_desc, buf);
1500 /* Check with and without parent-link. */
1501 if (!str)
1502 return FALSE;
1504 if (!out_desc)
1505 return TRUE;
1507 str += wcslen(buf);
1508 str2 = wcschr(str, L']');
1509 /* We want to include the ']' character, so + 2. */
1510 lstrcpynW(out_desc, str, ((str2 - str) + 2));
1512 return TRUE;
1515 #define check_runtime_id( exp_runtime_id, exp_size, runtime_id ) \
1516 check_runtime_id_( (exp_runtime_id), (exp_size), (runtime_id), __FILE__, __LINE__)
1517 static void check_runtime_id_(int *exp_runtime_id, int exp_size, SAFEARRAY *runtime_id, const char *file, int line)
1519 LONG i, idx, lbound, ubound, elems;
1520 HRESULT hr;
1521 UINT dims;
1522 int val;
1524 dims = SafeArrayGetDim(runtime_id);
1525 ok_(file, line)(dims == 1, "Unexpected array dims %d\n", dims);
1527 hr = SafeArrayGetLBound(runtime_id, 1, &lbound);
1528 ok_(file, line)(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
1530 hr = SafeArrayGetUBound(runtime_id, 1, &ubound);
1531 ok_(file, line)(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
1533 elems = (ubound - lbound) + 1;
1534 ok_(file, line)(exp_size == elems, "Unexpected runtime_id array size %#lx\n", elems);
1536 for (i = 0; i < elems; i++)
1538 idx = lbound + i;
1539 hr = SafeArrayGetElement(runtime_id, &idx, &val);
1540 ok_(file, line)(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
1541 ok_(file, line)(val == exp_runtime_id[i], "Unexpected runtime_id[%ld] %#x\n", i, val);
1545 static inline struct Provider *impl_from_ProviderSimple(IRawElementProviderSimple *iface)
1547 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderSimple_iface);
1550 HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
1552 struct Provider *This = impl_from_ProviderSimple(iface);
1554 *ppv = NULL;
1555 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
1556 *ppv = iface;
1557 else if (IsEqualIID(riid, &IID_IRawElementProviderFragment))
1558 *ppv = &This->IRawElementProviderFragment_iface;
1559 else if (IsEqualIID(riid, &IID_IRawElementProviderFragmentRoot))
1560 *ppv = &This->IRawElementProviderFragmentRoot_iface;
1561 else if (IsEqualIID(riid, &IID_IRawElementProviderHwndOverride))
1562 *ppv = &This->IRawElementProviderHwndOverride_iface;
1563 else if (IsEqualIID(riid, &IID_IValueProvider))
1564 *ppv = &This->IValueProvider_iface;
1565 else
1566 return E_NOINTERFACE;
1568 IRawElementProviderSimple_AddRef(iface);
1569 return S_OK;
1572 ULONG WINAPI ProviderSimple_AddRef(IRawElementProviderSimple *iface)
1574 struct Provider *This = impl_from_ProviderSimple(iface);
1575 return InterlockedIncrement(&This->ref);
1578 ULONG WINAPI ProviderSimple_Release(IRawElementProviderSimple *iface)
1580 struct Provider *This = impl_from_ProviderSimple(iface);
1581 return InterlockedDecrement(&This->ref);
1584 HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *iface,
1585 enum ProviderOptions *ret_val)
1587 struct Provider *This = impl_from_ProviderSimple(iface);
1589 add_method_call(This, PROV_GET_PROVIDER_OPTIONS);
1590 if (This->expected_tid)
1591 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1592 This->last_call_tid = GetCurrentThreadId();
1594 *ret_val = 0;
1595 if (This->prov_opts)
1597 *ret_val = This->prov_opts;
1598 return S_OK;
1601 return E_NOTIMPL;
1604 HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface,
1605 PATTERNID pattern_id, IUnknown **ret_val)
1607 struct Provider *This = impl_from_ProviderSimple(iface);
1609 add_method_call(This, PROV_GET_PATTERN_PROV);
1610 if (This->expected_tid)
1611 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1612 This->last_call_tid = GetCurrentThreadId();
1614 *ret_val = NULL;
1615 switch (pattern_id)
1617 case UIA_ValuePatternId:
1618 if (This->value_pattern_data.is_supported)
1619 *ret_val = (IUnknown *)iface;
1620 break;
1622 default:
1623 break;
1626 if (*ret_val)
1627 IUnknown_AddRef(*ret_val);
1629 return S_OK;
1632 HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface,
1633 PROPERTYID prop_id, VARIANT *ret_val)
1635 struct Provider *This = impl_from_ProviderSimple(iface);
1637 add_method_call(This, PROV_GET_PROPERTY_VALUE);
1638 if (This->expected_tid)
1639 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1640 This->last_call_tid = GetCurrentThreadId();
1642 if (This->prop_override && This->prop_override_count)
1644 int i;
1646 for (i = 0; i < This->prop_override_count; i++)
1648 if (This->prop_override[i].prop_id == prop_id)
1650 *ret_val = This->prop_override[i].val;
1651 return S_OK;
1656 VariantInit(ret_val);
1657 switch (prop_id)
1659 case UIA_NativeWindowHandlePropertyId:
1660 if (This->ret_invalid_prop_type)
1662 V_VT(ret_val) = VT_R8;
1663 V_R8(ret_val) = uia_r8_prop_val;
1665 else if (!This->ignore_hwnd_prop)
1667 V_VT(ret_val) = VT_I4;
1668 V_I4(ret_val) = HandleToULong(This->hwnd);
1670 break;
1672 case UIA_ProcessIdPropertyId:
1673 case UIA_ControlTypePropertyId:
1674 case UIA_CulturePropertyId:
1675 case UIA_OrientationPropertyId:
1676 case UIA_LiveSettingPropertyId:
1677 case UIA_PositionInSetPropertyId:
1678 case UIA_SizeOfSetPropertyId:
1679 case UIA_LevelPropertyId:
1680 case UIA_LandmarkTypePropertyId:
1681 case UIA_FillColorPropertyId:
1682 case UIA_FillTypePropertyId:
1683 case UIA_VisualEffectsPropertyId:
1684 case UIA_HeadingLevelPropertyId:
1685 if (This->ret_invalid_prop_type)
1687 V_VT(ret_val) = VT_R8;
1688 V_R8(ret_val) = uia_r8_prop_val;
1690 else
1692 V_VT(ret_val) = VT_I4;
1693 V_I4(ret_val) = uia_i4_prop_val;
1695 break;
1697 case UIA_RotationPropertyId:
1698 if (This->ret_invalid_prop_type)
1700 V_VT(ret_val) = VT_I4;
1701 V_I4(ret_val) = uia_i4_prop_val;
1703 else
1705 V_VT(ret_val) = VT_R8;
1706 V_R8(ret_val) = uia_r8_prop_val;
1708 break;
1710 case UIA_LocalizedControlTypePropertyId:
1711 case UIA_NamePropertyId:
1712 case UIA_AcceleratorKeyPropertyId:
1713 case UIA_AccessKeyPropertyId:
1714 case UIA_AutomationIdPropertyId:
1715 case UIA_ClassNamePropertyId:
1716 case UIA_HelpTextPropertyId:
1717 case UIA_ItemTypePropertyId:
1718 case UIA_FrameworkIdPropertyId:
1719 case UIA_ItemStatusPropertyId:
1720 case UIA_AriaRolePropertyId:
1721 case UIA_AriaPropertiesPropertyId:
1722 case UIA_LocalizedLandmarkTypePropertyId:
1723 case UIA_FullDescriptionPropertyId:
1724 if (This->ret_invalid_prop_type)
1726 V_VT(ret_val) = VT_I4;
1727 V_I4(ret_val) = uia_i4_prop_val;
1729 else
1731 V_VT(ret_val) = VT_BSTR;
1732 V_BSTR(ret_val) = SysAllocString(uia_bstr_prop_str);
1734 break;
1736 case UIA_HasKeyboardFocusPropertyId:
1737 case UIA_IsKeyboardFocusablePropertyId:
1738 case UIA_IsEnabledPropertyId:
1739 case UIA_IsControlElementPropertyId:
1740 case UIA_IsContentElementPropertyId:
1741 case UIA_IsPasswordPropertyId:
1742 case UIA_IsOffscreenPropertyId:
1743 case UIA_IsRequiredForFormPropertyId:
1744 case UIA_IsDataValidForFormPropertyId:
1745 case UIA_OptimizeForVisualContentPropertyId:
1746 case UIA_IsPeripheralPropertyId:
1747 case UIA_IsDialogPropertyId:
1748 if (This->ret_invalid_prop_type)
1750 V_VT(ret_val) = VT_R8;
1751 V_R8(ret_val) = uia_r8_prop_val;
1753 else
1755 V_VT(ret_val) = VT_BOOL;
1756 V_BOOL(ret_val) = VARIANT_TRUE;
1758 break;
1760 case UIA_AnnotationTypesPropertyId:
1761 case UIA_OutlineColorPropertyId:
1762 if (This->ret_invalid_prop_type)
1764 V_VT(ret_val) = VT_ARRAY | VT_R8;
1765 V_ARRAY(ret_val) = create_r8_safearray();
1767 else
1769 V_VT(ret_val) = VT_ARRAY | VT_I4;
1770 V_ARRAY(ret_val) = create_i4_safearray();
1772 break;
1774 case UIA_OutlineThicknessPropertyId:
1775 case UIA_SizePropertyId:
1776 if (This->ret_invalid_prop_type)
1778 V_VT(ret_val) = VT_ARRAY | VT_I4;
1779 V_ARRAY(ret_val) = create_i4_safearray();
1781 else
1783 V_VT(ret_val) = VT_ARRAY | VT_R8;
1784 V_ARRAY(ret_val) = create_r8_safearray();
1786 break;
1788 case UIA_LabeledByPropertyId:
1789 if (This->ret_invalid_prop_type)
1791 V_VT(ret_val) = VT_I4;
1792 V_I4(ret_val) = uia_i4_prop_val;
1794 else
1796 V_VT(ret_val) = VT_UNKNOWN;
1797 V_UNKNOWN(ret_val) = (IUnknown *)&Provider_child.IRawElementProviderSimple_iface;
1798 IUnknown_AddRef(V_UNKNOWN(ret_val));
1800 break;
1802 case UIA_AnnotationObjectsPropertyId:
1803 case UIA_DescribedByPropertyId:
1804 case UIA_FlowsFromPropertyId:
1805 case UIA_FlowsToPropertyId:
1806 case UIA_ControllerForPropertyId:
1807 if (This->ret_invalid_prop_type)
1809 V_VT(ret_val) = VT_ARRAY | VT_I4;
1810 V_ARRAY(ret_val) = create_i4_safearray();
1812 else
1814 V_VT(ret_val) = VT_UNKNOWN | VT_ARRAY;
1815 V_ARRAY(ret_val) = create_unk_safearray();
1817 break;
1819 case UIA_ProviderDescriptionPropertyId:
1821 WCHAR buf[1024] = {};
1823 mbstowcs(buf, This->prov_name, strlen(This->prov_name));
1824 V_VT(ret_val) = VT_BSTR;
1825 V_BSTR(ret_val) = SysAllocString(buf);
1826 break;
1829 default:
1830 break;
1833 return S_OK;
1836 HRESULT WINAPI ProviderSimple_get_HostRawElementProvider(IRawElementProviderSimple *iface,
1837 IRawElementProviderSimple **ret_val)
1839 struct Provider *This = impl_from_ProviderSimple(iface);
1841 add_method_call(This, PROV_GET_HOST_RAW_ELEMENT_PROVIDER);
1842 if (This->expected_tid)
1843 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1844 This->last_call_tid = GetCurrentThreadId();
1846 *ret_val = NULL;
1847 if (This->hwnd)
1848 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
1850 return S_OK;
1853 IRawElementProviderSimpleVtbl ProviderSimpleVtbl = {
1854 ProviderSimple_QueryInterface,
1855 ProviderSimple_AddRef,
1856 ProviderSimple_Release,
1857 ProviderSimple_get_ProviderOptions,
1858 ProviderSimple_GetPatternProvider,
1859 ProviderSimple_GetPropertyValue,
1860 ProviderSimple_get_HostRawElementProvider,
1863 static inline struct Provider *impl_from_ProviderFragment(IRawElementProviderFragment *iface)
1865 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderFragment_iface);
1868 static HRESULT WINAPI ProviderFragment_QueryInterface(IRawElementProviderFragment *iface, REFIID riid,
1869 void **ppv)
1871 struct Provider *Provider = impl_from_ProviderFragment(iface);
1872 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
1875 static ULONG WINAPI ProviderFragment_AddRef(IRawElementProviderFragment *iface)
1877 struct Provider *Provider = impl_from_ProviderFragment(iface);
1878 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
1881 static ULONG WINAPI ProviderFragment_Release(IRawElementProviderFragment *iface)
1883 struct Provider *Provider = impl_from_ProviderFragment(iface);
1884 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
1887 static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *iface,
1888 enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
1890 struct Provider *This = impl_from_ProviderFragment(iface);
1892 add_method_call(This, FRAG_NAVIGATE);
1893 if (This->expected_tid)
1894 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1895 This->last_call_tid = GetCurrentThreadId();
1897 *ret_val = NULL;
1898 switch (direction)
1900 case NavigateDirection_Parent:
1901 *ret_val = This->parent;
1902 break;
1904 case NavigateDirection_NextSibling:
1905 *ret_val = This->next_sibling;
1906 break;
1908 case NavigateDirection_PreviousSibling:
1909 *ret_val = This->prev_sibling;
1910 break;
1912 case NavigateDirection_FirstChild:
1913 *ret_val = This->first_child;
1914 break;
1916 case NavigateDirection_LastChild:
1917 *ret_val = This->last_child;
1918 break;
1920 default:
1921 trace("Invalid navigate direction %d\n", direction);
1922 break;
1925 if (*ret_val)
1926 IRawElementProviderFragment_AddRef(*ret_val);
1928 return S_OK;
1931 static HRESULT WINAPI ProviderFragment_GetRuntimeId(IRawElementProviderFragment *iface,
1932 SAFEARRAY **ret_val)
1934 struct Provider *This = impl_from_ProviderFragment(iface);
1936 add_method_call(This, FRAG_GET_RUNTIME_ID);
1937 if (This->expected_tid)
1938 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1939 This->last_call_tid = GetCurrentThreadId();
1941 *ret_val = NULL;
1942 if (This->runtime_id[0] || This->runtime_id[1])
1944 SAFEARRAY *sa;
1945 LONG idx;
1947 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(This->runtime_id))))
1948 return E_FAIL;
1950 for (idx = 0; idx < ARRAY_SIZE(This->runtime_id); idx++)
1951 SafeArrayPutElement(sa, &idx, (void *)&This->runtime_id[idx]);
1953 *ret_val = sa;
1956 return S_OK;
1959 static HRESULT WINAPI ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment *iface,
1960 struct UiaRect *ret_val)
1962 struct Provider *This = impl_from_ProviderFragment(iface);
1964 add_method_call(This, FRAG_GET_BOUNDING_RECT);
1965 if (This->expected_tid)
1966 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1967 This->last_call_tid = GetCurrentThreadId();
1969 *ret_val = This->bounds_rect;
1970 return S_OK;
1973 static HRESULT WINAPI ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface,
1974 SAFEARRAY **ret_val)
1976 ok(0, "unexpected call\n");
1977 *ret_val = NULL;
1978 return E_NOTIMPL;
1981 static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *iface)
1983 ok(0, "unexpected call\n");
1984 return E_NOTIMPL;
1987 static HRESULT WINAPI ProviderFragment_get_FragmentRoot(IRawElementProviderFragment *iface,
1988 IRawElementProviderFragmentRoot **ret_val)
1990 struct Provider *This = impl_from_ProviderFragment(iface);
1992 add_method_call(This, FRAG_GET_FRAGMENT_ROOT);
1993 if (This->expected_tid)
1994 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1995 This->last_call_tid = GetCurrentThreadId();
1997 *ret_val = NULL;
1998 if (This->frag_root)
2000 *ret_val = This->frag_root;
2001 IRawElementProviderFragmentRoot_AddRef(This->frag_root);
2004 return S_OK;
2007 static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl = {
2008 ProviderFragment_QueryInterface,
2009 ProviderFragment_AddRef,
2010 ProviderFragment_Release,
2011 ProviderFragment_Navigate,
2012 ProviderFragment_GetRuntimeId,
2013 ProviderFragment_get_BoundingRectangle,
2014 ProviderFragment_GetEmbeddedFragmentRoots,
2015 ProviderFragment_SetFocus,
2016 ProviderFragment_get_FragmentRoot,
2019 static inline struct Provider *impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot *iface)
2021 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderFragmentRoot_iface);
2024 static HRESULT WINAPI ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot *iface, REFIID riid,
2025 void **ppv)
2027 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2028 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2031 static ULONG WINAPI ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot *iface)
2033 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2034 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2037 static ULONG WINAPI ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot *iface)
2039 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2040 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2043 static HRESULT WINAPI ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot *iface,
2044 double x, double y, IRawElementProviderFragment **ret_val)
2046 ok(0, "unexpected call\n");
2047 return E_NOTIMPL;
2050 static HRESULT WINAPI ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot *iface,
2051 IRawElementProviderFragment **ret_val)
2053 ok(0, "unexpected call\n");
2054 return E_NOTIMPL;
2057 static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl = {
2058 ProviderFragmentRoot_QueryInterface,
2059 ProviderFragmentRoot_AddRef,
2060 ProviderFragmentRoot_Release,
2061 ProviderFragmentRoot_ElementProviderFromPoint,
2062 ProviderFragmentRoot_GetFocus,
2065 static inline struct Provider *impl_from_ProviderHwndOverride(IRawElementProviderHwndOverride *iface)
2067 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderHwndOverride_iface);
2070 static HRESULT WINAPI ProviderHwndOverride_QueryInterface(IRawElementProviderHwndOverride *iface, REFIID riid,
2071 void **ppv)
2073 struct Provider *Provider = impl_from_ProviderHwndOverride(iface);
2074 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2077 static ULONG WINAPI ProviderHwndOverride_AddRef(IRawElementProviderHwndOverride *iface)
2079 struct Provider *Provider = impl_from_ProviderHwndOverride(iface);
2080 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2083 static ULONG WINAPI ProviderHwndOverride_Release(IRawElementProviderHwndOverride *iface)
2085 struct Provider *Provider = impl_from_ProviderHwndOverride(iface);
2086 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2089 static HRESULT WINAPI ProviderHwndOverride_GetOverrideProviderForHwnd(IRawElementProviderHwndOverride *iface,
2090 HWND hwnd, IRawElementProviderSimple **ret_val)
2092 struct Provider *This = impl_from_ProviderHwndOverride(iface);
2094 add_method_call(This, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER);
2096 *ret_val = NULL;
2097 if (This->override_hwnd == hwnd)
2099 return IRawElementProviderSimple_QueryInterface(&Provider_override.IRawElementProviderSimple_iface,
2100 &IID_IRawElementProviderSimple, (void **)ret_val);
2103 return S_OK;
2106 static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl = {
2107 ProviderHwndOverride_QueryInterface,
2108 ProviderHwndOverride_AddRef,
2109 ProviderHwndOverride_Release,
2110 ProviderHwndOverride_GetOverrideProviderForHwnd,
2113 static inline struct Provider *impl_from_ProviderValuePattern(IValueProvider *iface)
2115 return CONTAINING_RECORD(iface, struct Provider, IValueProvider_iface);
2118 static HRESULT WINAPI ProviderValuePattern_QueryInterface(IValueProvider *iface, REFIID riid,
2119 void **ppv)
2121 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2122 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2125 static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface)
2127 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2128 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2131 static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface)
2133 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2134 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2137 static HRESULT WINAPI ProviderValuePattern_SetValue(IValueProvider *iface, LPCWSTR val)
2139 ok(0, "unexpected call\n");
2140 return E_NOTIMPL;
2143 static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
2145 ok(0, "unexpected call\n");
2146 return E_NOTIMPL;
2149 static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val)
2151 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2153 *ret_val = Provider->value_pattern_data.is_read_only;
2155 return S_OK;
2158 static const IValueProviderVtbl ProviderValuePatternVtbl = {
2159 ProviderValuePattern_QueryInterface,
2160 ProviderValuePattern_AddRef,
2161 ProviderValuePattern_Release,
2162 ProviderValuePattern_SetValue,
2163 ProviderValuePattern_get_Value,
2164 ProviderValuePattern_get_IsReadOnly,
2167 static struct Provider Provider =
2169 { &ProviderSimpleVtbl },
2170 { &ProviderFragmentVtbl },
2171 { &ProviderFragmentRootVtbl },
2172 { &ProviderHwndOverrideVtbl },
2173 { &ProviderValuePatternVtbl },
2175 "Provider",
2176 NULL, NULL,
2177 NULL, NULL,
2178 &Provider_child.IRawElementProviderFragment_iface, &Provider_child2.IRawElementProviderFragment_iface,
2179 0, 0, 0,
2182 static struct Provider Provider2 =
2184 { &ProviderSimpleVtbl },
2185 { &ProviderFragmentVtbl },
2186 { &ProviderFragmentRootVtbl },
2187 { &ProviderHwndOverrideVtbl },
2188 { &ProviderValuePatternVtbl },
2190 "Provider2",
2191 NULL, NULL,
2192 NULL, NULL,
2193 NULL, NULL,
2194 0, 0, 0,
2197 static struct Provider Provider_child =
2199 { &ProviderSimpleVtbl },
2200 { &ProviderFragmentVtbl },
2201 { &ProviderFragmentRootVtbl },
2202 { &ProviderHwndOverrideVtbl },
2203 { &ProviderValuePatternVtbl },
2205 "Provider_child",
2206 &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
2207 NULL, &Provider_child2.IRawElementProviderFragment_iface,
2208 NULL, NULL,
2209 ProviderOptions_ServerSideProvider, 0, 0,
2212 static struct Provider Provider_child2 =
2214 { &ProviderSimpleVtbl },
2215 { &ProviderFragmentVtbl },
2216 { &ProviderFragmentRootVtbl },
2217 { &ProviderHwndOverrideVtbl },
2218 { &ProviderValuePatternVtbl },
2220 "Provider_child2",
2221 &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
2222 &Provider_child.IRawElementProviderFragment_iface, NULL,
2223 NULL, NULL,
2224 ProviderOptions_ServerSideProvider, 0, 0,
2227 static struct Provider Provider_hwnd =
2229 { &ProviderSimpleVtbl },
2230 { &ProviderFragmentVtbl },
2231 { &ProviderFragmentRootVtbl },
2232 { &ProviderHwndOverrideVtbl },
2233 { &ProviderValuePatternVtbl },
2235 "Provider_hwnd",
2236 NULL, NULL,
2237 NULL, NULL,
2238 NULL, NULL,
2239 ProviderOptions_ClientSideProvider, 0, 0,
2242 static struct Provider Provider_nc =
2244 { &ProviderSimpleVtbl },
2245 { &ProviderFragmentVtbl },
2246 { &ProviderFragmentRootVtbl },
2247 { &ProviderHwndOverrideVtbl },
2248 { &ProviderValuePatternVtbl },
2250 "Provider_nc",
2251 NULL, NULL,
2252 NULL, NULL,
2253 NULL, NULL,
2254 ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider,
2255 0, 0,
2258 static struct Provider Provider_proxy =
2260 { &ProviderSimpleVtbl },
2261 { &ProviderFragmentVtbl },
2262 { &ProviderFragmentRootVtbl },
2263 { &ProviderHwndOverrideVtbl },
2264 { &ProviderValuePatternVtbl },
2266 "Provider_proxy",
2267 NULL, NULL,
2268 NULL, NULL,
2269 NULL, NULL,
2270 ProviderOptions_ClientSideProvider,
2271 0, 0,
2274 static struct Provider Provider_proxy2 =
2276 { &ProviderSimpleVtbl },
2277 { &ProviderFragmentVtbl },
2278 { &ProviderFragmentRootVtbl },
2279 { &ProviderHwndOverrideVtbl },
2280 { &ProviderValuePatternVtbl },
2282 "Provider_proxy2",
2283 NULL, NULL,
2284 NULL, NULL,
2285 NULL, NULL,
2286 ProviderOptions_ClientSideProvider,
2287 0, 0,
2290 static struct Provider Provider_override =
2292 { &ProviderSimpleVtbl },
2293 { &ProviderFragmentVtbl },
2294 { &ProviderFragmentRootVtbl },
2295 { &ProviderHwndOverrideVtbl },
2296 { &ProviderValuePatternVtbl },
2298 "Provider_override",
2299 NULL, NULL,
2300 NULL, NULL,
2301 NULL, NULL,
2302 ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider,
2303 0, 0,
2306 #define DEFINE_PROVIDER(name) \
2307 static struct Provider Provider_ ## name = \
2309 { &ProviderSimpleVtbl }, \
2310 { &ProviderFragmentVtbl }, \
2311 { &ProviderFragmentRootVtbl }, \
2312 { &ProviderHwndOverrideVtbl }, \
2313 { &ProviderValuePatternVtbl }, \
2314 1, \
2315 "Provider_" # name "", \
2316 NULL, NULL, \
2317 NULL, NULL, \
2318 NULL, NULL, \
2319 ProviderOptions_ServerSideProvider, 0, 0 \
2322 DEFINE_PROVIDER(hwnd_child);
2323 DEFINE_PROVIDER(hwnd_child2);
2324 DEFINE_PROVIDER(nc_child);
2325 DEFINE_PROVIDER(nc_child2);
2326 DEFINE_PROVIDER(child_child);
2327 DEFINE_PROVIDER(child_child2);
2328 DEFINE_PROVIDER(child2_child);
2329 DEFINE_PROVIDER(child2_child_child);
2331 static IAccessible *acc_client;
2332 static IRawElementProviderSimple *prov_root;
2333 static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2335 switch (message)
2337 case WM_GETOBJECT:
2338 if (lParam == (DWORD)OBJID_CLIENT)
2340 CHECK_EXPECT(winproc_GETOBJECT_CLIENT);
2341 if (acc_client)
2342 return LresultFromObject(&IID_IAccessible, wParam, (IUnknown *)acc_client);
2344 break;
2346 else if (lParam == UiaRootObjectId)
2348 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot);
2349 if (prov_root)
2350 return UiaReturnRawElementProvider(hwnd, wParam, lParam, prov_root);
2352 break;
2355 break;
2357 default:
2358 break;
2361 return DefWindowProcA(hwnd, message, wParam, lParam);
2364 static IRawElementProviderSimple *child_win_prov_root;
2365 static LRESULT WINAPI child_test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
2367 switch (message)
2369 case WM_GETOBJECT:
2370 if (lParam == UiaRootObjectId)
2372 CHECK_EXPECT(child_winproc_GETOBJECT_UiaRoot);
2373 if (child_win_prov_root)
2374 return UiaReturnRawElementProvider(hwnd, wParam, lParam, child_win_prov_root);
2376 break;
2379 break;
2381 default:
2382 break;
2385 return DefWindowProcA(hwnd, message, wParam, lParam);
2388 static void test_UiaHostProviderFromHwnd(void)
2390 IRawElementProviderSimple *p, *p2;
2391 enum ProviderOptions prov_opt;
2392 WNDCLASSA cls;
2393 HRESULT hr;
2394 HWND hwnd;
2395 VARIANT v;
2396 int i;
2398 cls.style = 0;
2399 cls.lpfnWndProc = test_wnd_proc;
2400 cls.cbClsExtra = 0;
2401 cls.cbWndExtra = 0;
2402 cls.hInstance = GetModuleHandleA(NULL);
2403 cls.hIcon = 0;
2404 cls.hCursor = NULL;
2405 cls.hbrBackground = NULL;
2406 cls.lpszMenuName = NULL;
2407 cls.lpszClassName = "HostProviderFromHwnd class";
2409 RegisterClassA(&cls);
2411 hwnd = CreateWindowExA(0, "HostProviderFromHwnd class", "Test window 1",
2412 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE,
2413 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
2414 ok(hwnd != NULL, "Failed to create a test window.\n");
2416 p = (void *)0xdeadbeef;
2417 hr = UiaHostProviderFromHwnd(NULL, &p);
2418 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2419 ok(p == NULL, "Unexpected instance.\n");
2421 hr = UiaHostProviderFromHwnd(hwnd, NULL);
2422 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2424 p = NULL;
2425 hr = UiaHostProviderFromHwnd(hwnd, &p);
2426 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
2428 p2 = NULL;
2429 hr = UiaHostProviderFromHwnd(hwnd, &p2);
2430 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
2431 ok(p != p2, "Unexpected instance.\n");
2432 IRawElementProviderSimple_Release(p2);
2434 hr = IRawElementProviderSimple_get_HostRawElementProvider(p, &p2);
2435 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2436 ok(p2 == NULL, "Unexpected instance.\n");
2438 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
2439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2440 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
2441 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
2443 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
2444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2445 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
2446 VariantClear(&v);
2448 /* No patterns are implemented on the HWND Host provider. */
2449 for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++)
2451 IUnknown *unk;
2453 unk = (void *)0xdeadbeef;
2454 hr = IRawElementProviderSimple_GetPatternProvider(p, i, &unk);
2455 ok(hr == S_OK, "Unexpected hr %#lx, %d.\n", hr, i);
2456 ok(!unk, "Pattern %d returned %p\n", i, unk);
2459 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
2460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2461 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
2462 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
2463 "Unexpected provider options %#x\n", prov_opt);
2465 /* Test behavior post Window destruction. */
2466 DestroyWindow(hwnd);
2468 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
2469 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2470 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
2471 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
2473 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
2474 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2475 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
2476 VariantClear(&v);
2478 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
2479 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2480 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
2481 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
2482 "Unexpected provider options %#x\n", prov_opt);
2484 IRawElementProviderSimple_Release(p);
2486 UnregisterClassA("HostProviderFromHwnd class", NULL);
2489 static DWORD WINAPI uia_reserved_val_iface_marshal_thread(LPVOID param)
2491 IStream **stream = param;
2492 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
2493 HRESULT hr;
2495 CoInitializeEx(NULL, COINIT_MULTITHREADED);
2497 hr = CoGetInterfaceAndReleaseStream(stream[0], &IID_IUnknown, (void **)&unk_ns);
2498 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2500 hr = CoGetInterfaceAndReleaseStream(stream[1], &IID_IUnknown, (void **)&unk_ma);
2501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2503 hr = UiaGetReservedNotSupportedValue(&unk_ns2);
2504 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2506 hr = UiaGetReservedMixedAttributeValue(&unk_ma2);
2507 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2509 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
2510 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
2512 CoUninitialize();
2514 return 0;
2517 static void test_uia_reserved_value_ifaces(void)
2519 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
2520 IStream *stream[2];
2521 IMarshal *marshal;
2522 HANDLE thread;
2523 ULONG refcnt;
2524 HRESULT hr;
2526 /* ReservedNotSupportedValue. */
2527 hr = UiaGetReservedNotSupportedValue(NULL);
2528 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2530 hr = UiaGetReservedNotSupportedValue(&unk_ns);
2531 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2532 ok(unk_ns != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.\n");
2534 refcnt = IUnknown_AddRef(unk_ns);
2535 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2537 refcnt = IUnknown_AddRef(unk_ns);
2538 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2540 refcnt = IUnknown_Release(unk_ns);
2541 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2543 hr = UiaGetReservedNotSupportedValue(&unk_ns2);
2544 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2545 ok(unk_ns2 != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.");
2546 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
2548 marshal = NULL;
2549 hr = IUnknown_QueryInterface(unk_ns, &IID_IMarshal, (void **)&marshal);
2550 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2551 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
2553 refcnt = IMarshal_AddRef(marshal);
2554 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
2556 refcnt = IMarshal_Release(marshal);
2557 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2559 refcnt = IMarshal_Release(marshal);
2560 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
2562 /* ReservedMixedAttributeValue. */
2563 hr = UiaGetReservedMixedAttributeValue(NULL);
2564 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
2566 hr = UiaGetReservedMixedAttributeValue(&unk_ma);
2567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2568 ok(unk_ma != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
2570 refcnt = IUnknown_AddRef(unk_ma);
2571 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2573 refcnt = IUnknown_AddRef(unk_ma);
2574 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2576 refcnt = IUnknown_Release(unk_ma);
2577 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2579 hr = UiaGetReservedMixedAttributeValue(&unk_ma2);
2580 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2581 ok(unk_ma2 != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
2582 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
2584 marshal = NULL;
2585 hr = IUnknown_QueryInterface(unk_ma, &IID_IMarshal, (void **)&marshal);
2586 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2587 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
2589 refcnt = IMarshal_AddRef(marshal);
2590 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
2592 refcnt = IMarshal_Release(marshal);
2593 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
2595 refcnt = IMarshal_Release(marshal);
2596 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
2598 /* Test cross-thread marshaling behavior. */
2599 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
2601 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, unk_ns, &stream[0]);
2602 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2603 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, unk_ma, &stream[1]);
2604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2606 thread = CreateThread(NULL, 0, uia_reserved_val_iface_marshal_thread, (void *)stream, 0, NULL);
2607 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
2609 MSG msg;
2610 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
2612 TranslateMessage(&msg);
2613 DispatchMessageW(&msg);
2616 CloseHandle(thread);
2618 CoUninitialize();
2621 struct msaa_role_uia_type {
2622 INT acc_role;
2623 INT uia_control_type;
2626 static const struct msaa_role_uia_type msaa_role_uia_types[] = {
2627 { ROLE_SYSTEM_TITLEBAR, UIA_TitleBarControlTypeId },
2628 { ROLE_SYSTEM_MENUBAR, UIA_MenuBarControlTypeId },
2629 { ROLE_SYSTEM_SCROLLBAR, UIA_ScrollBarControlTypeId },
2630 { ROLE_SYSTEM_GRIP, UIA_ThumbControlTypeId },
2631 { ROLE_SYSTEM_WINDOW, UIA_WindowControlTypeId },
2632 { ROLE_SYSTEM_MENUPOPUP, UIA_MenuControlTypeId },
2633 { ROLE_SYSTEM_MENUITEM, UIA_MenuItemControlTypeId },
2634 { ROLE_SYSTEM_TOOLTIP, UIA_ToolTipControlTypeId },
2635 { ROLE_SYSTEM_APPLICATION, UIA_WindowControlTypeId },
2636 { ROLE_SYSTEM_DOCUMENT, UIA_DocumentControlTypeId },
2637 { ROLE_SYSTEM_PANE, UIA_PaneControlTypeId },
2638 { ROLE_SYSTEM_GROUPING, UIA_GroupControlTypeId },
2639 { ROLE_SYSTEM_SEPARATOR, UIA_SeparatorControlTypeId },
2640 { ROLE_SYSTEM_TOOLBAR, UIA_ToolBarControlTypeId },
2641 { ROLE_SYSTEM_STATUSBAR, UIA_StatusBarControlTypeId },
2642 { ROLE_SYSTEM_TABLE, UIA_TableControlTypeId },
2643 { ROLE_SYSTEM_COLUMNHEADER, UIA_HeaderControlTypeId },
2644 { ROLE_SYSTEM_ROWHEADER, UIA_HeaderControlTypeId },
2645 { ROLE_SYSTEM_CELL, UIA_DataItemControlTypeId },
2646 { ROLE_SYSTEM_LINK, UIA_HyperlinkControlTypeId },
2647 { ROLE_SYSTEM_LIST, UIA_ListControlTypeId },
2648 { ROLE_SYSTEM_LISTITEM, UIA_ListItemControlTypeId },
2649 { ROLE_SYSTEM_OUTLINE, UIA_TreeControlTypeId },
2650 { ROLE_SYSTEM_OUTLINEITEM, UIA_TreeItemControlTypeId },
2651 { ROLE_SYSTEM_PAGETAB, UIA_TabItemControlTypeId },
2652 { ROLE_SYSTEM_INDICATOR, UIA_ThumbControlTypeId },
2653 { ROLE_SYSTEM_GRAPHIC, UIA_ImageControlTypeId },
2654 { ROLE_SYSTEM_STATICTEXT, UIA_TextControlTypeId },
2655 { ROLE_SYSTEM_TEXT, UIA_EditControlTypeId },
2656 { ROLE_SYSTEM_PUSHBUTTON, UIA_ButtonControlTypeId },
2657 { ROLE_SYSTEM_CHECKBUTTON, UIA_CheckBoxControlTypeId },
2658 { ROLE_SYSTEM_RADIOBUTTON, UIA_RadioButtonControlTypeId },
2659 { ROLE_SYSTEM_COMBOBOX, UIA_ComboBoxControlTypeId },
2660 { ROLE_SYSTEM_PROGRESSBAR, UIA_ProgressBarControlTypeId },
2661 { ROLE_SYSTEM_SLIDER, UIA_SliderControlTypeId },
2662 { ROLE_SYSTEM_SPINBUTTON, UIA_SpinnerControlTypeId },
2663 { ROLE_SYSTEM_BUTTONDROPDOWN, UIA_SplitButtonControlTypeId },
2664 { ROLE_SYSTEM_BUTTONMENU, UIA_MenuItemControlTypeId },
2665 { ROLE_SYSTEM_BUTTONDROPDOWNGRID, UIA_ButtonControlTypeId },
2666 { ROLE_SYSTEM_PAGETABLIST, UIA_TabControlTypeId },
2667 { ROLE_SYSTEM_SPLITBUTTON, UIA_SplitButtonControlTypeId },
2668 /* These accessible roles have no equivalent in UI Automation. */
2669 { ROLE_SYSTEM_SOUND, 0 },
2670 { ROLE_SYSTEM_CURSOR, 0 },
2671 { ROLE_SYSTEM_CARET, 0 },
2672 { ROLE_SYSTEM_ALERT, 0 },
2673 { ROLE_SYSTEM_CLIENT, 0 },
2674 { ROLE_SYSTEM_CHART, 0 },
2675 { ROLE_SYSTEM_DIALOG, 0 },
2676 { ROLE_SYSTEM_BORDER, 0 },
2677 { ROLE_SYSTEM_COLUMN, 0 },
2678 { ROLE_SYSTEM_ROW, 0 },
2679 { ROLE_SYSTEM_HELPBALLOON, 0 },
2680 { ROLE_SYSTEM_CHARACTER, 0 },
2681 { ROLE_SYSTEM_PROPERTYPAGE, 0 },
2682 { ROLE_SYSTEM_DROPLIST, 0 },
2683 { ROLE_SYSTEM_DIAL, 0 },
2684 { ROLE_SYSTEM_HOTKEYFIELD, 0 },
2685 { ROLE_SYSTEM_DIAGRAM, 0 },
2686 { ROLE_SYSTEM_ANIMATION, 0 },
2687 { ROLE_SYSTEM_EQUATION, 0 },
2688 { ROLE_SYSTEM_WHITESPACE, 0 },
2689 { ROLE_SYSTEM_IPADDRESS, 0 },
2690 { ROLE_SYSTEM_OUTLINEBUTTON, 0 },
2693 struct msaa_state_uia_prop {
2694 INT acc_state;
2695 INT prop_id;
2698 static const struct msaa_state_uia_prop msaa_state_uia_props[] = {
2699 { STATE_SYSTEM_FOCUSED, UIA_HasKeyboardFocusPropertyId },
2700 { STATE_SYSTEM_FOCUSABLE, UIA_IsKeyboardFocusablePropertyId },
2701 { ~STATE_SYSTEM_UNAVAILABLE, UIA_IsEnabledPropertyId },
2702 { STATE_SYSTEM_PROTECTED, UIA_IsPasswordPropertyId },
2705 static void set_accessible_props(struct Accessible *acc, INT role, INT state,
2706 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height)
2709 acc->role = role;
2710 acc->state = state;
2711 acc->child_count = child_count;
2712 acc->name = name;
2713 acc->left = left;
2714 acc->top = top;
2715 acc->width = width;
2716 acc->height = height;
2719 static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id)
2721 acc->enable_ia2 = enable_ia2;
2722 acc->unique_id = unique_id;
2725 static void test_uia_prov_from_acc_ia2(void)
2727 IRawElementProviderSimple *elprov, *elprov2;
2728 HRESULT hr;
2730 /* Only one exposes an IA2 interface, no match. */
2731 set_accessible_props(&Accessible, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
2732 set_accessible_ia2_props(&Accessible, TRUE, 0);
2733 set_accessible_props(&Accessible2, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
2734 set_accessible_ia2_props(&Accessible2, FALSE, 0);
2736 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
2737 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2738 if (Accessible.ref != 3)
2740 IRawElementProviderSimple_Release(elprov);
2741 win_skip("UiaProviderFromIAccessible has no IAccessible2 support, skipping tests.\n");
2742 return;
2745 acc_client = &Accessible2.IAccessible_iface;
2746 SET_EXPECT(winproc_GETOBJECT_CLIENT);
2747 elprov2 = (void *)0xdeadbeef;
2748 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2750 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
2751 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
2752 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
2754 elprov2 = (void *)0xdeadbeef;
2755 acc_client = NULL;
2756 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2757 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2758 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
2760 IRawElementProviderSimple_Release(elprov);
2761 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
2764 * If &Accessible returns a failure code on get_uniqueID, &Accessible2's
2765 * uniqueID is not checked.
2767 set_accessible_ia2_props(&Accessible, TRUE, 0);
2768 set_accessible_ia2_props(&Accessible2, TRUE, 0);
2769 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
2770 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2771 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
2773 acc_client = &Accessible2.IAccessible_iface;
2774 SET_EXPECT(winproc_GETOBJECT_CLIENT);
2775 SET_EXPECT(Accessible_get_accRole);
2776 SET_EXPECT(Accessible_get_accState);
2777 SET_EXPECT(Accessible_get_accChildCount);
2778 SET_EXPECT(Accessible_accLocation);
2779 SET_EXPECT(Accessible_get_accName);
2780 SET_EXPECT(Accessible_get_uniqueID);
2781 SET_EXPECT(Accessible2_get_accChildCount);
2782 SET_EXPECT(Accessible2_get_accName);
2783 SET_EXPECT(Accessible2_QI_IAccIdentity);
2784 SET_EXPECT(Accessible2_get_accParent);
2785 elprov2 = (void *)0xdeadbeef;
2786 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2787 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2788 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
2789 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
2790 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
2791 CHECK_CALLED(Accessible_get_accRole);
2792 CHECK_CALLED(Accessible_get_accState);
2793 CHECK_CALLED(Accessible_get_accChildCount);
2794 CHECK_CALLED(Accessible_accLocation);
2795 CHECK_CALLED(Accessible_get_accName);
2796 CHECK_CALLED(Accessible_get_uniqueID);
2797 CHECK_CALLED(Accessible2_get_accChildCount);
2798 CHECK_CALLED(Accessible2_get_accName);
2799 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
2800 todo_wine CHECK_CALLED(Accessible2_get_accParent);
2801 IRawElementProviderSimple_Release(elprov2);
2803 elprov2 = (void *)0xdeadbeef;
2804 acc_client = NULL;
2805 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2806 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2807 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
2808 IRawElementProviderSimple_Release(elprov2);
2810 IRawElementProviderSimple_Release(elprov);
2811 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
2813 /* Unique ID matches. */
2814 set_accessible_ia2_props(&Accessible, TRUE, 1);
2815 set_accessible_ia2_props(&Accessible2, TRUE, 1);
2816 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
2817 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2818 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
2820 acc_client = &Accessible2.IAccessible_iface;
2821 SET_EXPECT(winproc_GETOBJECT_CLIENT);
2822 SET_EXPECT(Accessible_get_uniqueID);
2823 SET_EXPECT(Accessible2_get_uniqueID);
2824 elprov2 = (void *)0xdeadbeef;
2825 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2826 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2827 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
2828 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
2829 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
2830 CHECK_CALLED(Accessible_get_uniqueID);
2831 CHECK_CALLED(Accessible2_get_uniqueID);
2832 IRawElementProviderSimple_Release(elprov2);
2834 elprov2 = (void *)0xdeadbeef;
2835 acc_client = NULL;
2836 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2837 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2838 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
2839 IRawElementProviderSimple_Release(elprov2);
2841 IRawElementProviderSimple_Release(elprov);
2842 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
2844 /* Unique ID mismatch. */
2845 set_accessible_ia2_props(&Accessible, TRUE, 1);
2846 set_accessible_ia2_props(&Accessible2, TRUE, 2);
2847 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
2848 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2849 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
2851 acc_client = &Accessible2.IAccessible_iface;
2852 SET_EXPECT(winproc_GETOBJECT_CLIENT);
2853 SET_EXPECT(Accessible_get_uniqueID);
2854 SET_EXPECT(Accessible2_get_uniqueID);
2855 elprov2 = (void *)0xdeadbeef;
2856 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2858 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
2859 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
2860 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
2861 CHECK_CALLED(Accessible_get_uniqueID);
2862 CHECK_CALLED(Accessible2_get_uniqueID);
2864 elprov2 = (void *)0xdeadbeef;
2865 acc_client = NULL;
2866 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2867 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2868 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
2870 IRawElementProviderSimple_Release(elprov);
2871 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
2873 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
2874 set_accessible_ia2_props(&Accessible, FALSE, 0);
2875 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
2876 set_accessible_ia2_props(&Accessible2, FALSE, 0);
2879 #define check_fragment_acc( fragment, acc, cid) \
2880 check_fragment_acc_( (fragment), (acc), (cid), __LINE__)
2881 static void check_fragment_acc_(IRawElementProviderFragment *elfrag, IAccessible *acc,
2882 INT cid, int line)
2884 ILegacyIAccessibleProvider *accprov;
2885 IAccessible *accessible;
2886 INT child_id;
2887 HRESULT hr;
2889 hr = IRawElementProviderFragment_QueryInterface(elfrag, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
2890 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
2891 ok_(__FILE__, line) (!!accprov, "accprov == NULL\n");
2893 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &accessible);
2894 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
2895 ok_(__FILE__, line) (accessible == acc, "accessible != acc\n");
2896 IAccessible_Release(accessible);
2898 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
2899 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
2900 ok_(__FILE__, line) (child_id == cid, "child_id != cid\n");
2902 ILegacyIAccessibleProvider_Release(accprov);
2905 static void test_uia_prov_from_acc_navigation(void)
2907 IRawElementProviderFragment *elfrag, *elfrag2, *elfrag3;
2908 IRawElementProviderSimple *elprov, *elprov2;
2909 HRESULT hr;
2912 * Full IAccessible parent, with 4 children:
2913 * childid 1 is a simple element, with STATE_SYSTEM_INVISIBLE.
2914 * childid 2 is Accessible_child.
2915 * childid 3 is a simple element with STATE_SYSTEM_NORMAL.
2916 * childid 4 is Accessible_child2.
2918 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
2919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2920 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
2922 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
2923 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2924 ok(!!elfrag, "elfrag == NULL\n");
2927 * First time doing NavigateDirection_Parent will result in the same root
2928 * accessible check as get_HostRawElementProvider. If this IAccessible is
2929 * the root for its associated HWND, NavigateDirection_Parent and
2930 * NavigateDirection_Next/PreviousSibling will do nothing, as UI Automation
2931 * provides non-client area providers for the root IAccessible's parent
2932 * and siblings.
2934 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
2935 L"acc_name", 0, 0, 50, 50);
2936 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
2937 L"acc_name", 0, 0, 50, 50);
2938 acc_client = &Accessible2.IAccessible_iface;
2939 SET_EXPECT(winproc_GETOBJECT_CLIENT);
2940 SET_EXPECT(Accessible_get_accRole);
2941 SET_EXPECT(Accessible_get_accState);
2942 SET_EXPECT(Accessible_get_accChildCount);
2943 SET_EXPECT(Accessible_accLocation);
2944 SET_EXPECT(Accessible_get_accName);
2945 SET_EXPECT(Accessible2_get_accRole);
2946 SET_EXPECT(Accessible2_get_accState);
2947 SET_EXPECT(Accessible2_get_accChildCount);
2948 SET_EXPECT(Accessible2_accLocation);
2949 SET_EXPECT(Accessible2_get_accName);
2950 SET_EXPECT(Accessible2_QI_IAccIdentity);
2951 SET_EXPECT(Accessible2_get_accParent);
2952 elfrag2 = (void *)0xdeadbeef;
2953 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
2954 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
2955 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2956 ok(!elfrag2, "elfrag2 != NULL\n");
2957 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
2958 CHECK_CALLED(Accessible_get_accRole);
2959 CHECK_CALLED(Accessible_get_accState);
2960 CHECK_CALLED(Accessible_get_accChildCount);
2961 CHECK_CALLED(Accessible_accLocation);
2962 CHECK_CALLED(Accessible_get_accName);
2963 CHECK_CALLED(Accessible2_get_accRole);
2964 CHECK_CALLED(Accessible2_get_accState);
2965 CHECK_CALLED(Accessible2_get_accChildCount);
2966 CHECK_CALLED(Accessible2_accLocation);
2967 CHECK_CALLED(Accessible2_get_accName);
2968 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
2969 todo_wine CHECK_CALLED(Accessible2_get_accParent);
2970 acc_client = NULL;
2972 /* No check against root IAccessible, since it was done previously. */
2973 elprov2 = (void *)0xdeadbeef;
2974 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
2975 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2976 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
2977 IRawElementProviderSimple_Release(elprov2);
2979 /* Do nothing. */
2980 elfrag2 = (void *)0xdeadbeef;
2981 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
2982 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
2983 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2984 ok(!elfrag2, "elfrag2 != NULL\n");
2986 elfrag2 = (void *)0xdeadbeef;
2987 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
2988 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
2989 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2990 ok(!elfrag2, "elfrag2 != NULL\n");
2992 elfrag2 = (void *)0xdeadbeef;
2993 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
2994 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
2995 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2996 ok(!elfrag2, "elfrag2 != NULL\n");
2999 * Retrieve childid 2 (Accessible_child) as first child. childid 1 is skipped due to
3000 * having a state of STATE_SYSTEM_INVISIBLE.
3002 set_accessible_props(&Accessible_child, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3003 set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3004 SET_EXPECT_MULTI(Accessible_get_accChildCount, 3);
3005 SET_EXPECT_MULTI(Accessible_get_accChild, 2);
3006 SET_EXPECT(Accessible_get_accState);
3007 SET_EXPECT(Accessible_child_get_accState);
3008 SET_EXPECT(Accessible_child_accNavigate);
3009 SET_EXPECT(Accessible_child_get_accParent);
3010 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
3011 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
3012 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3013 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3014 ok(!!elfrag2, "elfrag2 == NULL\n");
3015 CHECK_CALLED_MULTI(Accessible_get_accChildCount, 3);
3016 CHECK_CALLED_MULTI(Accessible_get_accChild, 2);
3017 CHECK_CALLED(Accessible_child_get_accState);
3018 CHECK_CALLED(Accessible_child_accNavigate);
3019 CHECK_CALLED(Accessible_child_get_accParent);
3021 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
3022 SET_EXPECT(Accessible_get_accChildCount);
3023 SET_EXPECT(Accessible_get_accChild);
3024 SET_EXPECT(Accessible_get_accState);
3025 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_NextSibling, &elfrag3);
3026 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
3027 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3028 ok(!!elfrag3, "elfrag2 == NULL\n");
3029 CHECK_CALLED(Accessible_get_accChildCount);
3030 CHECK_CALLED(Accessible_get_accChild);
3031 CHECK_CALLED(Accessible_get_accState);
3032 check_fragment_acc(elfrag3, &Accessible.IAccessible_iface, 3);
3034 IRawElementProviderFragment_Release(elfrag3);
3035 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3036 IRawElementProviderFragment_Release(elfrag2);
3037 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
3038 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3040 /* Retrieve childid 3 as first child now that Accessible_child is invisible. */
3041 set_accessible_props(&Accessible_child, 0, STATE_SYSTEM_INVISIBLE, 0, NULL, 0, 0, 0, 0);
3042 SET_EXPECT_MULTI(Accessible_get_accChildCount, 4);
3043 SET_EXPECT_MULTI(Accessible_get_accChild, 3);
3044 SET_EXPECT_MULTI(Accessible_get_accState, 2);
3045 SET_EXPECT(Accessible_child_get_accState);
3046 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
3047 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
3048 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3049 ok(!!elfrag2, "elfrag2 == NULL\n");
3050 CHECK_CALLED_MULTI(Accessible_get_accChildCount, 4);
3051 CHECK_CALLED_MULTI(Accessible_get_accChild, 3);
3052 CHECK_CALLED_MULTI(Accessible_get_accState, 2);
3053 CHECK_CALLED(Accessible_child_get_accState);
3054 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
3055 IRawElementProviderFragment_Release(elfrag2);
3056 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3058 /* Retrieve childid 4 (Accessible_child2) as last child. */
3059 set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3060 SET_EXPECT_MULTI(Accessible_get_accChildCount, 2);
3061 SET_EXPECT(Accessible_get_accChild);
3062 SET_EXPECT(Accessible_child2_get_accState);
3063 SET_EXPECT(Accessible_child2_accNavigate);
3064 SET_EXPECT(Accessible_child2_get_accParent);
3065 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
3066 ok(Accessible_child2.ref == 2, "Unexpected refcnt %ld\n", Accessible_child2.ref);
3067 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3069 ok(!!elfrag2, "elfrag2 == NULL\n");
3070 CHECK_CALLED_MULTI(Accessible_get_accChildCount, 2);
3071 CHECK_CALLED(Accessible_get_accChild);
3072 CHECK_CALLED(Accessible_child2_get_accState);
3073 CHECK_CALLED(Accessible_child2_accNavigate);
3074 CHECK_CALLED(Accessible_child2_get_accParent);
3076 check_fragment_acc(elfrag2, &Accessible_child2.IAccessible_iface, CHILDID_SELF);
3077 SET_EXPECT(Accessible_get_accChildCount);
3078 SET_EXPECT(Accessible_get_accChild);
3079 SET_EXPECT(Accessible_get_accState);
3080 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_PreviousSibling, &elfrag3);
3081 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
3082 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3083 ok(!!elfrag3, "elfrag2 == NULL\n");
3084 CHECK_CALLED(Accessible_get_accChildCount);
3085 CHECK_CALLED(Accessible_get_accChild);
3086 CHECK_CALLED(Accessible_get_accState);
3087 check_fragment_acc(elfrag3, &Accessible.IAccessible_iface, 3);
3089 IRawElementProviderFragment_Release(elfrag3);
3090 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3091 IRawElementProviderFragment_Release(elfrag2);
3092 ok(Accessible_child2.ref == 1, "Unexpected refcnt %ld\n", Accessible_child2.ref);
3093 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3095 /* Retrieve childid 3 as last child, now that Accessible_child2 is STATE_SYSTEM_INVISIBLE. */
3096 set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_INVISIBLE, 0, NULL, 0, 0, 0, 0);
3097 SET_EXPECT_MULTI(Accessible_get_accChildCount, 3);
3098 SET_EXPECT_MULTI(Accessible_get_accChild, 2);
3099 SET_EXPECT(Accessible_get_accState);
3100 SET_EXPECT(Accessible_child2_get_accState);
3101 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
3102 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
3103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3104 ok(!!elfrag2, "elfrag2 == NULL\n");
3105 CHECK_CALLED_MULTI(Accessible_get_accChildCount, 3);
3106 CHECK_CALLED_MULTI(Accessible_get_accChild, 2);
3107 CHECK_CALLED(Accessible_get_accState);
3108 CHECK_CALLED(Accessible_child2_get_accState);
3109 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
3110 IRawElementProviderFragment_Release(elfrag2);
3111 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3113 IRawElementProviderFragment_Release(elfrag);
3114 IRawElementProviderSimple_Release(elprov);
3115 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3118 * Full IAccessible child tests.
3120 SET_EXPECT(Accessible_child_accNavigate);
3121 SET_EXPECT(Accessible_child_get_accParent);
3122 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, 0, UIA_PFIA_DEFAULT, &elprov);
3123 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3124 CHECK_CALLED(Accessible_child_accNavigate);
3125 CHECK_CALLED(Accessible_child_get_accParent);
3126 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
3128 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3129 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3130 ok(!!elfrag, "elfrag == NULL\n");
3133 * After determining this isn't the root IAccessible, get_accParent will
3134 * be used to get the parent.
3136 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3137 set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3138 acc_client = &Accessible2.IAccessible_iface;
3139 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3140 SET_EXPECT(Accessible_child_get_accRole);
3141 SET_EXPECT(Accessible_child_get_accParent);
3142 SET_EXPECT(Accessible2_get_accRole);
3143 SET_EXPECT(Accessible2_QI_IAccIdentity);
3144 SET_EXPECT(Accessible2_get_accParent);
3145 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
3146 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3147 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3148 ok(!!elfrag2, "elfrag2 == NULL\n");
3149 CHECK_CALLED(Accessible_child_get_accParent);
3150 CHECK_CALLED(Accessible_child_get_accRole);
3151 CHECK_CALLED(Accessible2_get_accRole);
3152 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
3153 todo_wine CHECK_CALLED(Accessible2_get_accParent);
3154 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3155 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
3156 IRawElementProviderFragment_Release(elfrag2);
3157 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3158 acc_client = NULL;
3160 /* Second call only does get_accParent, no root check. */
3161 SET_EXPECT(Accessible_child_get_accParent);
3162 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
3163 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3164 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3165 ok(!!elfrag2, "elfrag2 == NULL\n");
3166 CHECK_CALLED(Accessible_child_get_accParent);
3167 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
3168 IRawElementProviderFragment_Release(elfrag2);
3169 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3171 /* ChildCount of 0, do nothing for First/Last child.*/
3172 SET_EXPECT(Accessible_child_get_accChildCount);
3173 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
3174 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3175 ok(!elfrag2, "elfrag2 != NULL\n");
3176 CHECK_CALLED(Accessible_child_get_accChildCount);
3178 SET_EXPECT(Accessible_child_get_accChildCount);
3179 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
3180 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3181 ok(!elfrag2, "elfrag2 != NULL\n");
3182 CHECK_CALLED(Accessible_child_get_accChildCount);
3185 * In the case of sibling navigation on an IAccessible that wasn't
3186 * received through previous navigation from a parent (i.e, from
3187 * NavigateDirection_First/LastChild), we have to figure out which
3188 * IAccessible child we represent by comparing against all children of our
3189 * IAccessible parent. If we find more than one IAccessible that matches,
3190 * or none at all that do, navigation will fail.
3192 set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 1,
3193 L"acc_child", 0, 0, 50, 50);
3194 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 1,
3195 L"acc_child", 0, 0, 50, 50);
3196 SET_EXPECT_MULTI(Accessible_get_accChildCount, 5);
3197 SET_EXPECT_MULTI(Accessible_get_accChild, 4);
3198 SET_EXPECT(Accessible_child_get_accParent);
3199 SET_EXPECT(Accessible_child_get_accRole);
3200 SET_EXPECT(Accessible_child_get_accState);
3201 SET_EXPECT(Accessible_child_get_accChildCount);
3202 SET_EXPECT(Accessible_child_accLocation);
3203 SET_EXPECT(Accessible_child_get_accName);
3204 SET_EXPECT(Accessible_child2_get_accRole);
3205 SET_EXPECT(Accessible_child2_get_accState);
3206 SET_EXPECT(Accessible_child2_get_accChildCount);
3207 SET_EXPECT(Accessible_child2_accLocation);
3208 SET_EXPECT(Accessible_child2_get_accName);
3209 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
3210 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3211 ok(!elfrag2, "elfrag2 != NULL\n");
3212 CHECK_CALLED_MULTI(Accessible_get_accChildCount, 5);
3213 CHECK_CALLED_MULTI(Accessible_get_accChild, 4);
3214 CHECK_CALLED(Accessible_child_get_accParent);
3215 CHECK_CALLED(Accessible_child_get_accRole);
3216 CHECK_CALLED(Accessible_child_get_accState);
3217 CHECK_CALLED(Accessible_child_get_accChildCount);
3218 CHECK_CALLED(Accessible_child_accLocation);
3219 CHECK_CALLED(Accessible_child_get_accName);
3220 CHECK_CALLED(Accessible_child2_get_accRole);
3221 CHECK_CALLED(Accessible_child2_get_accState);
3222 CHECK_CALLED(Accessible_child2_get_accChildCount);
3223 CHECK_CALLED(Accessible_child2_accLocation);
3224 CHECK_CALLED(Accessible_child2_get_accName);
3226 /* Now they have a role mismatch, we can determine our position. */
3227 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
3228 L"acc_child", 0, 0, 50, 50);
3229 SET_EXPECT_MULTI(Accessible_get_accChildCount, 6);
3230 SET_EXPECT_MULTI(Accessible_get_accChild, 5);
3231 /* Check ChildID 1 for STATE_SYSTEM_INVISIBLE. */
3232 SET_EXPECT(Accessible_get_accState);
3233 SET_EXPECT(Accessible_child_get_accParent);
3234 SET_EXPECT(Accessible_child_get_accRole);
3235 SET_EXPECT(Accessible_child2_get_accRole);
3236 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
3238 * Even though we didn't get a new fragment, now that we know our
3239 * position, a reference is added to the parent IAccessible.
3241 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3243 ok(!elfrag2, "elfrag2 != NULL\n");
3244 CHECK_CALLED_MULTI(Accessible_get_accChildCount, 6);
3245 CHECK_CALLED_MULTI(Accessible_get_accChild, 5);
3246 CHECK_CALLED(Accessible_get_accState);
3247 CHECK_CALLED(Accessible_child_get_accParent);
3248 CHECK_CALLED(Accessible_child_get_accRole);
3249 CHECK_CALLED(Accessible_child2_get_accRole);
3251 /* Now that we know our position, no extra nav work. */
3252 SET_EXPECT(Accessible_get_accChildCount);
3253 SET_EXPECT(Accessible_get_accChild);
3254 SET_EXPECT(Accessible_get_accState);
3255 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
3256 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
3257 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3258 ok(!!elfrag2, "elfrag2 == NULL\n");
3259 CHECK_CALLED(Accessible_get_accChildCount);
3260 CHECK_CALLED(Accessible_get_accChild);
3261 CHECK_CALLED(Accessible_get_accState);
3262 if (elfrag2)
3264 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
3265 IRawElementProviderFragment_Release(elfrag2);
3266 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3269 IRawElementProviderFragment_Release(elfrag);
3270 IRawElementProviderSimple_Release(elprov);
3271 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
3272 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3275 * Simple element child tests.
3277 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
3278 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3279 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3281 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3283 ok(!!elfrag, "elfrag == NULL\n");
3286 * Simple child elements don't check the root IAccessible, because they
3287 * can't be the root IAccessible.
3289 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
3290 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3291 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3292 ok(!!elfrag2, "elfrag2 == NULL\n");
3293 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
3294 IRawElementProviderFragment_Release(elfrag2);
3295 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3298 * Test NavigateDirection_First/LastChild on simple child element. Does
3299 * nothing, as simple children cannot have children.
3301 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
3302 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3303 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3304 ok(!elfrag2, "elfrag2 != NULL\n");
3306 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
3307 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3308 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3309 ok(!elfrag2, "elfrag2 != NULL\n");
3312 * NavigateDirection_Next/PreviousSibling behaves normally, no IAccessible
3313 * comparisons.
3315 SET_EXPECT(Accessible_get_accChildCount);
3316 SET_EXPECT(Accessible_get_accChild);
3317 SET_EXPECT(Accessible_child_get_accState);
3318 SET_EXPECT(Accessible_child_accNavigate);
3319 SET_EXPECT(Accessible_child_get_accParent);
3320 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
3321 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
3322 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
3323 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3324 ok(!!elfrag2, "elfrag2 == NULL\n");
3325 CHECK_CALLED(Accessible_get_accChildCount);
3326 CHECK_CALLED(Accessible_get_accChild);
3327 CHECK_CALLED(Accessible_child_get_accState);
3328 CHECK_CALLED(Accessible_child_accNavigate);
3329 CHECK_CALLED(Accessible_child_get_accParent);
3330 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
3332 IRawElementProviderFragment_Release(elfrag2);
3333 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
3334 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3335 IRawElementProviderFragment_Release(elfrag);
3336 IRawElementProviderSimple_Release(elprov);
3337 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3339 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
3340 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
3341 set_accessible_props(&Accessible_child, 0, 0, 0, NULL, 0, 0, 0, 0);
3342 set_accessible_props(&Accessible_child2, 0, 0, 0, NULL, 0, 0, 0, 0);
3345 static void test_uia_prov_from_acc_properties(void)
3347 IRawElementProviderSimple *elprov;
3348 HRESULT hr;
3349 VARIANT v;
3350 int i, x;
3352 /* MSAA role to UIA control type test. */
3353 VariantInit(&v);
3354 for (i = 0; i < ARRAY_SIZE(msaa_role_uia_types); i++)
3356 const struct msaa_role_uia_type *role = &msaa_role_uia_types[i];
3359 * Roles get cached once a valid one is mapped, so create a new
3360 * element for each role.
3362 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3363 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3364 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3366 Accessible.role = role->acc_role;
3367 SET_EXPECT(Accessible_get_accRole);
3368 VariantClear(&v);
3369 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
3370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3371 if (role->uia_control_type)
3372 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
3373 else
3374 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
3375 CHECK_CALLED(Accessible_get_accRole);
3377 if (!role->uia_control_type)
3378 SET_EXPECT(Accessible_get_accRole);
3379 VariantClear(&v);
3380 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
3381 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3382 if (role->uia_control_type)
3383 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
3384 else
3385 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
3386 if (!role->uia_control_type)
3387 CHECK_CALLED(Accessible_get_accRole);
3389 IRawElementProviderSimple_Release(elprov);
3390 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3393 /* ROLE_SYSTEM_CLOCK has no mapping in Windows < 10 1809. */
3394 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3396 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3398 Accessible.role = ROLE_SYSTEM_CLOCK;
3399 SET_EXPECT(Accessible_get_accRole);
3400 VariantClear(&v);
3401 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
3402 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3403 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
3404 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
3405 CHECK_CALLED(Accessible_get_accRole);
3407 if (V_VT(&v) == VT_EMPTY)
3408 SET_EXPECT(Accessible_get_accRole);
3409 VariantClear(&v);
3410 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
3411 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
3412 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
3413 if (V_VT(&v) == VT_EMPTY)
3414 CHECK_CALLED(Accessible_get_accRole);
3416 Accessible.role = 0;
3417 IRawElementProviderSimple_Release(elprov);
3418 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3420 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3421 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3422 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3424 /* UIA PropertyId's that correspond directly to individual MSAA state flags. */
3425 for (i = 0; i < ARRAY_SIZE(msaa_state_uia_props); i++)
3427 const struct msaa_state_uia_prop *state = &msaa_state_uia_props[i];
3429 for (x = 0; x < 2; x++)
3431 Accessible.state = x ? state->acc_state : ~state->acc_state;
3432 SET_EXPECT(Accessible_get_accState);
3433 hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v);
3434 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3435 ok(check_variant_bool(&v, x), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
3436 CHECK_CALLED(Accessible_get_accState);
3439 Accessible.state = 0;
3441 IRawElementProviderSimple_Release(elprov);
3442 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3444 /* UIA_NamePropertyId tests. */
3445 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible", 0, 0, 0, 0);
3446 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3447 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3448 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3450 SET_EXPECT(Accessible_get_accName);
3451 VariantInit(&v);
3452 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
3453 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3454 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
3455 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
3456 VariantClear(&v);
3457 CHECK_CALLED(Accessible_get_accName);
3459 /* Name is not cached. */
3460 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible2", 0, 0, 0, 0);
3461 SET_EXPECT(Accessible_get_accName);
3462 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
3463 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3464 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
3465 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
3466 VariantClear(&v);
3467 CHECK_CALLED(Accessible_get_accName);
3469 IRawElementProviderSimple_Release(elprov);
3470 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3473 static void test_UiaProviderFromIAccessible(void)
3475 ILegacyIAccessibleProvider *accprov;
3476 IRawElementProviderSimple *elprov, *elprov2;
3477 IRawElementProviderFragment *elfrag;
3478 enum ProviderOptions prov_opt;
3479 struct UiaRect rect;
3480 IAccessible *acc;
3481 IUnknown *unk;
3482 WNDCLASSA cls;
3483 HRESULT hr;
3484 HWND hwnd;
3485 VARIANT v;
3486 INT cid;
3488 CoInitializeEx(NULL, COINIT_MULTITHREADED);
3489 cls.style = 0;
3490 cls.lpfnWndProc = test_wnd_proc;
3491 cls.cbClsExtra = 0;
3492 cls.cbWndExtra = 0;
3493 cls.hInstance = GetModuleHandleA(NULL);
3494 cls.hIcon = 0;
3495 cls.hCursor = NULL;
3496 cls.hbrBackground = NULL;
3497 cls.lpszMenuName = NULL;
3498 cls.lpszClassName = "UiaProviderFromIAccessible class";
3500 RegisterClassA(&cls);
3502 hwnd = CreateWindowA("UiaProviderFromIAccessible class", "Test window", WS_OVERLAPPEDWINDOW,
3503 0, 0, 100, 100, NULL, NULL, NULL, NULL);
3505 hr = pUiaProviderFromIAccessible(NULL, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3506 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3508 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, NULL);
3509 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
3512 * UiaProviderFromIAccessible will not wrap an MSAA proxy, this is
3513 * detected by checking for the 'IIS_IsOleaccProxy' service from the
3514 * IServiceProvider interface.
3516 hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
3517 ok(hr == S_OK, "got %#lx\n", hr);
3518 ok(!!acc, "acc == NULL\n");
3520 hr = pUiaProviderFromIAccessible(acc, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3521 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3522 IAccessible_Release(acc);
3524 /* Don't return an HWND from accNavigate or OleWindow. */
3525 SET_EXPECT(Accessible_accNavigate);
3526 SET_EXPECT(Accessible_get_accParent);
3527 Accessible.acc_hwnd = NULL;
3528 Accessible.ow_hwnd = NULL;
3529 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3530 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
3531 CHECK_CALLED(Accessible_accNavigate);
3532 CHECK_CALLED(Accessible_get_accParent);
3534 /* Return an HWND from accNavigate, not OleWindow. */
3535 SET_EXPECT(Accessible_accNavigate);
3536 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3537 acc_client = &Accessible.IAccessible_iface;
3538 Accessible.acc_hwnd = hwnd;
3539 Accessible.ow_hwnd = NULL;
3540 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3541 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3542 CHECK_CALLED(Accessible_accNavigate);
3543 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3544 IRawElementProviderSimple_Release(elprov);
3545 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3546 acc_client = NULL;
3548 /* Skip tests on Win10v1507. */
3549 if (called_winproc_GETOBJECT_CLIENT)
3551 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
3552 return;
3554 expect_winproc_GETOBJECT_CLIENT = FALSE;
3556 /* Return an HWND from parent IAccessible's IOleWindow interface. */
3557 SET_EXPECT(Accessible_child_accNavigate);
3558 SET_EXPECT(Accessible_child_get_accParent);
3559 Accessible.acc_hwnd = NULL;
3560 Accessible.ow_hwnd = hwnd;
3561 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3562 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3563 CHECK_CALLED(Accessible_child_accNavigate);
3564 CHECK_CALLED(Accessible_child_get_accParent);
3565 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
3566 IRawElementProviderSimple_Release(elprov);
3567 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
3569 /* Return an HWND from OleWindow, not accNavigate. */
3570 Accessible.acc_hwnd = NULL;
3571 Accessible.ow_hwnd = hwnd;
3572 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3573 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3574 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3576 hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opt);
3577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3578 ok((prov_opt == (ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading)) ||
3579 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3580 "Unexpected provider options %#x\n", prov_opt);
3582 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ProviderDescriptionPropertyId, &v);
3583 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3584 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3585 VariantClear(&v);
3587 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
3588 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3589 ok(!!unk, "unk == NULL\n");
3590 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
3592 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
3593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3594 ok(!!accprov, "accprov == NULL\n");
3596 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
3597 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3598 ok(cid == CHILDID_SELF, "cid != CHILDID_SELF\n");
3600 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
3601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3602 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
3603 IAccessible_Release(acc);
3604 IUnknown_Release(unk);
3605 ILegacyIAccessibleProvider_Release(accprov);
3607 IRawElementProviderSimple_Release(elprov);
3608 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3610 /* ChildID other than CHILDID_SELF. */
3611 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
3612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3613 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3616 * Simple child element (IAccessible without CHILDID_SELF) cannot be root
3617 * IAccessible. No checks against the root HWND IAccessible will be done.
3619 elprov2 = (void *)0xdeadbeef;
3620 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3621 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3622 ok(!elprov2, "elprov != NULL\n");
3624 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
3625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3626 ok(!!unk, "unk == NULL\n");
3627 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
3629 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
3630 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3631 ok(!!accprov, "accprov == NULL\n");
3633 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
3634 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3635 ok(cid == 1, "cid != CHILDID_SELF\n");
3637 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
3638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3639 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
3640 IAccessible_Release(acc);
3641 IUnknown_Release(unk);
3642 ILegacyIAccessibleProvider_Release(accprov);
3644 IRawElementProviderSimple_Release(elprov);
3645 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3648 * &Accessible.IAccessible_iface will be compared against the default
3649 * client accessible object. Since we have all properties set to 0,
3650 * we return failure HRESULTs and all properties will get queried but not
3651 * compared.
3653 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3654 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3655 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3657 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3658 SET_EXPECT(Accessible_get_accRole);
3659 SET_EXPECT(Accessible_get_accState);
3660 SET_EXPECT(Accessible_get_accChildCount);
3661 SET_EXPECT(Accessible_accLocation);
3662 SET_EXPECT(Accessible_get_accName);
3663 elprov2 = (void *)0xdeadbeef;
3664 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3665 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3666 ok(!elprov2, "elprov != NULL\n");
3667 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3668 CHECK_CALLED(Accessible_get_accRole);
3669 CHECK_CALLED(Accessible_get_accState);
3670 CHECK_CALLED(Accessible_get_accChildCount);
3671 CHECK_CALLED(Accessible_accLocation);
3672 CHECK_CALLED(Accessible_get_accName);
3674 /* Second call won't send WM_GETOBJECT. */
3675 elprov2 = (void *)0xdeadbeef;
3676 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3677 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3678 ok(!elprov2, "elprov != NULL\n");
3680 IRawElementProviderSimple_Release(elprov);
3681 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3684 * Return &Accessible.IAccessible_iface in response to OBJID_CLIENT,
3685 * interface pointers will be compared, no method calls to check property
3686 * values.
3688 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3689 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3690 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3692 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3693 elprov2 = (void *)0xdeadbeef;
3694 acc_client = &Accessible.IAccessible_iface;
3695 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3697 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3698 IRawElementProviderSimple_Release(elprov2);
3699 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3701 /* Second call, no checks. */
3702 elprov2 = (void *)0xdeadbeef;
3703 acc_client = NULL;
3704 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3705 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3706 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3707 IRawElementProviderSimple_Release(elprov2);
3709 IRawElementProviderSimple_Release(elprov);
3710 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3713 * Return &Accessible2.IAccessible_iface in response to OBJID_CLIENT,
3714 * interface pointers won't match, so properties will be compared.
3716 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3717 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3718 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3720 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
3721 L"acc_name", 0, 0, 50, 50);
3722 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
3723 L"acc_name", 0, 0, 50, 50);
3725 acc_client = &Accessible2.IAccessible_iface;
3726 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3727 SET_EXPECT(Accessible_get_accRole);
3728 SET_EXPECT(Accessible_get_accState);
3729 SET_EXPECT(Accessible_get_accChildCount);
3730 SET_EXPECT(Accessible_accLocation);
3731 SET_EXPECT(Accessible_get_accName);
3732 SET_EXPECT(Accessible2_get_accRole);
3733 SET_EXPECT(Accessible2_get_accState);
3734 SET_EXPECT(Accessible2_get_accChildCount);
3735 SET_EXPECT(Accessible2_accLocation);
3736 SET_EXPECT(Accessible2_get_accName);
3738 * The IAccessible returned by WM_GETOBJECT will be checked for an
3739 * IAccIdentity interface to see if Dynamic Annotation properties should
3740 * be queried. If not present on the current IAccessible, it will check
3741 * the parent IAccessible for one.
3743 SET_EXPECT(Accessible2_QI_IAccIdentity);
3744 SET_EXPECT(Accessible2_get_accParent);
3745 elprov2 = (void *)0xdeadbeef;
3746 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3747 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3748 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3749 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3750 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3751 CHECK_CALLED(Accessible_get_accRole);
3752 CHECK_CALLED(Accessible_get_accState);
3753 CHECK_CALLED(Accessible_get_accChildCount);
3754 CHECK_CALLED(Accessible_accLocation);
3755 CHECK_CALLED(Accessible_get_accName);
3756 CHECK_CALLED(Accessible2_get_accRole);
3757 CHECK_CALLED(Accessible2_get_accState);
3758 CHECK_CALLED(Accessible2_get_accChildCount);
3759 CHECK_CALLED(Accessible2_accLocation);
3760 CHECK_CALLED(Accessible2_get_accName);
3761 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
3762 todo_wine CHECK_CALLED(Accessible2_get_accParent);
3763 IRawElementProviderSimple_Release(elprov2);
3765 elprov2 = (void *)0xdeadbeef;
3766 acc_client = NULL;
3767 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3768 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3769 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3770 IRawElementProviderSimple_Release(elprov2);
3772 IRawElementProviderSimple_Release(elprov);
3773 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3776 * If a failure HRESULT is returned from the IRawElementProviderSimple
3777 * IAccessible, the corresponding AOFW IAccessible method isn't called.
3778 * An exception is get_accChildCount, which is always called, but only
3779 * checked if the HRESULT return value is not a failure. If Role/State/Name
3780 * are not queried, no IAccIdentity check is done.
3782 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3783 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3784 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3786 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
3787 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
3788 L"acc_name", 0, 0, 50, 50);
3790 acc_client = &Accessible2.IAccessible_iface;
3791 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3792 SET_EXPECT(Accessible_get_accRole);
3793 SET_EXPECT(Accessible_get_accState);
3794 SET_EXPECT(Accessible_get_accChildCount);
3795 SET_EXPECT(Accessible2_get_accChildCount);
3796 SET_EXPECT(Accessible_accLocation);
3797 SET_EXPECT(Accessible_get_accName);
3798 elprov2 = (void *)0xdeadbeef;
3799 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3801 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3802 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3803 CHECK_CALLED(Accessible_get_accRole);
3804 CHECK_CALLED(Accessible_get_accState);
3805 CHECK_CALLED(Accessible_get_accChildCount);
3806 CHECK_CALLED(Accessible2_get_accChildCount);
3807 CHECK_CALLED(Accessible_accLocation);
3808 CHECK_CALLED(Accessible_get_accName);
3810 acc_client = NULL;
3811 elprov2 = (void *)0xdeadbeef;
3812 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3813 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3814 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3816 IRawElementProviderSimple_Release(elprov);
3817 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3820 * Properties are checked in a sequence of accRole, accState,
3821 * accChildCount, accLocation, and finally accName. If a mismatch is found
3822 * early in the sequence, the rest aren't checked.
3824 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3825 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3826 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3828 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3829 set_accessible_props(&Accessible2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
3831 acc_client = &Accessible2.IAccessible_iface;
3832 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3833 SET_EXPECT(Accessible_get_accRole);
3834 SET_EXPECT(Accessible2_get_accRole);
3835 SET_EXPECT(Accessible2_QI_IAccIdentity);
3836 SET_EXPECT(Accessible2_get_accParent);
3837 elprov2 = (void *)0xdeadbeef;
3838 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3840 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3841 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3842 CHECK_CALLED(Accessible_get_accRole);
3843 CHECK_CALLED(Accessible2_get_accRole);
3844 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
3845 todo_wine CHECK_CALLED(Accessible2_get_accParent);
3847 elprov2 = (void *)0xdeadbeef;
3848 acc_client = NULL;
3849 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3851 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3853 IRawElementProviderSimple_Release(elprov);
3854 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3856 /* 4/5 properties match, considered a match. */
3857 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3858 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3859 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3861 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
3862 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
3864 acc_client = &Accessible2.IAccessible_iface;
3865 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3866 SET_EXPECT(Accessible_get_accRole);
3867 SET_EXPECT(Accessible_get_accState);
3868 SET_EXPECT(Accessible_get_accChildCount);
3869 SET_EXPECT(Accessible_accLocation);
3870 SET_EXPECT(Accessible_get_accName);
3871 SET_EXPECT(Accessible2_get_accRole);
3872 SET_EXPECT(Accessible2_get_accState);
3873 SET_EXPECT(Accessible2_get_accChildCount);
3874 SET_EXPECT(Accessible2_accLocation);
3875 SET_EXPECT(Accessible2_QI_IAccIdentity);
3876 SET_EXPECT(Accessible2_get_accParent);
3877 elprov2 = (void *)0xdeadbeef;
3878 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3879 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3880 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3881 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3882 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3883 CHECK_CALLED(Accessible_get_accRole);
3884 CHECK_CALLED(Accessible_get_accState);
3885 CHECK_CALLED(Accessible_get_accChildCount);
3886 CHECK_CALLED(Accessible_accLocation);
3887 CHECK_CALLED(Accessible_get_accName);
3888 CHECK_CALLED(Accessible2_get_accRole);
3889 CHECK_CALLED(Accessible2_get_accState);
3890 CHECK_CALLED(Accessible2_get_accChildCount);
3891 CHECK_CALLED(Accessible2_accLocation);
3892 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
3893 todo_wine CHECK_CALLED(Accessible2_get_accParent);
3894 IRawElementProviderSimple_Release(elprov2);
3896 elprov2 = (void *)0xdeadbeef;
3897 acc_client = NULL;
3898 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3900 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3901 IRawElementProviderSimple_Release(elprov2);
3903 IRawElementProviderSimple_Release(elprov);
3904 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3906 /* 3/5 properties match, not considered a match. */
3907 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3908 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3909 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3911 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
3912 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
3914 acc_client = &Accessible2.IAccessible_iface;
3915 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3916 SET_EXPECT(Accessible_get_accRole);
3917 SET_EXPECT(Accessible_get_accState);
3918 SET_EXPECT(Accessible_get_accChildCount);
3919 SET_EXPECT(Accessible_accLocation);
3920 SET_EXPECT(Accessible_get_accName);
3921 SET_EXPECT(Accessible2_get_accRole);
3922 SET_EXPECT(Accessible2_get_accState);
3923 SET_EXPECT(Accessible2_get_accChildCount);
3924 SET_EXPECT(Accessible2_QI_IAccIdentity);
3925 SET_EXPECT(Accessible2_get_accParent);
3926 elprov2 = (void *)0xdeadbeef;
3927 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3928 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3929 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3930 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3931 CHECK_CALLED(Accessible_get_accRole);
3932 CHECK_CALLED(Accessible_get_accState);
3933 CHECK_CALLED(Accessible_get_accChildCount);
3934 CHECK_CALLED(Accessible_accLocation);
3935 CHECK_CALLED(Accessible_get_accName);
3936 CHECK_CALLED(Accessible2_get_accRole);
3937 CHECK_CALLED(Accessible2_get_accState);
3938 CHECK_CALLED(Accessible2_get_accChildCount);
3939 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
3940 todo_wine CHECK_CALLED(Accessible2_get_accParent);
3942 elprov2 = (void *)0xdeadbeef;
3943 acc_client = NULL;
3944 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3945 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3946 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3948 IRawElementProviderSimple_Release(elprov);
3949 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3951 /* Only name matches, considered a match. */
3952 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3953 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3954 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3956 set_accessible_props(&Accessible, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
3957 set_accessible_props(&Accessible2, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
3959 acc_client = &Accessible2.IAccessible_iface;
3960 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3961 SET_EXPECT(Accessible_get_accRole);
3962 SET_EXPECT(Accessible_get_accState);
3963 SET_EXPECT(Accessible_get_accChildCount);
3964 SET_EXPECT(Accessible_accLocation);
3965 SET_EXPECT(Accessible_get_accName);
3966 SET_EXPECT(Accessible2_get_accChildCount);
3967 SET_EXPECT(Accessible2_get_accName);
3968 SET_EXPECT(Accessible2_QI_IAccIdentity);
3969 SET_EXPECT(Accessible2_get_accParent);
3970 elprov2 = (void *)0xdeadbeef;
3971 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3972 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3973 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3974 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3975 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3976 CHECK_CALLED(Accessible_get_accRole);
3977 CHECK_CALLED(Accessible_get_accState);
3978 CHECK_CALLED(Accessible_get_accChildCount);
3979 CHECK_CALLED(Accessible_accLocation);
3980 CHECK_CALLED(Accessible_get_accName);
3981 CHECK_CALLED(Accessible2_get_accChildCount);
3982 CHECK_CALLED(Accessible2_get_accName);
3983 todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity);
3984 todo_wine CHECK_CALLED(Accessible2_get_accParent);
3985 IRawElementProviderSimple_Release(elprov2);
3987 elprov2 = (void *)0xdeadbeef;
3988 acc_client = NULL;
3989 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3990 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3991 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3992 IRawElementProviderSimple_Release(elprov2);
3994 IRawElementProviderSimple_Release(elprov);
3995 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3998 * Test IRawElementProviderFragment_get_BoundingRectangle.
4000 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, L"acc_name", 25, 25, 50, 50);
4001 /* Test the case where Accessible is not the root for its HWND. */
4002 acc_client = NULL;
4003 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4004 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4005 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4007 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4008 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4009 ok(!!elfrag, "elfrag == NULL\n");
4011 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4012 SET_EXPECT(Accessible_get_accRole);
4013 SET_EXPECT(Accessible_get_accState);
4014 SET_EXPECT(Accessible_accLocation);
4015 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
4016 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4017 ok(rect.left == (double)Accessible.left, "Unexpected left value %f\n", rect.left);
4018 ok(rect.top == (double)Accessible.top, "Unexpected top value %f\n", rect.top);
4019 ok(rect.width == (double)Accessible.width, "Unexpected width value %f\n", rect.width);
4020 ok(rect.height == (double)Accessible.height, "Unexpected height value %f\n", rect.height);
4021 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4022 CHECK_CALLED(Accessible_get_accRole);
4023 CHECK_CALLED(Accessible_get_accState);
4024 CHECK_CALLED(Accessible_accLocation);
4026 /* If Accessible has STATE_SYSTEM_OFFSCREEN, it will return an empty rect. */
4027 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_OFFSCREEN, 0, L"acc_name", 0, 0, 50, 50);
4028 SET_EXPECT(Accessible_get_accState);
4029 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
4030 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4031 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
4032 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
4033 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
4034 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
4035 CHECK_CALLED(Accessible_get_accState);
4037 IRawElementProviderFragment_Release(elfrag);
4038 IRawElementProviderSimple_Release(elprov);
4039 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4041 /* Test case where accessible is the root accessible. */
4042 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
4043 acc_client = &Accessible.IAccessible_iface;
4044 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4045 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4046 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4048 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4049 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4050 ok(!!elfrag, "elfrag == NULL\n");
4052 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4053 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
4054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4055 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
4056 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
4057 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
4058 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
4059 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4061 /* Second call does nothing. */
4062 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
4063 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4064 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
4065 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
4066 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
4067 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
4069 IRawElementProviderFragment_Release(elfrag);
4070 IRawElementProviderSimple_Release(elprov);
4071 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4072 acc_client = NULL;
4074 test_uia_prov_from_acc_properties();
4075 test_uia_prov_from_acc_navigation();
4076 test_uia_prov_from_acc_ia2();
4078 CoUninitialize();
4079 DestroyWindow(hwnd);
4080 UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
4081 Accessible.acc_hwnd = NULL;
4082 Accessible.ow_hwnd = NULL;
4085 struct uia_lookup_id {
4086 const GUID *guid;
4087 int id;
4090 static const struct uia_lookup_id uia_property_lookup_ids[] = {
4091 { &RuntimeId_Property_GUID, UIA_RuntimeIdPropertyId },
4092 { &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId },
4093 { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId },
4094 { &ControlType_Property_GUID, UIA_ControlTypePropertyId },
4095 { &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId },
4096 { &Name_Property_GUID, UIA_NamePropertyId },
4097 { &AcceleratorKey_Property_GUID, UIA_AcceleratorKeyPropertyId },
4098 { &AccessKey_Property_GUID, UIA_AccessKeyPropertyId },
4099 { &HasKeyboardFocus_Property_GUID, UIA_HasKeyboardFocusPropertyId },
4100 { &IsKeyboardFocusable_Property_GUID, UIA_IsKeyboardFocusablePropertyId },
4101 { &IsEnabled_Property_GUID, UIA_IsEnabledPropertyId },
4102 { &AutomationId_Property_GUID, UIA_AutomationIdPropertyId },
4103 { &ClassName_Property_GUID, UIA_ClassNamePropertyId },
4104 { &HelpText_Property_GUID, UIA_HelpTextPropertyId },
4105 { &ClickablePoint_Property_GUID, UIA_ClickablePointPropertyId },
4106 { &Culture_Property_GUID, UIA_CulturePropertyId },
4107 { &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId },
4108 { &IsContentElement_Property_GUID, UIA_IsContentElementPropertyId },
4109 { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId },
4110 { &IsPassword_Property_GUID, UIA_IsPasswordPropertyId },
4111 { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId },
4112 { &ItemType_Property_GUID, UIA_ItemTypePropertyId },
4113 { &IsOffscreen_Property_GUID, UIA_IsOffscreenPropertyId },
4114 { &Orientation_Property_GUID, UIA_OrientationPropertyId },
4115 { &FrameworkId_Property_GUID, UIA_FrameworkIdPropertyId },
4116 { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId },
4117 { &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId },
4118 { &IsDockPatternAvailable_Property_GUID, UIA_IsDockPatternAvailablePropertyId },
4119 { &IsExpandCollapsePatternAvailable_Property_GUID, UIA_IsExpandCollapsePatternAvailablePropertyId },
4120 { &IsGridItemPatternAvailable_Property_GUID, UIA_IsGridItemPatternAvailablePropertyId },
4121 { &IsGridPatternAvailable_Property_GUID, UIA_IsGridPatternAvailablePropertyId },
4122 { &IsInvokePatternAvailable_Property_GUID, UIA_IsInvokePatternAvailablePropertyId },
4123 { &IsMultipleViewPatternAvailable_Property_GUID, UIA_IsMultipleViewPatternAvailablePropertyId },
4124 { &IsRangeValuePatternAvailable_Property_GUID, UIA_IsRangeValuePatternAvailablePropertyId },
4125 { &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId },
4126 { &IsScrollItemPatternAvailable_Property_GUID, UIA_IsScrollItemPatternAvailablePropertyId },
4127 { &IsSelectionItemPatternAvailable_Property_GUID, UIA_IsSelectionItemPatternAvailablePropertyId },
4128 { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId },
4129 { &IsTablePatternAvailable_Property_GUID, UIA_IsTablePatternAvailablePropertyId },
4130 { &IsTableItemPatternAvailable_Property_GUID, UIA_IsTableItemPatternAvailablePropertyId },
4131 { &IsTextPatternAvailable_Property_GUID, UIA_IsTextPatternAvailablePropertyId },
4132 { &IsTogglePatternAvailable_Property_GUID, UIA_IsTogglePatternAvailablePropertyId },
4133 { &IsTransformPatternAvailable_Property_GUID, UIA_IsTransformPatternAvailablePropertyId },
4134 { &IsValuePatternAvailable_Property_GUID, UIA_IsValuePatternAvailablePropertyId },
4135 { &IsWindowPatternAvailable_Property_GUID, UIA_IsWindowPatternAvailablePropertyId },
4136 { &Value_Value_Property_GUID, UIA_ValueValuePropertyId },
4137 { &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId },
4138 { &RangeValue_Value_Property_GUID, UIA_RangeValueValuePropertyId },
4139 { &RangeValue_IsReadOnly_Property_GUID, UIA_RangeValueIsReadOnlyPropertyId },
4140 { &RangeValue_Minimum_Property_GUID, UIA_RangeValueMinimumPropertyId },
4141 { &RangeValue_Maximum_Property_GUID, UIA_RangeValueMaximumPropertyId },
4142 { &RangeValue_LargeChange_Property_GUID, UIA_RangeValueLargeChangePropertyId },
4143 { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId },
4144 { &Scroll_HorizontalScrollPercent_Property_GUID, UIA_ScrollHorizontalScrollPercentPropertyId },
4145 { &Scroll_HorizontalViewSize_Property_GUID, UIA_ScrollHorizontalViewSizePropertyId },
4146 { &Scroll_VerticalScrollPercent_Property_GUID, UIA_ScrollVerticalScrollPercentPropertyId },
4147 { &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId },
4148 { &Scroll_HorizontallyScrollable_Property_GUID, UIA_ScrollHorizontallyScrollablePropertyId },
4149 { &Scroll_VerticallyScrollable_Property_GUID, UIA_ScrollVerticallyScrollablePropertyId },
4150 { &Selection_Selection_Property_GUID, UIA_SelectionSelectionPropertyId },
4151 { &Selection_CanSelectMultiple_Property_GUID, UIA_SelectionCanSelectMultiplePropertyId },
4152 { &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId },
4153 { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId },
4154 { &Grid_ColumnCount_Property_GUID, UIA_GridColumnCountPropertyId },
4155 { &GridItem_Row_Property_GUID, UIA_GridItemRowPropertyId },
4156 { &GridItem_Column_Property_GUID, UIA_GridItemColumnPropertyId },
4157 { &GridItem_RowSpan_Property_GUID, UIA_GridItemRowSpanPropertyId },
4158 { &GridItem_ColumnSpan_Property_GUID, UIA_GridItemColumnSpanPropertyId },
4159 { &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId },
4160 { &Dock_DockPosition_Property_GUID, UIA_DockDockPositionPropertyId },
4161 { &ExpandCollapse_ExpandCollapseState_Property_GUID, UIA_ExpandCollapseExpandCollapseStatePropertyId },
4162 { &MultipleView_CurrentView_Property_GUID, UIA_MultipleViewCurrentViewPropertyId },
4163 { &MultipleView_SupportedViews_Property_GUID, UIA_MultipleViewSupportedViewsPropertyId },
4164 { &Window_CanMaximize_Property_GUID, UIA_WindowCanMaximizePropertyId },
4165 { &Window_CanMinimize_Property_GUID, UIA_WindowCanMinimizePropertyId },
4166 { &Window_WindowVisualState_Property_GUID, UIA_WindowWindowVisualStatePropertyId },
4167 { &Window_WindowInteractionState_Property_GUID, UIA_WindowWindowInteractionStatePropertyId },
4168 { &Window_IsModal_Property_GUID, UIA_WindowIsModalPropertyId },
4169 { &Window_IsTopmost_Property_GUID, UIA_WindowIsTopmostPropertyId },
4170 { &SelectionItem_IsSelected_Property_GUID, UIA_SelectionItemIsSelectedPropertyId },
4171 { &SelectionItem_SelectionContainer_Property_GUID, UIA_SelectionItemSelectionContainerPropertyId },
4172 { &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId },
4173 { &Table_ColumnHeaders_Property_GUID, UIA_TableColumnHeadersPropertyId },
4174 { &Table_RowOrColumnMajor_Property_GUID, UIA_TableRowOrColumnMajorPropertyId },
4175 { &TableItem_RowHeaderItems_Property_GUID, UIA_TableItemRowHeaderItemsPropertyId },
4176 { &TableItem_ColumnHeaderItems_Property_GUID, UIA_TableItemColumnHeaderItemsPropertyId },
4177 { &Toggle_ToggleState_Property_GUID, UIA_ToggleToggleStatePropertyId },
4178 { &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId },
4179 { &Transform_CanResize_Property_GUID, UIA_TransformCanResizePropertyId },
4180 { &Transform_CanRotate_Property_GUID, UIA_TransformCanRotatePropertyId },
4181 { &IsLegacyIAccessiblePatternAvailable_Property_GUID, UIA_IsLegacyIAccessiblePatternAvailablePropertyId },
4182 { &LegacyIAccessible_ChildId_Property_GUID, UIA_LegacyIAccessibleChildIdPropertyId },
4183 { &LegacyIAccessible_Name_Property_GUID, UIA_LegacyIAccessibleNamePropertyId },
4184 { &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId },
4185 { &LegacyIAccessible_Description_Property_GUID, UIA_LegacyIAccessibleDescriptionPropertyId },
4186 { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId },
4187 { &LegacyIAccessible_State_Property_GUID, UIA_LegacyIAccessibleStatePropertyId },
4188 { &LegacyIAccessible_Help_Property_GUID, UIA_LegacyIAccessibleHelpPropertyId },
4189 { &LegacyIAccessible_KeyboardShortcut_Property_GUID, UIA_LegacyIAccessibleKeyboardShortcutPropertyId },
4190 { &LegacyIAccessible_Selection_Property_GUID, UIA_LegacyIAccessibleSelectionPropertyId },
4191 { &LegacyIAccessible_DefaultAction_Property_GUID, UIA_LegacyIAccessibleDefaultActionPropertyId },
4192 { &AriaRole_Property_GUID, UIA_AriaRolePropertyId },
4193 { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId },
4194 { &IsDataValidForForm_Property_GUID, UIA_IsDataValidForFormPropertyId },
4195 { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId },
4196 { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId },
4197 { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId },
4198 { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId },
4199 { &IsItemContainerPatternAvailable_Property_GUID, UIA_IsItemContainerPatternAvailablePropertyId },
4200 { &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId },
4201 { &IsSynchronizedInputPatternAvailable_Property_GUID, UIA_IsSynchronizedInputPatternAvailablePropertyId },
4202 /* Implemented on Win8+ */
4203 { &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId },
4204 { &IsObjectModelPatternAvailable_Property_GUID, UIA_IsObjectModelPatternAvailablePropertyId },
4205 { &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId },
4206 { &Annotation_AnnotationTypeName_Property_GUID, UIA_AnnotationAnnotationTypeNamePropertyId },
4207 { &Annotation_Author_Property_GUID, UIA_AnnotationAuthorPropertyId },
4208 { &Annotation_DateTime_Property_GUID, UIA_AnnotationDateTimePropertyId },
4209 { &Annotation_Target_Property_GUID, UIA_AnnotationTargetPropertyId },
4210 { &IsAnnotationPatternAvailable_Property_GUID, UIA_IsAnnotationPatternAvailablePropertyId },
4211 { &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId },
4212 { &Styles_StyleId_Property_GUID, UIA_StylesStyleIdPropertyId },
4213 { &Styles_StyleName_Property_GUID, UIA_StylesStyleNamePropertyId },
4214 { &Styles_FillColor_Property_GUID, UIA_StylesFillColorPropertyId },
4215 { &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId },
4216 { &Styles_Shape_Property_GUID, UIA_StylesShapePropertyId },
4217 { &Styles_FillPatternColor_Property_GUID, UIA_StylesFillPatternColorPropertyId },
4218 { &Styles_ExtendedProperties_Property_GUID, UIA_StylesExtendedPropertiesPropertyId },
4219 { &IsStylesPatternAvailable_Property_GUID, UIA_IsStylesPatternAvailablePropertyId },
4220 { &IsSpreadsheetPatternAvailable_Property_GUID, UIA_IsSpreadsheetPatternAvailablePropertyId },
4221 { &SpreadsheetItem_Formula_Property_GUID, UIA_SpreadsheetItemFormulaPropertyId },
4222 { &SpreadsheetItem_AnnotationObjects_Property_GUID, UIA_SpreadsheetItemAnnotationObjectsPropertyId },
4223 { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId },
4224 { &IsSpreadsheetItemPatternAvailable_Property_GUID, UIA_IsSpreadsheetItemPatternAvailablePropertyId },
4225 { &Transform2_CanZoom_Property_GUID, UIA_Transform2CanZoomPropertyId },
4226 { &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId },
4227 { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId },
4228 { &IsTextChildPatternAvailable_Property_GUID, UIA_IsTextChildPatternAvailablePropertyId },
4229 { &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId },
4230 { &Drag_IsGrabbed_Property_GUID, UIA_DragIsGrabbedPropertyId },
4231 { &Drag_DropEffect_Property_GUID, UIA_DragDropEffectPropertyId },
4232 { &Drag_DropEffects_Property_GUID, UIA_DragDropEffectsPropertyId },
4233 { &IsDropTargetPatternAvailable_Property_GUID, UIA_IsDropTargetPatternAvailablePropertyId },
4234 { &DropTarget_DropTargetEffect_Property_GUID, UIA_DropTargetDropTargetEffectPropertyId },
4235 { &DropTarget_DropTargetEffects_Property_GUID, UIA_DropTargetDropTargetEffectsPropertyId },
4236 { &Drag_GrabbedItems_Property_GUID, UIA_DragGrabbedItemsPropertyId },
4237 { &Transform2_ZoomLevel_Property_GUID, UIA_Transform2ZoomLevelPropertyId },
4238 { &Transform2_ZoomMinimum_Property_GUID, UIA_Transform2ZoomMinimumPropertyId },
4239 { &Transform2_ZoomMaximum_Property_GUID, UIA_Transform2ZoomMaximumPropertyId },
4240 { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId },
4241 { &IsTextEditPatternAvailable_Property_GUID, UIA_IsTextEditPatternAvailablePropertyId },
4242 { &IsPeripheral_Property_GUID, UIA_IsPeripheralPropertyId },
4243 /* Implemented on Win10v1507+. */
4244 { &IsCustomNavigationPatternAvailable_Property_GUID, UIA_IsCustomNavigationPatternAvailablePropertyId },
4245 { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId },
4246 { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId },
4247 { &Level_Property_GUID, UIA_LevelPropertyId },
4248 { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId },
4249 { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId },
4250 /* Implemented on Win10v1809+. */
4251 { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId },
4252 { &LocalizedLandmarkType_Property_GUID, UIA_LocalizedLandmarkTypePropertyId },
4253 { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId },
4254 { &FillColor_Property_GUID, UIA_FillColorPropertyId },
4255 { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId },
4256 { &FillType_Property_GUID, UIA_FillTypePropertyId },
4257 { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId },
4258 { &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId },
4259 { &CenterPoint_Property_GUID, UIA_CenterPointPropertyId },
4260 { &Rotation_Property_GUID, UIA_RotationPropertyId },
4261 { &Size_Property_GUID, UIA_SizePropertyId },
4262 { &IsSelectionPattern2Available_Property_GUID, UIA_IsSelectionPattern2AvailablePropertyId },
4263 { &Selection2_FirstSelectedItem_Property_GUID, UIA_Selection2FirstSelectedItemPropertyId },
4264 { &Selection2_LastSelectedItem_Property_GUID, UIA_Selection2LastSelectedItemPropertyId },
4265 { &Selection2_CurrentSelectedItem_Property_GUID, UIA_Selection2CurrentSelectedItemPropertyId },
4266 { &Selection2_ItemCount_Property_GUID, UIA_Selection2ItemCountPropertyId },
4267 { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId },
4268 { &IsDialog_Property_GUID, UIA_IsDialogPropertyId },
4271 static const struct uia_lookup_id uia_event_lookup_ids[] = {
4272 { &ToolTipOpened_Event_GUID, UIA_ToolTipOpenedEventId },
4273 { &ToolTipClosed_Event_GUID, UIA_ToolTipClosedEventId },
4274 { &StructureChanged_Event_GUID, UIA_StructureChangedEventId },
4275 { &MenuOpened_Event_GUID, UIA_MenuOpenedEventId },
4276 { &AutomationPropertyChanged_Event_GUID, UIA_AutomationPropertyChangedEventId },
4277 { &AutomationFocusChanged_Event_GUID, UIA_AutomationFocusChangedEventId },
4278 { &AsyncContentLoaded_Event_GUID, UIA_AsyncContentLoadedEventId },
4279 { &MenuClosed_Event_GUID, UIA_MenuClosedEventId },
4280 { &LayoutInvalidated_Event_GUID, UIA_LayoutInvalidatedEventId },
4281 { &Invoke_Invoked_Event_GUID, UIA_Invoke_InvokedEventId },
4282 { &SelectionItem_ElementAddedToSelectionEvent_Event_GUID, UIA_SelectionItem_ElementAddedToSelectionEventId },
4283 { &SelectionItem_ElementRemovedFromSelectionEvent_Event_GUID, UIA_SelectionItem_ElementRemovedFromSelectionEventId },
4284 { &SelectionItem_ElementSelectedEvent_Event_GUID, UIA_SelectionItem_ElementSelectedEventId },
4285 { &Selection_InvalidatedEvent_Event_GUID, UIA_Selection_InvalidatedEventId },
4286 { &Text_TextSelectionChangedEvent_Event_GUID, UIA_Text_TextSelectionChangedEventId },
4287 { &Text_TextChangedEvent_Event_GUID, UIA_Text_TextChangedEventId },
4288 { &Window_WindowOpened_Event_GUID, UIA_Window_WindowOpenedEventId },
4289 { &Window_WindowClosed_Event_GUID, UIA_Window_WindowClosedEventId },
4290 { &MenuModeStart_Event_GUID, UIA_MenuModeStartEventId },
4291 { &MenuModeEnd_Event_GUID, UIA_MenuModeEndEventId },
4292 { &InputReachedTarget_Event_GUID, UIA_InputReachedTargetEventId },
4293 { &InputReachedOtherElement_Event_GUID, UIA_InputReachedOtherElementEventId },
4294 { &InputDiscarded_Event_GUID, UIA_InputDiscardedEventId },
4295 /* Implemented on Win8+ */
4296 { &SystemAlert_Event_GUID, UIA_SystemAlertEventId },
4297 { &LiveRegionChanged_Event_GUID, UIA_LiveRegionChangedEventId },
4298 { &HostedFragmentRootsInvalidated_Event_GUID, UIA_HostedFragmentRootsInvalidatedEventId },
4299 { &Drag_DragStart_Event_GUID, UIA_Drag_DragStartEventId },
4300 { &Drag_DragCancel_Event_GUID, UIA_Drag_DragCancelEventId },
4301 { &Drag_DragComplete_Event_GUID, UIA_Drag_DragCompleteEventId },
4302 { &DropTarget_DragEnter_Event_GUID, UIA_DropTarget_DragEnterEventId },
4303 { &DropTarget_DragLeave_Event_GUID, UIA_DropTarget_DragLeaveEventId },
4304 { &DropTarget_Dropped_Event_GUID, UIA_DropTarget_DroppedEventId },
4305 { &TextEdit_TextChanged_Event_GUID, UIA_TextEdit_TextChangedEventId },
4306 { &TextEdit_ConversionTargetChanged_Event_GUID, UIA_TextEdit_ConversionTargetChangedEventId },
4307 /* Implemented on Win10v1809+. */
4308 { &Changes_Event_GUID, UIA_ChangesEventId },
4309 { &Notification_Event_GUID, UIA_NotificationEventId },
4312 static const struct uia_lookup_id uia_pattern_lookup_ids[] = {
4313 { &Invoke_Pattern_GUID, UIA_InvokePatternId },
4314 { &Selection_Pattern_GUID, UIA_SelectionPatternId },
4315 { &Value_Pattern_GUID, UIA_ValuePatternId },
4316 { &RangeValue_Pattern_GUID, UIA_RangeValuePatternId },
4317 { &Scroll_Pattern_GUID, UIA_ScrollPatternId },
4318 { &ExpandCollapse_Pattern_GUID, UIA_ExpandCollapsePatternId },
4319 { &Grid_Pattern_GUID, UIA_GridPatternId },
4320 { &GridItem_Pattern_GUID, UIA_GridItemPatternId },
4321 { &MultipleView_Pattern_GUID, UIA_MultipleViewPatternId },
4322 { &Window_Pattern_GUID, UIA_WindowPatternId },
4323 { &SelectionItem_Pattern_GUID, UIA_SelectionItemPatternId },
4324 { &Dock_Pattern_GUID, UIA_DockPatternId },
4325 { &Table_Pattern_GUID, UIA_TablePatternId },
4326 { &TableItem_Pattern_GUID, UIA_TableItemPatternId },
4327 { &Text_Pattern_GUID, UIA_TextPatternId },
4328 { &Toggle_Pattern_GUID, UIA_TogglePatternId },
4329 { &Transform_Pattern_GUID, UIA_TransformPatternId },
4330 { &ScrollItem_Pattern_GUID, UIA_ScrollItemPatternId },
4331 { &LegacyIAccessible_Pattern_GUID, UIA_LegacyIAccessiblePatternId },
4332 { &ItemContainer_Pattern_GUID, UIA_ItemContainerPatternId },
4333 { &VirtualizedItem_Pattern_GUID, UIA_VirtualizedItemPatternId },
4334 { &SynchronizedInput_Pattern_GUID, UIA_SynchronizedInputPatternId },
4335 /* Implemented on Win8+ */
4336 { &ObjectModel_Pattern_GUID, UIA_ObjectModelPatternId },
4337 { &Annotation_Pattern_GUID, UIA_AnnotationPatternId },
4338 { &Text_Pattern2_GUID, UIA_TextPattern2Id },
4339 { &Styles_Pattern_GUID, UIA_StylesPatternId },
4340 { &Spreadsheet_Pattern_GUID, UIA_SpreadsheetPatternId },
4341 { &SpreadsheetItem_Pattern_GUID, UIA_SpreadsheetItemPatternId },
4342 { &Tranform_Pattern2_GUID, UIA_TransformPattern2Id },
4343 { &TextChild_Pattern_GUID, UIA_TextChildPatternId },
4344 { &Drag_Pattern_GUID, UIA_DragPatternId },
4345 { &DropTarget_Pattern_GUID, UIA_DropTargetPatternId },
4346 { &TextEdit_Pattern_GUID, UIA_TextEditPatternId },
4347 /* Implemented on Win10+. */
4348 { &CustomNavigation_Pattern_GUID, UIA_CustomNavigationPatternId },
4351 static const struct uia_lookup_id uia_control_type_lookup_ids[] = {
4352 { &Button_Control_GUID, UIA_ButtonControlTypeId },
4353 { &Calendar_Control_GUID, UIA_CalendarControlTypeId },
4354 { &CheckBox_Control_GUID, UIA_CheckBoxControlTypeId },
4355 { &ComboBox_Control_GUID, UIA_ComboBoxControlTypeId },
4356 { &Edit_Control_GUID, UIA_EditControlTypeId },
4357 { &Hyperlink_Control_GUID, UIA_HyperlinkControlTypeId },
4358 { &Image_Control_GUID, UIA_ImageControlTypeId },
4359 { &ListItem_Control_GUID, UIA_ListItemControlTypeId },
4360 { &List_Control_GUID, UIA_ListControlTypeId },
4361 { &Menu_Control_GUID, UIA_MenuControlTypeId },
4362 { &MenuBar_Control_GUID, UIA_MenuBarControlTypeId },
4363 { &MenuItem_Control_GUID, UIA_MenuItemControlTypeId },
4364 { &ProgressBar_Control_GUID, UIA_ProgressBarControlTypeId },
4365 { &RadioButton_Control_GUID, UIA_RadioButtonControlTypeId },
4366 { &ScrollBar_Control_GUID, UIA_ScrollBarControlTypeId },
4367 { &Slider_Control_GUID, UIA_SliderControlTypeId },
4368 { &Spinner_Control_GUID, UIA_SpinnerControlTypeId },
4369 { &StatusBar_Control_GUID, UIA_StatusBarControlTypeId },
4370 { &Tab_Control_GUID, UIA_TabControlTypeId },
4371 { &TabItem_Control_GUID, UIA_TabItemControlTypeId },
4372 { &Text_Control_GUID, UIA_TextControlTypeId },
4373 { &ToolBar_Control_GUID, UIA_ToolBarControlTypeId },
4374 { &ToolTip_Control_GUID, UIA_ToolTipControlTypeId },
4375 { &Tree_Control_GUID, UIA_TreeControlTypeId },
4376 { &TreeItem_Control_GUID, UIA_TreeItemControlTypeId },
4377 { &Custom_Control_GUID, UIA_CustomControlTypeId },
4378 { &Group_Control_GUID, UIA_GroupControlTypeId },
4379 { &Thumb_Control_GUID, UIA_ThumbControlTypeId },
4380 { &DataGrid_Control_GUID, UIA_DataGridControlTypeId },
4381 { &DataItem_Control_GUID, UIA_DataItemControlTypeId },
4382 { &Document_Control_GUID, UIA_DocumentControlTypeId },
4383 { &SplitButton_Control_GUID, UIA_SplitButtonControlTypeId },
4384 { &Window_Control_GUID, UIA_WindowControlTypeId },
4385 { &Pane_Control_GUID, UIA_PaneControlTypeId },
4386 { &Header_Control_GUID, UIA_HeaderControlTypeId },
4387 { &HeaderItem_Control_GUID, UIA_HeaderItemControlTypeId },
4388 { &Table_Control_GUID, UIA_TableControlTypeId },
4389 { &TitleBar_Control_GUID, UIA_TitleBarControlTypeId },
4390 { &Separator_Control_GUID, UIA_SeparatorControlTypeId },
4391 /* Implemented on Win8+ */
4392 { &SemanticZoom_Control_GUID, UIA_SemanticZoomControlTypeId },
4393 { &AppBar_Control_GUID, UIA_AppBarControlTypeId },
4396 static void test_UiaLookupId(void)
4398 static const struct {
4399 const char *id_type_name;
4400 int id_type;
4401 const struct uia_lookup_id *ids;
4402 int ids_count;
4403 } tests[] =
4405 { "property", AutomationIdentifierType_Property, uia_property_lookup_ids, ARRAY_SIZE(uia_property_lookup_ids) },
4406 { "event", AutomationIdentifierType_Event, uia_event_lookup_ids, ARRAY_SIZE(uia_event_lookup_ids) },
4407 { "pattern", AutomationIdentifierType_Pattern, uia_pattern_lookup_ids, ARRAY_SIZE(uia_pattern_lookup_ids) },
4408 { "control_type", AutomationIdentifierType_ControlType, uia_control_type_lookup_ids, ARRAY_SIZE(uia_control_type_lookup_ids) },
4410 unsigned int i, y;
4412 for (i = 0; i < ARRAY_SIZE(tests); i++)
4414 for (y = 0; y < tests[i].ids_count; y++)
4416 int id = UiaLookupId(tests[i].id_type, tests[i].ids[y].guid);
4418 if (!id)
4420 win_skip("No %s id for GUID %s, skipping further tests.\n", tests[i].id_type_name, debugstr_guid(tests[i].ids[y].guid));
4421 break;
4424 ok(id == tests[i].ids[y].id, "Unexpected %s id, expected %d, got %d\n", tests[i].id_type_name, tests[i].ids[y].id, id);
4429 static const struct prov_method_sequence node_from_prov1[] = {
4430 { &Provider, PROV_GET_PROVIDER_OPTIONS },
4431 { 0 }
4434 static const struct prov_method_sequence node_from_prov2[] = {
4435 { &Provider, PROV_GET_PROVIDER_OPTIONS },
4436 /* Win10v1507 and below call this. */
4437 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4438 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4439 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
4440 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4441 /* Only called on Windows versions past Win10v1507. */
4442 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4443 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4444 { 0 }
4447 static const struct prov_method_sequence node_from_prov3[] = {
4448 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
4449 /* Win10v1507 and below call this. */
4450 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4451 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4452 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
4453 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4454 /* Only called on Windows versions past Win10v1507. */
4455 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4456 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4457 { 0 }
4460 static const struct prov_method_sequence node_from_prov4[] = {
4461 { &Provider, PROV_GET_PROVIDER_OPTIONS },
4462 /* Win10v1507 and below call this. */
4463 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4464 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4465 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4466 /* Only called on Windows versions past Win10v1507. */
4467 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4468 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4469 { 0 }
4472 static const struct prov_method_sequence node_from_prov5[] = {
4473 { &Provider, PROV_GET_PROVIDER_OPTIONS },
4474 /* Win10v1507 and below call this. */
4475 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4476 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4477 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4478 /* Win10v1507 and below call this. */
4479 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4480 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4481 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4482 /* These three are only done on Win10v1507 and below. */
4483 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4484 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4485 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
4486 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4487 /* This is only done on Win10v1507. */
4488 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4489 /* Only called on Windows versions past Win10v1507. */
4490 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4491 /* Win10v1507 and below call this. */
4492 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
4493 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4494 { 0 }
4497 static const struct prov_method_sequence node_from_prov6[] = {
4498 { &Provider, PROV_GET_PROVIDER_OPTIONS },
4499 /* Win10v1507 and below call this. */
4500 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4501 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4502 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4503 /* Win10v1507 and below call this. */
4504 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4505 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4506 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4507 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4508 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4509 /* Only called on Windows versions past Win10v1507. */
4510 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
4511 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
4512 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4513 /* This is only done on Win10v1507. */
4514 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4515 /* Only called on Windows versions past Win10v1507. */
4516 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4517 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4518 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4519 { 0 }
4522 static const struct prov_method_sequence node_from_prov7[] = {
4523 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
4524 /* Win10v1507 and below call this. */
4525 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4526 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4527 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4528 /* Win10v1507 and below call this. */
4529 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4530 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4531 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4532 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4533 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
4534 /* Only called on Windows versions past Win10v1507. */
4535 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
4536 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
4537 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4538 /* This is only done on Win10v1507. */
4539 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4540 /* Only called on Windows versions past Win10v1507. */
4541 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4542 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4543 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
4544 { 0 }
4547 static const struct prov_method_sequence node_from_prov8[] = {
4548 { &Provider, PROV_GET_PROVIDER_OPTIONS },
4549 /* Win10v1507 and below call this. */
4550 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4551 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4552 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
4553 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4554 /* Only called on Windows versions past Win10v1507. */
4555 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4556 { 0 }
4559 static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com);
4560 static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param)
4562 HUIANODE node = param;
4563 HRESULT hr;
4564 VARIANT v;
4567 * Since this is a node representing an IRawElementProviderSimple with
4568 * ProviderOptions_UseComThreading set, it is only usable in threads that
4569 * have initialized COM.
4571 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
4572 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
4574 CoInitializeEx(NULL, COINIT_MULTITHREADED);
4576 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
4577 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4578 check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v, FALSE);
4581 * When retrieving a UIAutomationType_Element property, if UseComThreading
4582 * is set, we'll get an HUIANODE that will make calls inside of the
4583 * apartment of the node it is retrieved from. I.e, if we received a node
4584 * with UseComThreading set from another node with UseComThreading set
4585 * inside of an STA, the returned node will have all of its methods called
4586 * from the STA thread.
4588 Provider_child.prov_opts = ProviderOptions_UseComThreading | ProviderOptions_ServerSideProvider;
4589 Provider_child.expected_tid = Provider.expected_tid;
4590 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
4591 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4592 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
4594 /* Unset ProviderOptions_UseComThreading. */
4595 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
4596 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
4597 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4600 * ProviderOptions_UseComThreading not set, GetPropertyValue will be
4601 * called on the current thread.
4603 Provider_child.expected_tid = GetCurrentThreadId();
4604 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
4606 CoUninitialize();
4608 return 0;
4611 static void test_uia_node_from_prov_com_threading(void)
4613 HANDLE thread;
4614 HUIANODE node;
4615 HRESULT hr;
4617 /* Test ProviderOptions_UseComThreading. */
4618 Provider.hwnd = NULL;
4619 prov_root = NULL;
4620 Provider.prov_opts = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading;
4621 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4622 ok_method_sequence(node_from_prov8, "node_from_prov8");
4625 * On Windows versions prior to Windows 10, UiaNodeFromProvider ignores the
4626 * ProviderOptions_UseComThreading flag.
4628 if (hr == S_OK)
4630 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
4631 UiaNodeRelease(node);
4632 return;
4634 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx.\n", hr);
4636 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
4637 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4639 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
4640 ok_method_sequence(node_from_prov8, "node_from_prov8");
4642 Provider.expected_tid = GetCurrentThreadId();
4643 thread = CreateThread(NULL, 0, uia_node_from_provider_test_com_thread, (void *)node, 0, NULL);
4644 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
4646 MSG msg;
4647 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
4649 TranslateMessage(&msg);
4650 DispatchMessageW(&msg);
4653 CloseHandle(thread);
4655 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4656 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
4657 Provider_child.expected_tid = Provider.expected_tid = 0;
4659 CoUninitialize();
4661 static void test_UiaNodeFromProvider(void)
4663 WNDCLASSA cls;
4664 HUIANODE node;
4665 HRESULT hr;
4666 ULONG ref;
4667 HWND hwnd;
4668 VARIANT v;
4670 cls.style = 0;
4671 cls.lpfnWndProc = test_wnd_proc;
4672 cls.cbClsExtra = 0;
4673 cls.cbWndExtra = 0;
4674 cls.hInstance = GetModuleHandleA(NULL);
4675 cls.hIcon = 0;
4676 cls.hCursor = NULL;
4677 cls.hbrBackground = NULL;
4678 cls.lpszMenuName = NULL;
4679 cls.lpszClassName = "UiaNodeFromProvider class";
4681 RegisterClassA(&cls);
4683 hwnd = CreateWindowA("UiaNodeFromProvider class", "Test window", WS_OVERLAPPEDWINDOW,
4684 0, 0, 100, 100, NULL, NULL, NULL, NULL);
4686 /* Run these tests early, we end up in an implicit MTA later. */
4687 test_uia_node_from_prov_com_threading();
4689 CoInitializeEx(NULL, COINIT_MULTITHREADED);
4691 hr = UiaNodeFromProvider(NULL, &node);
4692 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4694 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, NULL);
4695 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4697 /* Must have a successful call to get_ProviderOptions. */
4698 Provider.prov_opts = 0;
4699 node = (void *)0xdeadbeef;
4700 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4701 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
4702 ok(!node, "node != NULL\n");
4703 ok_method_sequence(node_from_prov1, "node_from_prov1");
4705 /* No HWND exposed through Provider. */
4706 Provider.prov_opts = ProviderOptions_ServerSideProvider;
4707 node = (void *)0xdeadbeef;
4708 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4709 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
4711 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
4712 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4713 if (SUCCEEDED(hr))
4715 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
4716 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
4717 VariantClear(&v);
4720 ok_method_sequence(node_from_prov2, "node_from_prov2");
4722 /* HUIANODE represents a COM interface. */
4723 ref = IUnknown_AddRef((IUnknown *)node);
4724 ok(ref == 2, "Unexpected refcnt %ld\n", ref);
4726 ref = IUnknown_AddRef((IUnknown *)node);
4727 ok(ref == 3, "Unexpected refcnt %ld\n", ref);
4729 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4731 ref = IUnknown_Release((IUnknown *)node);
4732 ok(ref == 1, "Unexpected refcnt %ld\n", ref);
4734 ref = IUnknown_Release((IUnknown *)node);
4735 ok(ref == 0, "Unexpected refcnt %ld\n", ref);
4736 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
4739 * No HWND exposed through Provider_child, but it returns a parent from
4740 * NavigateDirection_Parent. Behavior doesn't change.
4742 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
4743 node = (void *)0xdeadbeef;
4744 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
4745 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
4747 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
4748 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4749 if (SUCCEEDED(hr))
4751 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
4752 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
4753 VariantClear(&v);
4756 ok_method_sequence(node_from_prov3, "node_from_prov3");
4757 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4758 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
4760 /* HWND exposed, but Provider2 not returned from WM_GETOBJECT. */
4761 Provider.hwnd = hwnd;
4762 prov_root = NULL;
4763 node = (void *)0xdeadbeef;
4764 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
4765 /* Win10v1507 and below send this, Windows 7 sends it twice. */
4766 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
4767 Provider.ignore_hwnd_prop = TRUE;
4768 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4769 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4770 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
4771 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
4772 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
4774 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
4775 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4776 if (SUCCEEDED(hr))
4778 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
4779 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
4780 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
4781 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
4782 VariantClear(&v);
4785 Provider.ignore_hwnd_prop = FALSE;
4786 ok_method_sequence(node_from_prov4, "node_from_prov4");
4788 ok(!!node, "node == NULL\n");
4789 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4790 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
4793 * Provider is our main provider, since Provider2 is also a main, it won't
4794 * get added.
4796 Provider.hwnd = Provider2.hwnd = hwnd;
4797 Provider.prov_opts = Provider2.prov_opts = ProviderOptions_ServerSideProvider;
4798 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = TRUE;
4799 prov_root = &Provider2.IRawElementProviderSimple_iface;
4800 node = (void *)0xdeadbeef;
4801 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
4802 /* Windows 7 sends this. */
4803 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4804 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4805 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4806 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
4807 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
4809 /* Win10v1507 and below hold a reference to the root provider for the HWND */
4810 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
4811 ok(!!node, "node == NULL\n");
4813 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
4814 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4815 if (SUCCEEDED(hr))
4817 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
4818 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
4819 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
4820 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
4821 VariantClear(&v);
4824 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = FALSE;
4825 ok_method_sequence(node_from_prov5, "node_from_prov5");
4827 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4828 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
4829 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
4832 * Provider is classified as an Hwnd provider, Provider2 will become our
4833 * Main provider since we don't have one already.
4835 Provider.prov_opts = ProviderOptions_ClientSideProvider;
4836 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
4837 prov_root = &Provider2.IRawElementProviderSimple_iface;
4838 node = (void *)0xdeadbeef;
4839 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
4840 /* Windows 7 sends this. */
4841 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4842 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
4843 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4844 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
4845 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
4847 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
4848 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4849 if (SUCCEEDED(hr))
4851 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
4852 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
4853 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
4854 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
4855 VariantClear(&v);
4857 ok_method_sequence(node_from_prov6, "node_from_prov6");
4859 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
4860 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
4862 ok(!!node, "node == NULL\n");
4863 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4864 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
4865 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
4867 /* Provider_child has a parent, so it will be "(parent link)". */
4868 Provider_child.prov_opts = ProviderOptions_ClientSideProvider;
4869 Provider_child.hwnd = hwnd;
4870 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
4871 prov_root = &Provider2.IRawElementProviderSimple_iface;
4872 node = (void *)0xdeadbeef;
4873 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
4874 /* Windows 7 sends this. */
4875 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4876 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
4877 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4878 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
4879 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
4881 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
4882 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
4883 if (SUCCEEDED(hr))
4885 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
4886 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", FALSE);
4887 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
4888 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_child", TRUE);
4889 VariantClear(&v);
4891 ok_method_sequence(node_from_prov7, "node_from_prov7");
4893 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
4894 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
4896 ok(!!node, "node == NULL\n");
4897 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
4898 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
4899 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
4901 CoUninitialize();
4902 DestroyWindow(hwnd);
4903 UnregisterClassA("UiaNodeFromProvider class", NULL);
4904 prov_root = NULL;
4907 /* Sequence for types other than UIAutomationType_Element. */
4908 static const struct prov_method_sequence get_prop_seq[] = {
4909 { &Provider, PROV_GET_PROPERTY_VALUE },
4910 { 0 }
4913 /* Sequence for getting a property that returns an invalid type. */
4914 static const struct prov_method_sequence get_prop_invalid_type_seq[] = {
4915 { &Provider, PROV_GET_PROPERTY_VALUE },
4916 /* Windows 7 calls this. */
4917 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4918 { 0 }
4921 /* UIAutomationType_Element sequence. */
4922 static const struct prov_method_sequence get_elem_prop_seq[] = {
4923 { &Provider, PROV_GET_PROPERTY_VALUE },
4924 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
4925 /* Win10v1507 and below call this. */
4926 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4927 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4928 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
4929 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4930 /* Only called on Windows versions past Win10v1507. */
4931 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
4932 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL },
4933 { 0 }
4936 /* UIAutomationType_ElementArray sequence. */
4937 static const struct prov_method_sequence get_elem_arr_prop_seq[] = {
4938 { &Provider, PROV_GET_PROPERTY_VALUE },
4939 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
4940 /* Win10v1507 and below call this. */
4941 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4942 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4943 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
4944 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4945 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
4946 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS },
4947 /* Win10v1507 and below call this. */
4948 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4949 { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
4950 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
4951 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
4952 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS },
4953 { &Provider_child, PROV_GET_PROPERTY_VALUE },
4954 { &Provider_child2, PROV_GET_PROPERTY_VALUE },
4955 { 0 }
4958 static const struct prov_method_sequence get_pattern_prop_seq[] = {
4959 { &Provider, PROV_GET_PATTERN_PROV },
4960 { 0 }
4963 static const struct prov_method_sequence get_bounding_rect_seq[] = {
4964 NODE_CREATE_SEQ(&Provider_child),
4965 { &Provider_child, FRAG_GET_BOUNDING_RECT },
4967 * Win10v21H2+ and above call these, attempting to get the fragment root's
4968 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
4970 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
4971 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
4972 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4973 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
4974 { 0 }
4977 static const struct prov_method_sequence get_bounding_rect_seq2[] = {
4978 { &Provider, PROV_GET_PROPERTY_VALUE },
4979 NODE_CREATE_SEQ(&Provider_child),
4980 { &Provider_child, FRAG_GET_BOUNDING_RECT },
4982 * Win10v21H2+ and above call these, attempting to get the fragment root's
4983 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
4985 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
4986 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
4987 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
4988 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
4989 { 0 }
4992 static const struct prov_method_sequence get_bounding_rect_seq3[] = {
4993 { &Provider_child, FRAG_GET_BOUNDING_RECT },
4995 * Win10v21H2+ and above call these, attempting to get the fragment root's
4996 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
4998 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
4999 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5000 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5001 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5002 { 0 }
5005 static const struct prov_method_sequence get_empty_bounding_rect_seq[] = {
5006 { &Provider_child, FRAG_GET_BOUNDING_RECT },
5007 { 0 }
5010 static void set_uia_rect(struct UiaRect *rect, double left, double top, double width, double height)
5012 rect->left = left;
5013 rect->top = top;
5014 rect->width = width;
5015 rect->height = height;
5018 #define check_uia_rect_val( v, rect ) \
5019 check_uia_rect_val_( (v), (rect), __FILE__, __LINE__)
5020 static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *file, int line)
5022 LONG lbound, ubound, elems, idx;
5023 SAFEARRAY *sa;
5024 double tmp[4];
5025 VARTYPE vt;
5026 HRESULT hr;
5027 UINT dims;
5029 ok_(file, line)(V_VT(v) == (VT_R8 | VT_ARRAY), "Unexpected rect VT hr %d.\n", V_VT(v));
5030 if (V_VT(v) != (VT_R8 | VT_ARRAY))
5031 return;
5033 sa = V_ARRAY(v);
5034 hr = SafeArrayGetVartype(sa, &vt);
5035 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5036 ok_(file, line)(vt == VT_R8, "Unexpected vt %d\n", vt);
5038 dims = SafeArrayGetDim(sa);
5039 ok_(file, line)(dims == 1, "Unexpected dims %d\n", dims);
5041 lbound = ubound = elems = 0;
5042 hr = SafeArrayGetLBound(sa, 1, &lbound);
5043 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
5044 ok_(file, line)(lbound == 0, "Unexpected lbound %ld\n", lbound);
5046 hr = SafeArrayGetUBound(sa, 1, &ubound);
5047 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
5048 ok_(file, line)(ubound == 3, "Unexpected ubound %ld\n", ubound);
5050 elems = (ubound - lbound) + 1;
5051 ok_(file, line)(elems == 4, "Unexpected rect elems %ld\n", elems);
5053 for (idx = 0; idx < ARRAY_SIZE(tmp); idx++)
5055 hr = SafeArrayGetElement(sa, &idx, &tmp[idx]);
5056 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetElement at idx %ld.\n", hr, idx);
5059 ok_(file, line)(tmp[0] == rect->left, "Unexpected left value %f, expected %f\n", tmp[0], rect->left);
5060 ok_(file, line)(tmp[1] == rect->top, "Unexpected top value %f, expected %f\n", tmp[1], rect->top);
5061 ok_(file, line)(tmp[2] == rect->width, "Unexpected width value %f, expected %f\n", tmp[2], rect->width);
5062 ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height);
5065 #define check_uia_rect_rect_val( rect, uia_rect ) \
5066 check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__)
5067 static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line)
5069 ok_(file, line)(rect->left == (LONG)uia_rect->left, "Unexpected left value %ld, expected %ld\n", rect->left, (LONG)uia_rect->left);
5070 ok_(file, line)(rect->top == (LONG)uia_rect->top, "Unexpected top value %ld, expected %ld\n", rect->top, (LONG)uia_rect->top);
5071 ok_(file, line)(rect->right == (LONG)(uia_rect->left + uia_rect->width), "Unexpected right value %ld, expected %ld\n", rect->right,
5072 (LONG)(uia_rect->left + uia_rect->width));
5073 ok_(file, line)(rect->bottom == (LONG)(uia_rect->top + uia_rect->height), "Unexpected bottom value %ld, expected %ld\n", rect->bottom,
5074 (LONG)(uia_rect->top + uia_rect->height));
5077 static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com)
5079 LONG idx;
5081 switch (type)
5083 case UIAutomationType_String:
5084 ok(V_VT(v) == VT_BSTR, "Unexpected VT %d\n", V_VT(v));
5085 ok(!lstrcmpW(V_BSTR(v), uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(v)));
5086 ok_method_sequence(get_prop_seq, NULL);
5087 break;
5089 case UIAutomationType_Bool:
5090 ok(V_VT(v) == VT_BOOL, "Unexpected VT %d\n", V_VT(v));
5092 /* UIA_IsKeyboardFocusablePropertyId is broken on Win8 and Win10v1507. */
5093 if (prop_id == UIA_IsKeyboardFocusablePropertyId)
5094 ok(check_variant_bool(v, TRUE) || broken(check_variant_bool(v, FALSE)),
5095 "Unexpected BOOL %#x\n", V_BOOL(v));
5096 else
5097 ok(check_variant_bool(v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(v));
5098 ok_method_sequence(get_prop_seq, NULL);
5099 break;
5101 case UIAutomationType_Int:
5102 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
5104 if (prop_id == UIA_NativeWindowHandlePropertyId)
5105 ok(ULongToHandle(V_I4(v)) == Provider.hwnd, "Unexpected I4 %#lx\n", V_I4(v));
5106 else
5107 ok(V_I4(v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(v));
5108 ok_method_sequence(get_prop_seq, NULL);
5109 break;
5111 case UIAutomationType_IntArray:
5112 ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v));
5114 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
5116 ULONG val;
5118 SafeArrayGetElement(V_ARRAY(v), &idx, &val);
5119 ok(val == uia_i4_arr_prop_val[idx], "Unexpected I4 %#lx at idx %ld\n", val, idx);
5121 ok_method_sequence(get_prop_seq, NULL);
5122 break;
5124 case UIAutomationType_Double:
5125 ok(V_VT(v) == VT_R8, "Unexpected VT %d\n", V_VT(v));
5126 ok(V_R8(v) == uia_r8_prop_val, "Unexpected R8 %lf\n", V_R8(v));
5127 ok_method_sequence(get_prop_seq, NULL);
5128 break;
5130 case UIAutomationType_DoubleArray:
5131 ok(V_VT(v) == (VT_ARRAY | VT_R8), "Unexpected VT %d\n", V_VT(v));
5132 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
5134 double val;
5136 SafeArrayGetElement(V_ARRAY(v), &idx, &val);
5137 ok(val == uia_r8_arr_prop_val[idx], "Unexpected R8 %lf at idx %ld\n", val, idx);
5139 ok_method_sequence(get_prop_seq, NULL);
5140 break;
5142 case UIAutomationType_Element:
5144 HUIANODE tmp_node;
5145 HRESULT hr;
5146 VARIANT v1;
5148 if (from_com)
5150 IUIAutomationElement *elem;
5152 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
5153 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElement, (void **)&elem);
5154 VariantClear(v);
5155 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5156 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
5158 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_ControlTypePropertyId, TRUE, &v1);
5159 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5160 IUIAutomationElement_Release(elem);
5162 else
5164 #ifdef _WIN64
5165 ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
5166 tmp_node = (HUIANODE)V_I8(v);
5167 #else
5168 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
5169 tmp_node = (HUIANODE)V_I4(v);
5170 #endif
5171 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
5173 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
5174 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5175 ok(UiaNodeRelease(tmp_node), "Failed to release node\n");
5178 ok(V_VT(&v1) == VT_I4, "Unexpected VT %d\n", V_VT(&v1));
5179 ok(V_I4(&v1) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v1));
5180 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
5182 ok_method_sequence(get_elem_prop_seq, NULL);
5183 break;
5186 case UIAutomationType_ElementArray:
5187 ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v));
5188 if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN))
5189 break;
5191 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
5192 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
5193 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
5195 HUIANODE tmp_node;
5196 HRESULT hr;
5197 VARIANT v1;
5199 SafeArrayGetElement(V_ARRAY(v), &idx, &tmp_node);
5201 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
5202 ok(hr == S_OK, "node[%ld] Unexpected hr %#lx\n", idx, hr);
5203 ok(V_VT(&v1) == VT_I4, "node[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
5204 ok(V_I4(&v1) == uia_i4_prop_val, "node[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
5206 ok(UiaNodeRelease(tmp_node), "Failed to release node[%ld]\n", idx);
5207 VariantClear(&v1);
5210 VariantClear(v);
5211 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
5212 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
5213 ok_method_sequence(get_elem_arr_prop_seq, NULL);
5214 break;
5216 default:
5217 break;
5220 VariantClear(v);
5221 V_VT(v) = VT_EMPTY;
5224 struct uia_element_property {
5225 const GUID *prop_guid;
5226 enum UIAutomationType type;
5227 BOOL skip_invalid;
5230 static const struct uia_element_property element_properties[] = {
5231 { &ProcessId_Property_GUID, UIAutomationType_Int, TRUE },
5232 { &ControlType_Property_GUID, UIAutomationType_Int },
5233 { &LocalizedControlType_Property_GUID, UIAutomationType_String, TRUE },
5234 { &Name_Property_GUID, UIAutomationType_String },
5235 { &AcceleratorKey_Property_GUID, UIAutomationType_String },
5236 { &AccessKey_Property_GUID, UIAutomationType_String },
5237 { &HasKeyboardFocus_Property_GUID, UIAutomationType_Bool },
5238 { &IsKeyboardFocusable_Property_GUID, UIAutomationType_Bool },
5239 { &IsEnabled_Property_GUID, UIAutomationType_Bool },
5240 { &AutomationId_Property_GUID, UIAutomationType_String },
5241 { &ClassName_Property_GUID, UIAutomationType_String },
5242 { &HelpText_Property_GUID, UIAutomationType_String },
5243 { &Culture_Property_GUID, UIAutomationType_Int },
5244 { &IsControlElement_Property_GUID, UIAutomationType_Bool },
5245 { &IsContentElement_Property_GUID, UIAutomationType_Bool },
5246 { &LabeledBy_Property_GUID, UIAutomationType_Element },
5247 { &IsPassword_Property_GUID, UIAutomationType_Bool },
5248 { &NewNativeWindowHandle_Property_GUID, UIAutomationType_Int },
5249 { &ItemType_Property_GUID, UIAutomationType_String },
5250 { &IsOffscreen_Property_GUID, UIAutomationType_Bool },
5251 { &Orientation_Property_GUID, UIAutomationType_Int },
5252 { &FrameworkId_Property_GUID, UIAutomationType_String },
5253 { &IsRequiredForForm_Property_GUID, UIAutomationType_Bool },
5254 { &ItemStatus_Property_GUID, UIAutomationType_String },
5255 { &AriaRole_Property_GUID, UIAutomationType_String },
5256 { &AriaProperties_Property_GUID, UIAutomationType_String },
5257 { &IsDataValidForForm_Property_GUID, UIAutomationType_Bool },
5258 { &ControllerFor_Property_GUID, UIAutomationType_ElementArray },
5259 { &DescribedBy_Property_GUID, UIAutomationType_ElementArray },
5260 { &FlowsTo_Property_GUID, UIAutomationType_ElementArray },
5261 /* Implemented on Win8+ */
5262 { &OptimizeForVisualContent_Property_GUID, UIAutomationType_Bool },
5263 { &LiveSetting_Property_GUID, UIAutomationType_Int },
5264 { &FlowsFrom_Property_GUID, UIAutomationType_ElementArray },
5265 { &IsPeripheral_Property_GUID, UIAutomationType_Bool },
5266 /* Implemented on Win10v1507+. */
5267 { &PositionInSet_Property_GUID, UIAutomationType_Int },
5268 { &SizeOfSet_Property_GUID, UIAutomationType_Int },
5269 { &Level_Property_GUID, UIAutomationType_Int },
5270 { &AnnotationTypes_Property_GUID, UIAutomationType_IntArray },
5271 { &AnnotationObjects_Property_GUID, UIAutomationType_ElementArray },
5272 /* Implemented on Win10v1809+. */
5273 { &LandmarkType_Property_GUID, UIAutomationType_Int },
5274 { &LocalizedLandmarkType_Property_GUID, UIAutomationType_String, TRUE },
5275 { &FullDescription_Property_GUID, UIAutomationType_String },
5276 { &FillColor_Property_GUID, UIAutomationType_Int },
5277 { &OutlineColor_Property_GUID, UIAutomationType_IntArray },
5278 { &FillType_Property_GUID, UIAutomationType_Int },
5279 { &VisualEffects_Property_GUID, UIAutomationType_Int },
5280 { &OutlineThickness_Property_GUID, UIAutomationType_DoubleArray },
5281 { &Rotation_Property_GUID, UIAutomationType_Double },
5282 { &Size_Property_GUID, UIAutomationType_DoubleArray },
5283 { &HeadingLevel_Property_GUID, UIAutomationType_Int },
5284 { &IsDialog_Property_GUID, UIAutomationType_Bool },
5287 static void test_UiaGetPropertyValue(void)
5289 const struct uia_element_property *elem_prop;
5290 struct UiaRect rect;
5291 IUnknown *unk_ns;
5292 unsigned int i;
5293 HUIANODE node;
5294 int prop_id;
5295 HRESULT hr;
5296 VARIANT v;
5298 CoInitializeEx(NULL, COINIT_MULTITHREADED);
5300 Provider.prov_opts = ProviderOptions_ServerSideProvider;
5301 Provider_child.prov_opts = Provider_child2.prov_opts = ProviderOptions_ServerSideProvider;
5302 Provider.hwnd = Provider_child.hwnd = Provider_child2.hwnd = NULL;
5303 node = (void *)0xdeadbeef;
5304 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5305 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5306 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5307 ok_method_sequence(node_from_prov8, NULL);
5309 hr = UiaGetReservedNotSupportedValue(&unk_ns);
5310 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5312 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
5314 elem_prop = &element_properties[i];
5316 Provider.ret_invalid_prop_type = FALSE;
5317 VariantClear(&v);
5318 prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid);
5319 if (!prop_id)
5321 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
5322 break;
5324 winetest_push_context("prop_id %d", prop_id);
5325 hr = UiaGetPropertyValue(node, prop_id, &v);
5326 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5327 check_uia_prop_val(prop_id, elem_prop->type, &v, FALSE);
5330 * Some properties have special behavior if an invalid value is
5331 * returned, skip them here.
5333 if (!elem_prop->skip_invalid)
5335 Provider.ret_invalid_prop_type = TRUE;
5336 hr = UiaGetPropertyValue(node, prop_id, &v);
5337 if (hr == E_NOTIMPL)
5338 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5339 else
5340 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5341 if (SUCCEEDED(hr))
5343 ok_method_sequence(get_prop_invalid_type_seq, NULL);
5344 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
5345 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
5346 VariantClear(&v);
5350 winetest_pop_context();
5353 /* IValueProvider pattern property IDs. */
5354 Provider.value_pattern_data.is_supported = FALSE;
5355 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
5356 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5357 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
5358 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
5359 ok_method_sequence(get_pattern_prop_seq, NULL);
5360 VariantClear(&v);
5362 Provider.value_pattern_data.is_supported = TRUE;
5363 for (i = 0; i < 2; i++)
5365 Provider.value_pattern_data.is_read_only = i;
5367 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
5368 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5369 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
5370 ok(check_variant_bool(&v, i), "Unexpected BOOL %#x\n", V_BOOL(&v));
5371 ok_method_sequence(get_pattern_prop_seq, NULL);
5372 VariantClear(&v);
5375 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5376 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
5377 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
5380 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
5381 * It's the only version with this behavior.
5383 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
5385 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
5386 goto exit;
5389 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
5390 node = (void *)0xdeadbeef;
5391 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
5392 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5393 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
5395 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
5396 set_uia_rect(&rect, 0, 0, 50, 50);
5397 Provider_child.bounds_rect = rect;
5398 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
5399 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5400 check_uia_rect_val(&v, &rect);
5401 VariantClear(&v);
5403 ok_method_sequence(get_bounding_rect_seq, "get_bounding_rect_seq");
5405 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
5406 set_uia_rect(&rect, 0, 0, 0, 0);
5407 Provider_child.bounds_rect = rect;
5408 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
5409 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5410 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
5411 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
5412 VariantClear(&v);
5413 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
5415 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5416 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
5417 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
5419 exit:
5421 IUnknown_Release(unk_ns);
5422 CoUninitialize();
5425 static const struct prov_method_sequence get_runtime_id1[] = {
5426 { &Provider_child, FRAG_GET_RUNTIME_ID },
5427 { 0 }
5430 static const struct prov_method_sequence get_runtime_id2[] = {
5431 { &Provider_child, FRAG_GET_RUNTIME_ID },
5432 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
5433 { 0 }
5436 static const struct prov_method_sequence get_runtime_id3[] = {
5437 { &Provider_child, FRAG_GET_RUNTIME_ID },
5438 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
5439 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5440 /* Not called on Windows 7. */
5441 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5442 /* Only called on Win8+. */
5443 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5444 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5445 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5446 { &Provider2, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5447 { 0 }
5450 static const struct prov_method_sequence get_runtime_id4[] = {
5451 { &Provider_child, FRAG_GET_RUNTIME_ID },
5452 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
5453 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5454 /* Not called on Windows 7. */
5455 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5456 /* These methods are only called on Win8+. */
5457 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5458 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5459 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5460 { 0 }
5463 static const struct prov_method_sequence get_runtime_id5[] = {
5464 { &Provider_child, FRAG_GET_RUNTIME_ID },
5465 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
5466 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5467 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5468 { 0 }
5471 static void test_UiaGetRuntimeId(void)
5473 const int root_prov_opts[] = { ProviderOptions_ServerSideProvider, ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider,
5474 ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider };
5475 int rt_id[4], tmp, i;
5476 IUnknown *unk_ns;
5477 SAFEARRAY *sa;
5478 WNDCLASSA cls;
5479 HUIANODE node;
5480 HRESULT hr;
5481 HWND hwnd;
5482 VARIANT v;
5484 VariantInit(&v);
5485 cls.style = 0;
5486 cls.lpfnWndProc = test_wnd_proc;
5487 cls.cbClsExtra = 0;
5488 cls.cbWndExtra = 0;
5489 cls.hInstance = GetModuleHandleA(NULL);
5490 cls.hIcon = 0;
5491 cls.hCursor = NULL;
5492 cls.hbrBackground = NULL;
5493 cls.lpszMenuName = NULL;
5494 cls.lpszClassName = "UiaGetRuntimeId class";
5496 RegisterClassA(&cls);
5498 hwnd = CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW,
5499 0, 0, 100, 100, NULL, NULL, NULL, NULL);
5501 hr = UiaGetReservedNotSupportedValue(&unk_ns);
5502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5504 CoInitializeEx(NULL, COINIT_MULTITHREADED);
5505 Provider.prov_opts = Provider2.prov_opts = Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
5506 Provider.hwnd = Provider2.hwnd = Provider_child.hwnd = NULL;
5507 node = (void *)0xdeadbeef;
5508 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
5509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5510 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
5512 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5513 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5514 if (SUCCEEDED(hr))
5516 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
5517 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
5518 VariantClear(&v);
5520 ok_method_sequence(node_from_prov3, NULL);
5522 /* NULL runtime ID. */
5523 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0;
5524 sa = (void *)0xdeadbeef;
5525 hr = UiaGetRuntimeId(node, &sa);
5526 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5527 ok(!sa, "sa != NULL\n");
5528 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
5530 /* No UiaAppendRuntimeId prefix, returns GetRuntimeId array directly. */
5531 Provider_child.runtime_id[0] = rt_id[0] = 5;
5532 Provider_child.runtime_id[1] = rt_id[1] = 2;
5533 sa = (void *)0xdeadbeef;
5534 hr = UiaGetRuntimeId(node, &sa);
5535 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5536 ok(!!sa, "sa == NULL\n");
5537 check_runtime_id(rt_id, 2, sa);
5538 SafeArrayDestroy(sa);
5539 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
5542 * If a provider returns a RuntimeId beginning with the constant
5543 * UiaAppendRuntimeId, UI Automation will add a prefix based on the
5544 * providers HWND fragment root before returning to the client. The added
5545 * prefix is 3 int values, with:
5547 * idx[0] always being 42. (UIA_RUNTIME_ID_PREFIX)
5548 * idx[1] always being the HWND.
5549 * idx[2] has three different values depending on what type of provider
5550 * the fragment root is. Fragment roots can be an override provider, a
5551 * nonclient provider, or a main provider.
5553 Provider_child.frag_root = NULL;
5554 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
5555 Provider_child.runtime_id[1] = 2;
5556 sa = (void *)0xdeadbeef;
5558 /* Provider_child has no fragment root for UiaAppendRuntimeId. */
5559 hr = UiaGetRuntimeId(node, &sa);
5560 /* Windows 7 returns S_OK. */
5561 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
5562 ok(!sa, "sa != NULL\n");
5563 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
5566 * UIA_RuntimeIdPropertyId won't return a failure code from
5567 * UiaGetPropertyValue.
5569 hr = UiaGetPropertyValue(node, UIA_RuntimeIdPropertyId, &v);
5570 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5571 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
5572 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
5573 VariantClear(&v);
5574 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
5577 * Provider_child returns a fragment root that doesn't expose an HWND. On
5578 * Win8+, fragment roots are navigated recursively until either a NULL
5579 * fragment root is returned, the same fragment root as the current one is
5580 * returned, or a fragment root with an HWND is returned.
5582 Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
5583 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
5584 Provider2.hwnd = NULL;
5585 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
5586 Provider.hwnd = NULL;
5587 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
5588 Provider_child.runtime_id[1] = 2;
5589 sa = (void *)0xdeadbeef;
5590 hr = UiaGetRuntimeId(node, &sa);
5591 /* Windows 7 returns S_OK. */
5592 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
5593 ok(!sa, "sa != NULL\n");
5594 ok_method_sequence(get_runtime_id3, "get_runtime_id3");
5596 /* Provider2 returns an HWND. */
5597 Provider.hwnd = NULL;
5598 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
5599 Provider2.hwnd = hwnd;
5600 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
5601 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
5602 Provider_child.runtime_id[1] = rt_id[3] = 2;
5603 sa = NULL;
5604 hr = UiaGetRuntimeId(node, &sa);
5605 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5606 /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */
5607 ok(!!sa || broken(!sa), "sa == NULL\n");
5608 SafeArrayDestroy(sa);
5610 ok_method_sequence(get_runtime_id4, "get_runtime_id4");
5612 /* Test RuntimeId values for different root fragment provider types. */
5613 Provider.frag_root = NULL;
5614 Provider.hwnd = hwnd;
5615 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
5616 Provider_child.runtime_id[1] = rt_id[3] = 2;
5617 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
5618 rt_id[1] = HandleToULong(hwnd);
5619 for (i = 0; i < ARRAY_SIZE(root_prov_opts); i++)
5621 LONG lbound;
5623 Provider.prov_opts = root_prov_opts[i];
5624 sa = NULL;
5625 hr = UiaGetRuntimeId(node, &sa);
5626 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5627 ok(!!sa, "sa == NULL\n");
5629 hr = SafeArrayGetLBound(sa, 1, &lbound);
5630 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
5632 lbound = lbound + 2;
5633 hr = SafeArrayGetElement(sa, &lbound, &tmp);
5634 ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
5635 if (i)
5636 ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n");
5638 rt_id[2] = tmp;
5639 check_runtime_id(rt_id, 4, sa);
5641 SafeArrayDestroy(sa);
5642 ok_method_sequence(get_runtime_id5, "get_runtime_id5");
5645 UiaNodeRelease(node);
5647 /* Test behavior on a node with an associated HWND. */
5648 Provider.prov_opts = ProviderOptions_ClientSideProvider;
5649 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
5650 Provider.hwnd = Provider2.hwnd = hwnd;
5651 prov_root = &Provider2.IRawElementProviderSimple_iface;
5652 node = (void *)0xdeadbeef;
5653 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
5654 /* Windows 7 sends this. */
5655 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5656 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5657 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5658 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
5659 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
5661 VariantInit(&v);
5662 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5663 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5664 if (SUCCEEDED(hr))
5666 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
5667 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
5668 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
5669 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
5670 VariantClear(&v);
5672 ok_method_sequence(node_from_prov6, "node_from_prov6");
5674 /* No methods called, RuntimeId is based on the node's HWND. */
5675 hr = UiaGetRuntimeId(node, &sa);
5676 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5677 ok(!!sa, "sa == NULL\n");
5678 ok(!sequence_cnt, "Unexpected sequence_cnt %d\n", sequence_cnt);
5680 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
5681 rt_id[1] = HandleToULong(hwnd);
5682 check_runtime_id(rt_id, 2, sa);
5683 SafeArrayDestroy(sa);
5684 UiaNodeRelease(node);
5686 DestroyWindow(hwnd);
5687 UnregisterClassA("UiaGetRuntimeId class", NULL);
5688 CoUninitialize();
5691 static const struct prov_method_sequence node_from_var_seq[] = {
5692 NODE_CREATE_SEQ(&Provider),
5693 { 0 },
5696 static void test_UiaHUiaNodeFromVariant(void)
5698 HUIANODE node, node2;
5699 ULONG node_ref;
5700 HRESULT hr;
5701 VARIANT v;
5703 hr = UiaHUiaNodeFromVariant(NULL, &node);
5704 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5706 hr = UiaHUiaNodeFromVariant(&v, NULL);
5707 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5709 node = (void *)0xdeadbeef;
5710 V_VT(&v) = VT_R8;
5711 hr = UiaHUiaNodeFromVariant(&v, &node);
5712 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5713 ok(!node, "node != NULL\n");
5715 node = NULL;
5716 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
5717 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5719 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5720 ok(!!node, "node == NULL\n");
5721 ok_method_sequence(node_from_var_seq, "node_from_var_seq");
5723 node2 = (void *)0xdeadbeef;
5724 V_VT(&v) = VT_UNKNOWN;
5725 V_UNKNOWN(&v) = (IUnknown *)node;
5726 hr = UiaHUiaNodeFromVariant(&v, &node2);
5727 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5728 ok(node == node2, "node != NULL\n");
5730 node_ref = IUnknown_AddRef((IUnknown *)node);
5731 ok(node_ref == 3, "Unexpected node_ref %ld\n", node_ref);
5732 VariantClear(&v);
5733 IUnknown_Release((IUnknown *)node);
5735 #ifdef _WIN64
5736 node2 = (void *)0xdeadbeef;
5737 V_VT(&v) = VT_I4;
5738 V_I4(&v) = 0xbeefdead;
5739 hr = UiaHUiaNodeFromVariant(&v, &node2);
5740 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5741 ok(!node2, "node2 != NULL\n");
5743 node2 = (void *)0xdeadbeef;
5744 V_VT(&v) = VT_I8;
5745 V_I8(&v) = (UINT64)node;
5746 hr = UiaHUiaNodeFromVariant(&v, &node2);
5747 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5748 ok(node2 == (void *)V_I8(&v), "node2 != V_I8\n");
5749 #else
5750 node2 = (void *)0xdeadbeef;
5751 V_VT(&v) = VT_I8;
5752 V_I8(&v) = 0xbeefdead;
5753 hr = UiaHUiaNodeFromVariant(&v, &node2);
5754 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5755 ok(!node2, "node2 != NULL\n");
5757 node2 = (void *)0xdeadbeef;
5758 V_VT(&v) = VT_I4;
5759 V_I4(&v) = (UINT32)node;
5760 hr = UiaHUiaNodeFromVariant(&v, &node2);
5761 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5762 ok(node2 == (void *)V_I4(&v), "node2 != V_I4\n");
5763 #endif
5765 UiaNodeRelease(node);
5768 static const struct prov_method_sequence node_from_hwnd1[] = {
5769 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5770 { 0 }
5773 static const struct prov_method_sequence node_from_hwnd2[] = {
5774 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5775 /* Win10v1507 and below call this. */
5776 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5777 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5778 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5779 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5780 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5781 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5782 /* Windows 10+ calls this. */
5783 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5784 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
5785 { 0 }
5788 static const struct prov_method_sequence node_from_hwnd3[] = {
5789 NODE_CREATE_SEQ2(&Provider),
5790 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5791 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
5792 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
5793 NODE_CREATE_SEQ2_OPTIONAL(&Provider),
5794 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5795 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5796 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
5797 { 0 }
5800 static const struct prov_method_sequence node_from_hwnd4[] = {
5801 { &Provider, PROV_GET_PROPERTY_VALUE },
5802 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5803 /* Win10v1507 and below call this. */
5804 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5805 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5806 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5807 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5808 /* Only called on Windows versions past Win10v1507. */
5809 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5810 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5811 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
5812 { 0 }
5815 static const struct prov_method_sequence node_from_hwnd5[] = {
5816 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
5817 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5818 /* Win10v1507 and below call this. */
5819 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5820 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5821 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5822 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5823 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5824 /* Only done in Windows 8+. */
5825 { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
5826 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5827 /* These two are only done on Windows 7. */
5828 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5829 { &Provider_child, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
5830 { 0 }
5833 static const struct prov_method_sequence node_from_hwnd6[] = {
5834 { &Provider, PROV_GET_PROPERTY_VALUE },
5835 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5836 /* Win10v1507 and below call this. */
5837 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5838 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5839 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5840 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5841 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5842 /* Next 4 are only done in Windows 8+. */
5843 { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
5844 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5845 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5846 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5847 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5848 /* Next two are only done on Win10v1809+. */
5849 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5850 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5851 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5852 /* Next two are only done on Win10v1809+. */
5853 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5854 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5855 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
5856 { 0 }
5859 static const struct prov_method_sequence node_from_hwnd7[] = {
5860 { &Provider, PROV_GET_PROPERTY_VALUE },
5861 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5862 /* Win10v1507 and below call this. */
5863 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5864 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5865 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5866 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5867 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5868 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5869 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5870 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5871 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5872 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5873 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5874 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
5875 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
5876 { 0 }
5879 static const struct prov_method_sequence node_from_hwnd8[] = {
5880 NODE_CREATE_SEQ2(&Provider),
5881 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5882 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
5883 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
5884 NODE_CREATE_SEQ2_OPTIONAL(&Provider),
5885 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5886 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5887 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5888 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
5889 { 0 }
5892 static const struct prov_method_sequence node_from_hwnd9[] = {
5893 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5894 /* Win10v1507 and below call this. */
5895 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5896 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5897 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5898 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5899 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5900 /* Only done in Windows 8+. */
5901 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
5902 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
5903 /* These three are only done on Windows 7. */
5904 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5905 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
5906 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
5907 { 0 }
5910 static const struct prov_method_sequence disconnect_prov1[] = {
5911 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5912 /* Win10v1507 and below call this. */
5913 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5914 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5915 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5916 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5917 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5918 { &Provider_child, FRAG_GET_RUNTIME_ID },
5919 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
5920 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5921 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5922 { 0 }
5925 static const struct prov_method_sequence disconnect_prov2[] = {
5926 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5927 /* Win10v1507 and below call this. */
5928 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5929 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5930 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5931 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5932 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5933 { &Provider, FRAG_GET_RUNTIME_ID },
5934 { &Provider, FRAG_GET_FRAGMENT_ROOT },
5935 { 0 }
5938 static const struct prov_method_sequence disconnect_prov3[] = {
5939 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5940 /* Win10v1507 and below call this. */
5941 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5942 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5943 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5944 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5945 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5946 { &Provider, FRAG_GET_RUNTIME_ID },
5947 { 0 }
5950 static const struct prov_method_sequence disconnect_prov4[] = {
5951 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5952 /* Win10v1507 and below call this. */
5953 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5954 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5955 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5956 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5957 { 0 }
5960 static void test_UiaNodeFromHandle_client_proc(void)
5962 APTTYPEQUALIFIER apt_qualifier;
5963 APTTYPE apt_type;
5964 WCHAR buf[2048];
5965 HUIANODE node;
5966 HRESULT hr;
5967 HWND hwnd;
5968 VARIANT v;
5970 hwnd = FindWindowA("UiaNodeFromHandle class", "Test window");
5972 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
5973 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
5975 hr = UiaNodeFromHandle(hwnd, &node);
5976 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5978 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5979 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5980 if (SUCCEEDED(hr))
5982 DWORD pid;
5984 memset(buf, 0, sizeof(buf));
5985 GetWindowThreadProcessId(hwnd, &pid);
5987 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
5988 check_node_provider_desc_prefix(buf, pid, hwnd);
5989 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
5991 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
5992 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
5993 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
5994 VariantClear(&v);
5997 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
5998 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5999 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
6000 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
6003 * On Windows 8 and above, if a node contains a nested provider, the
6004 * process will be in an implicit MTA until the node is released.
6006 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
6007 ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
6008 if (SUCCEEDED(hr))
6010 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
6011 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
6014 UiaNodeRelease(node);
6016 /* Node released, we're out of the implicit MTA. */
6017 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
6019 /* Windows 10v1709-1809 are stuck in an implicit MTA. */
6020 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
6021 if (SUCCEEDED(hr))
6023 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
6024 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
6028 static DWORD WINAPI uia_node_from_handle_test_thread(LPVOID param)
6030 HUIANODE node, node2, node3;
6031 HWND hwnd = (HWND)param;
6032 WCHAR buf[2048];
6033 HRESULT hr;
6034 VARIANT v;
6036 CoInitializeEx(NULL, COINIT_MULTITHREADED);
6038 /* Only sent twice on Windows 11. */
6039 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
6040 /* Only sent on Win7. */
6041 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6042 prov_root = &Provider.IRawElementProviderSimple_iface;
6043 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6044 Provider.hwnd = hwnd;
6045 Provider.runtime_id[0] = Provider.runtime_id[1] = 0;
6046 Provider.frag_root = NULL;
6047 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6048 Provider.ignore_hwnd_prop = TRUE;
6049 hr = UiaNodeFromHandle(hwnd, &node);
6050 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6051 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
6052 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6053 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6055 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6056 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6057 if (SUCCEEDED(hr))
6059 memset(buf, 0, sizeof(buf));
6061 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
6062 check_node_provider_desc_prefix(buf, GetCurrentProcessId(), hwnd);
6063 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
6065 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6066 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6067 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
6068 VariantClear(&v);
6071 Provider.ignore_hwnd_prop = FALSE;
6072 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
6074 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
6075 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6076 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
6079 * On Windows, nested providers are always called on a separate thread if
6080 * UseComThreading isn't set. Since we're doing COM marshaling, if we're
6081 * currently in an MTA, we just call the nested provider from the current
6082 * thread.
6084 todo_wine ok(Provider.last_call_tid != GetCurrentThreadId() &&
6085 Provider.last_call_tid != GetWindowThreadProcessId(hwnd, NULL), "Expected method call on separate thread\n");
6088 * Elements returned from nested providers have to be able to get a
6089 * RuntimeId, or else we'll get E_FAIL on Win8+.
6091 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
6092 Provider_child.expected_tid = Provider.expected_tid;
6093 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
6094 Provider_child.runtime_id[1] = 2;
6095 Provider_child.frag_root = NULL;
6096 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6097 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
6098 if (SUCCEEDED(hr))
6100 hr = UiaHUiaNodeFromVariant(&v, &node2);
6101 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6102 UiaNodeRelease(node2);
6105 ok_method_sequence(node_from_hwnd5, "node_from_hwnd5");
6107 /* RuntimeId check succeeds, we'll get a nested node. */
6108 Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
6109 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6110 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6111 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6113 hr = UiaHUiaNodeFromVariant(&v, &node2);
6114 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6115 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
6116 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6117 if (SUCCEEDED(hr))
6120 * Even though this is a nested node, without any additional
6121 * providers, it will not have the 'Nested' prefix.
6123 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
6124 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6125 VariantClear(&v);
6128 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
6129 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6130 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
6131 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
6132 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
6134 UiaNodeRelease(node2);
6137 * There is a delay between nested nodes being released and the
6138 * corresponding IRawElementProviderSimple release on newer Windows
6139 * versions.
6141 if (Provider_child.ref != 1)
6142 Sleep(50);
6143 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6146 * Returned nested elements with an HWND will have client-side providers
6147 * added to them.
6149 Provider_child.hwnd = hwnd;
6150 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6151 /* Only sent on Win7. */
6152 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6153 Provider_child.ignore_hwnd_prop = TRUE;
6154 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6155 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6156 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6157 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6158 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6160 hr = UiaHUiaNodeFromVariant(&v, &node2);
6161 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6162 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
6163 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6164 if (SUCCEEDED(hr))
6166 memset(buf, 0, sizeof(buf));
6168 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", TRUE, buf), "Failed to get nested provider description\n");
6169 check_node_provider_desc_prefix(buf, GetCurrentProcessId(), hwnd);
6170 check_node_provider_desc(buf, L"Main", L"Provider_child", TRUE);
6172 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6173 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6174 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, FALSE);
6175 VariantClear(&v);
6178 Provider_child.ignore_hwnd_prop = FALSE;
6179 ok_method_sequence(node_from_hwnd7, "node_from_hwnd7");
6180 UiaNodeRelease(node2);
6182 if (Provider_child.ref != 1)
6183 Sleep(50);
6184 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6186 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6187 /* Win10v1809 can be slow to call Release on Provider. */
6188 if (Provider.ref != 1)
6189 Sleep(50);
6190 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6192 if (!pUiaDisconnectProvider)
6194 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
6195 goto exit;
6199 * UiaDisconnectProvider tests.
6201 /* Only sent twice on Windows 11. */
6202 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
6203 prov_root = &Provider.IRawElementProviderSimple_iface;
6204 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6205 Provider.hwnd = hwnd;
6206 Provider.runtime_id[0] = Provider.runtime_id[1] = 0;
6207 Provider.frag_root = NULL;
6208 Provider.ignore_hwnd_prop = TRUE;
6209 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6210 hr = UiaNodeFromHandle(hwnd, &node);
6211 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6212 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
6213 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6215 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6216 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6217 if (SUCCEEDED(hr))
6219 memset(buf, 0, sizeof(buf));
6221 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
6222 check_node_provider_desc_prefix(buf, GetCurrentProcessId(), hwnd);
6223 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
6225 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6226 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6227 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
6228 VariantClear(&v);
6231 Provider.ignore_hwnd_prop = FALSE;
6232 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
6234 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
6235 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6236 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
6238 /* Nodes returned from a nested node will be tracked and disconnectable. */
6239 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
6240 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
6241 Provider_child.runtime_id[1] = 2;
6242 Provider_child.hwnd = NULL;
6243 Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
6244 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6245 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6246 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6248 hr = UiaHUiaNodeFromVariant(&v, &node2);
6249 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6250 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
6251 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6252 if (SUCCEEDED(hr))
6254 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
6255 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6256 VariantClear(&v);
6259 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
6260 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6261 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
6262 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
6263 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
6265 /* Get a new node for the same provider. */
6266 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6267 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6268 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
6270 hr = UiaHUiaNodeFromVariant(&v, &node3);
6271 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6272 hr = UiaGetPropertyValue(node3, UIA_ProviderDescriptionPropertyId, &v);
6273 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6274 if (SUCCEEDED(hr))
6276 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
6277 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6278 VariantClear(&v);
6281 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
6282 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6283 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
6284 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
6285 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
6288 * Both node2 and node3 represent Provider_child, one call to
6289 * UiaDisconnectProvider disconnects both.
6291 hr = pUiaDisconnectProvider(&Provider_child.IRawElementProviderSimple_iface);
6292 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6293 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6295 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
6296 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
6298 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
6299 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
6300 ok_method_sequence(disconnect_prov1, "disconnect_prov1");
6302 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
6303 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
6306 * Returns same failure code as UiaGetRuntimeId when we fail to get a
6307 * fragment root for AppendRuntimeId.
6309 Provider.hwnd = NULL;
6310 Provider.runtime_id[0] = UiaAppendRuntimeId;
6311 Provider.runtime_id[1] = 2;
6312 Provider.frag_root = NULL;
6313 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
6314 ok(hr == E_FAIL, "Unexpected hr %#lx\n", hr);
6315 ok_method_sequence(disconnect_prov2, "disconnect_prov2");
6318 * Comparisons for disconnection are only based on RuntimeId comparisons,
6319 * not interface pointer values. If an interface returns a NULL RuntimeId,
6320 * no disconnection will occur.
6322 Provider.runtime_id[0] = Provider.runtime_id[1] = 0;
6323 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
6324 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
6325 ok_method_sequence(disconnect_prov3, "disconnect_prov3");
6327 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
6328 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6329 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
6331 /* Finally, disconnect node. */
6332 Provider.hwnd = hwnd;
6333 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
6334 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6336 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
6337 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
6338 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6339 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
6341 exit:
6342 CoUninitialize();
6344 return 0;
6347 static void test_UiaNodeFromHandle(const char *name)
6349 APTTYPEQUALIFIER apt_qualifier;
6350 PROCESS_INFORMATION proc;
6351 char cmdline[MAX_PATH];
6352 STARTUPINFOA startup;
6353 HUIANODE node, node2;
6354 APTTYPE apt_type;
6355 DWORD exit_code;
6356 WNDCLASSA cls;
6357 HANDLE thread;
6358 HRESULT hr;
6359 HWND hwnd;
6360 VARIANT v;
6362 cls.style = 0;
6363 cls.lpfnWndProc = test_wnd_proc;
6364 cls.cbClsExtra = 0;
6365 cls.cbWndExtra = 0;
6366 cls.hInstance = GetModuleHandleA(NULL);
6367 cls.hIcon = 0;
6368 cls.hCursor = NULL;
6369 cls.hbrBackground = NULL;
6370 cls.lpszMenuName = NULL;
6371 cls.lpszClassName = "UiaNodeFromHandle class";
6372 RegisterClassA(&cls);
6374 hwnd = CreateWindowA("UiaNodeFromHandle class", "Test window", WS_OVERLAPPEDWINDOW,
6375 0, 0, 100, 100, NULL, NULL, NULL, NULL);
6377 hr = UiaNodeFromHandle(hwnd, NULL);
6378 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6380 hr = UiaNodeFromHandle(NULL, &node);
6381 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
6383 /* COM uninitialized, no provider returned by UiaReturnRawElementProvider. */
6384 prov_root = NULL;
6385 node = (void *)0xdeadbeef;
6386 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6387 /* Only sent twice on Win7. */
6388 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
6389 hr = UiaNodeFromHandle(hwnd, &node);
6390 /* Windows 10 and below return E_FAIL, Windows 11 returns S_OK. */
6391 todo_wine ok(hr == S_OK || broken(hr == E_FAIL), "Unexpected hr %#lx.\n", hr);
6392 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6393 todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
6394 if (SUCCEEDED(hr))
6395 UiaNodeRelease(node);
6398 * COM initialized, no provider returned by UiaReturnRawElementProvider.
6399 * In this case, we get a default MSAA proxy.
6401 CoInitializeEx(NULL, COINIT_MULTITHREADED);
6402 prov_root = NULL;
6403 node = (void *)0xdeadbeef;
6404 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6405 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
6406 hr = UiaNodeFromHandle(hwnd, &node);
6407 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6408 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6409 todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
6411 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6412 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6413 if (SUCCEEDED(hr))
6415 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6416 check_node_provider_desc(V_BSTR(&v), L"Annotation", NULL, FALSE);
6417 check_node_provider_desc(V_BSTR(&v), L"Main", NULL, FALSE);
6418 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6419 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
6420 VariantClear(&v);
6423 todo_wine ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6426 * COM initialized, but provider passed into UiaReturnRawElementProvider
6427 * returns a failure code on get_ProviderOptions. Same behavior as before.
6429 Provider.prov_opts = 0;
6430 Provider.hwnd = hwnd;
6431 prov_root = &Provider.IRawElementProviderSimple_iface;
6432 node = (void *)0xdeadbeef;
6433 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6434 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
6435 hr = UiaNodeFromHandle(hwnd, &node);
6436 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6437 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6438 todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
6440 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6441 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6442 if (SUCCEEDED(hr))
6444 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6445 check_node_provider_desc(V_BSTR(&v), L"Annotation", NULL, FALSE);
6446 check_node_provider_desc(V_BSTR(&v), L"Main", NULL, FALSE);
6447 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6448 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
6449 VariantClear(&v);
6451 ok_method_sequence(node_from_hwnd1, "node_from_hwnd1");
6453 todo_wine ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6456 * COM initialized, but provider passed into UiaReturnRawElementProvider
6457 * on Win8+ will have its RuntimeId queried for UiaDisconnectProvider.
6458 * It will fail due to the lack of a valid fragment root, and we'll fall
6459 * back to an MSAA proxy. On Win7, RuntimeId isn't queried because the
6460 * disconnection functions weren't implemented yet.
6462 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6463 Provider.hwnd = NULL;
6464 prov_root = &Provider.IRawElementProviderSimple_iface;
6465 node = (void *)0xdeadbeef;
6466 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6467 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
6468 Provider.frag_root = NULL;
6469 Provider.runtime_id[0] = UiaAppendRuntimeId;
6470 Provider.runtime_id[1] = 1;
6471 hr = UiaNodeFromHandle(hwnd, &node);
6472 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6473 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
6474 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6475 todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
6477 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6478 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6479 if (SUCCEEDED(hr))
6481 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6483 if (get_provider_desc(V_BSTR(&v), L"Annotation:", NULL))
6485 check_node_provider_desc(V_BSTR(&v), L"Annotation", NULL, FALSE);
6486 check_node_provider_desc(V_BSTR(&v), L"Main", NULL, FALSE);
6488 else
6489 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
6491 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6492 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
6493 VariantClear(&v);
6495 ok_method_sequence(node_from_hwnd9, "node_from_hwnd9");
6496 todo_wine ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6498 * Bug on Windows 8 through Win10v1709 - if we have a RuntimeId failure,
6499 * refcount doesn't get decremented.
6501 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
6502 if (Provider.ref == 2)
6503 IRawElementProviderSimple_Release(&Provider.IRawElementProviderSimple_iface);
6505 CoUninitialize();
6508 * COM uninitialized, return a Provider from UiaReturnRawElementProvider
6509 * with ProviderOptions_ServerSideProvider.
6511 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6512 Provider.hwnd = hwnd;
6513 prov_root = &Provider.IRawElementProviderSimple_iface;
6514 node = (void *)0xdeadbeef;
6515 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6516 /* Only sent on Win7. */
6517 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6518 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6519 hr = UiaNodeFromHandle(hwnd, &node);
6520 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6521 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6522 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6523 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6525 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6526 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6527 if (SUCCEEDED(hr))
6529 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6530 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
6531 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6532 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
6533 VariantClear(&v);
6536 ok_method_sequence(node_from_hwnd2, "node_from_hwnd2");
6538 /* For same-thread HWND nodes, no disconnection will occur. */
6539 if (pUiaDisconnectProvider)
6541 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
6542 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6544 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
6548 * This is relevant too: Since we don't get a 'nested' node, all calls
6549 * will occur on the current thread.
6551 Provider.expected_tid = GetCurrentThreadId();
6552 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
6553 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6554 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
6556 /* UIAutomationType_Element properties will return a normal node. */
6557 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
6558 Provider_child.hwnd = NULL;
6559 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6560 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6562 hr = UiaHUiaNodeFromVariant(&v, &node2);
6563 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6564 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
6565 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6566 if (SUCCEEDED(hr))
6568 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
6569 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6570 VariantClear(&v);
6573 Provider_child.expected_tid = GetCurrentThreadId();
6574 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
6575 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6576 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
6577 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
6578 ok_method_sequence(node_from_hwnd4, "node_from_hwnd4");
6580 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
6582 Provider.expected_tid = Provider_child.expected_tid = 0;
6583 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6586 * On Windows 8 and above, after the first successful call to
6587 * UiaReturnRawElementProvider the process ends up in an implicit MTA
6588 * until the process exits.
6590 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
6591 /* Wine's provider thread doesn't always terminate immediately. */
6592 if (hr == S_OK && !strcmp(winetest_platform, "wine"))
6594 Sleep(10);
6595 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
6597 todo_wine ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
6598 if (SUCCEEDED(hr))
6600 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
6601 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
6604 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
6605 thread = CreateThread(NULL, 0, uia_node_from_handle_test_thread, (void *)hwnd, 0, NULL);
6606 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
6608 MSG msg;
6609 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
6611 TranslateMessage(&msg);
6612 DispatchMessageW(&msg);
6615 CloseHandle(thread);
6617 /* Test behavior from separate process. */
6618 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6619 Provider.hwnd = hwnd;
6620 Provider.ignore_hwnd_prop = TRUE;
6621 prov_root = &Provider.IRawElementProviderSimple_iface;
6622 sprintf(cmdline, "\"%s\" uiautomation UiaNodeFromHandle_client_proc", name);
6623 memset(&startup, 0, sizeof(startup));
6624 startup.cb = sizeof(startup);
6625 /* Only called twice on Windows 11. */
6626 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
6627 /* Only sent on Win7. */
6628 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6629 CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
6630 while (MsgWaitForMultipleObjects(1, &proc.hProcess, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
6632 MSG msg;
6633 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
6635 TranslateMessage(&msg);
6636 DispatchMessageW(&msg);
6640 GetExitCodeProcess(proc.hProcess, &exit_code);
6641 if (exit_code > 255)
6642 ok(0, "unhandled exception %08x in child process %04x\n", (UINT)exit_code, (UINT)GetProcessId(proc.hProcess));
6643 else if (exit_code)
6644 ok(0, "%u failures in child process\n", (UINT)exit_code);
6646 CloseHandle(proc.hProcess);
6647 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6648 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6649 Provider.ignore_hwnd_prop = FALSE;
6650 ok_method_sequence(node_from_hwnd8, "node_from_hwnd8");
6652 CoUninitialize();
6654 DestroyWindow(hwnd);
6655 UnregisterClassA("UiaNodeFromHandle class", NULL);
6656 prov_root = NULL;
6659 static const struct prov_method_sequence reg_prov_cb1[] = {
6660 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6661 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
6662 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6663 { 0 }
6666 static const struct prov_method_sequence reg_prov_cb2[] = {
6667 /* These two are only done on Win10v1809+. */
6668 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6669 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6670 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6671 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
6672 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6673 { 0 }
6676 static const struct prov_method_sequence reg_prov_cb3[] = {
6677 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
6678 /* These two are only done on Win10v1809+. */
6679 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6680 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6681 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6682 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6683 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6684 /* These three only done on Win10+. */
6685 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6686 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6687 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6688 { &Provider_proxy, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6689 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6690 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6691 { 0 }
6694 static const struct prov_method_sequence reg_prov_cb4[] = {
6695 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
6696 /* These two are only done on Win10v1809+. */
6697 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6698 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6699 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
6700 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6701 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6702 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6703 /* These four only done on Win10+. */
6704 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6705 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6706 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6707 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6708 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6709 { &Provider_proxy, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6710 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6711 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6712 { 0 }
6715 static const struct prov_method_sequence reg_prov_cb5[] = {
6716 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
6717 { 0 }
6720 static const struct prov_method_sequence reg_prov_cb6[] = {
6721 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
6722 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6723 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6724 { 0 }
6727 static const struct prov_method_sequence reg_prov_cb7[] = {
6728 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
6729 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6730 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6731 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6732 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6733 { 0 }
6736 static const struct prov_method_sequence reg_prov_cb8[] = {
6737 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
6738 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6739 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6740 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6741 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6742 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6743 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6744 { 0 }
6747 static const struct prov_method_sequence reg_prov_cb9[] = {
6748 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
6749 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6750 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6751 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6752 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6753 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6754 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
6755 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
6756 { 0 }
6759 static const struct prov_method_sequence reg_prov_cb10[] = {
6760 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
6761 /* These two are only done on Win10v1809+. */
6762 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6763 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6764 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
6765 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6766 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6767 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6768 /* These four only done on Win10+. */
6769 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6770 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6771 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6772 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6773 { 0 }
6776 static const struct prov_method_sequence reg_prov_cb11[] = {
6777 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6778 /* Win10v1507 and below call this. */
6779 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6780 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6781 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6782 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6783 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6784 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
6785 /* These two are only done on Win10v1809+. */
6786 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6787 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6788 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6789 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6790 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6791 /* These three only done on Win10+. */
6792 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6793 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6794 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6795 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6796 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6797 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6798 { 0 }
6801 static const struct prov_method_sequence reg_prov_cb12[] = {
6802 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6803 /* Win10v1507 and below call this. */
6804 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6805 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6806 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6807 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6808 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6809 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
6810 /* Win10v1507 and below call this. */
6811 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6812 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
6813 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
6814 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
6815 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
6816 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
6817 /* These two are only done on Win10v1809+. */
6818 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6819 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6820 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6821 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6822 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6823 /* These three only done on Win10+. */
6824 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6825 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6826 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6827 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6828 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6829 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6830 { 0 }
6833 static const struct prov_method_sequence reg_prov_cb13[] = {
6834 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6835 /* Win10v1507 and below call this. */
6836 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6837 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6838 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6839 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6840 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6841 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
6842 /* Win10v1507 and below call this. */
6843 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6844 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
6845 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
6846 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
6847 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
6848 /* Provider override only retrieved successfully on Win10v1809+ */
6849 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6850 { &Provider_override, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6851 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6852 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6853 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6854 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1507 and below. */
6855 /* These two are only done on Win10v1809+. */
6856 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6857 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6858 /* Only done on Win10v1809+. */
6859 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6860 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6861 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6862 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6863 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
6864 /* These three only done on Win10+. */
6865 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6866 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6867 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6868 /* Only done on Win10v1809+. */
6869 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
6870 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6871 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6872 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
6873 { 0 }
6876 static IRawElementProviderSimple *base_hwnd_prov, *proxy_prov, *parent_proxy_prov, *nc_prov;
6877 static SAFEARRAY WINAPI *test_uia_provider_callback(HWND hwnd, enum ProviderType prov_type)
6879 IRawElementProviderSimple *elprov = NULL;
6881 switch (prov_type)
6883 case ProviderType_BaseHwnd:
6884 CHECK_EXPECT(prov_callback_base_hwnd);
6885 elprov = base_hwnd_prov;
6886 break;
6888 case ProviderType_Proxy:
6889 if (Provider_proxy.hwnd == hwnd)
6891 CHECK_EXPECT(prov_callback_proxy);
6892 elprov = proxy_prov;
6894 else if (hwnd == GetParent(Provider_proxy.hwnd))
6896 CHECK_EXPECT(prov_callback_parent_proxy);
6897 elprov = parent_proxy_prov;
6899 break;
6901 case ProviderType_NonClientArea:
6902 CHECK_EXPECT(prov_callback_nonclient);
6903 elprov = nc_prov;
6904 break;
6906 default:
6907 break;
6910 if (elprov)
6912 SAFEARRAY *sa;
6913 LONG idx = 0;
6915 sa = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
6916 if (sa)
6917 SafeArrayPutElement(sa, &idx, (void *)elprov);
6919 return sa;
6922 return NULL;
6925 static void test_UiaRegisterProviderCallback(void)
6927 HWND hwnd, hwnd2;
6928 WNDCLASSA cls;
6929 HUIANODE node;
6930 HRESULT hr;
6931 VARIANT v;
6933 cls.style = 0;
6934 cls.lpfnWndProc = test_wnd_proc;
6935 cls.cbClsExtra = 0;
6936 cls.cbWndExtra = 0;
6937 cls.hInstance = GetModuleHandleA(NULL);
6938 cls.hIcon = 0;
6939 cls.hCursor = NULL;
6940 cls.hbrBackground = NULL;
6941 cls.lpszMenuName = NULL;
6942 cls.lpszClassName = "UiaRegisterProviderCallback class";
6944 RegisterClassA(&cls);
6946 cls.lpfnWndProc = child_test_wnd_proc;
6947 cls.lpszClassName = "UiaRegisterProviderCallback child class";
6948 RegisterClassA(&cls);
6950 hwnd = CreateWindowA("UiaRegisterProviderCallback class", "Test window", WS_OVERLAPPEDWINDOW,
6951 0, 0, 100, 100, NULL, NULL, NULL, NULL);
6953 hwnd2 = CreateWindowA("UiaRegisterProviderCallback child class", "Test child window", WS_CHILD,
6954 0, 0, 100, 100, hwnd, NULL, NULL, NULL);
6956 UiaRegisterProviderCallback(test_uia_provider_callback);
6958 /* No providers returned by UiaRootObjectId or the provider callback. */
6959 Provider_proxy.hwnd = hwnd2;
6960 child_win_prov_root = prov_root = NULL;
6961 node = (void *)0xdeadbeef;
6962 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6963 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
6964 SET_EXPECT(prov_callback_base_hwnd);
6965 SET_EXPECT(prov_callback_nonclient);
6966 SET_EXPECT(prov_callback_proxy);
6967 SET_EXPECT(prov_callback_parent_proxy);
6968 hr = UiaNodeFromHandle(hwnd2, &node);
6969 /* Windows 7 returns S_OK with a NULL HUIANODE. */
6970 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
6971 ok(!node, "node != NULL\n");
6972 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6973 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
6974 CHECK_CALLED(prov_callback_base_hwnd);
6975 CHECK_CALLED(prov_callback_nonclient);
6976 CHECK_CALLED(prov_callback_proxy);
6977 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
6979 /* Return only nonclient proxy provider. */
6980 base_hwnd_prov = proxy_prov = parent_proxy_prov = NULL;
6981 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
6982 child_win_prov_root = prov_root = NULL;
6983 node = (void *)0xdeadbeef;
6984 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6985 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
6986 SET_EXPECT(prov_callback_base_hwnd);
6987 SET_EXPECT(prov_callback_nonclient);
6988 SET_EXPECT(prov_callback_proxy);
6989 SET_EXPECT(prov_callback_parent_proxy);
6990 hr = UiaNodeFromHandle(hwnd2, &node);
6991 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6992 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
6993 ok(!!node, "node == NULL\n");
6994 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6995 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
6996 CHECK_CALLED(prov_callback_base_hwnd);
6997 CHECK_CALLED(prov_callback_nonclient);
6998 CHECK_CALLED(prov_callback_proxy);
6999 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7001 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7002 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7003 if (SUCCEEDED(hr))
7005 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7006 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
7007 VariantClear(&v);
7010 ok_method_sequence(reg_prov_cb1, "reg_prov_cb1");
7012 UiaNodeRelease(node);
7013 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
7015 /* Return only base_hwnd provider. */
7016 nc_prov = proxy_prov = parent_proxy_prov = NULL;
7017 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
7018 child_win_prov_root = prov_root = NULL;
7019 node = (void *)0xdeadbeef;
7020 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7021 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7022 SET_EXPECT(prov_callback_base_hwnd);
7023 SET_EXPECT(prov_callback_nonclient);
7024 SET_EXPECT(prov_callback_proxy);
7025 SET_EXPECT(prov_callback_parent_proxy);
7026 hr = UiaNodeFromHandle(hwnd2, &node);
7027 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7028 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
7029 ok(!!node, "node == NULL\n");
7030 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7031 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7032 CHECK_CALLED(prov_callback_base_hwnd);
7033 CHECK_CALLED(prov_callback_nonclient);
7034 CHECK_CALLED(prov_callback_proxy);
7035 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7037 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7038 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7039 if (SUCCEEDED(hr))
7041 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7042 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", TRUE);
7043 VariantClear(&v);
7046 ok_method_sequence(reg_prov_cb2, "reg_prov_cb2");
7048 UiaNodeRelease(node);
7049 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
7051 /* Return providers for all ProviderTypes. */
7052 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
7053 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
7054 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
7055 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
7056 Provider_proxy.hwnd = hwnd2;
7057 child_win_prov_root = prov_root = NULL;
7058 node = (void *)0xdeadbeef;
7059 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7060 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7061 SET_EXPECT(prov_callback_base_hwnd);
7062 SET_EXPECT(prov_callback_nonclient);
7063 SET_EXPECT(prov_callback_proxy);
7064 SET_EXPECT(prov_callback_parent_proxy);
7065 hr = UiaNodeFromHandle(hwnd2, &node);
7066 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7067 ok(!!node, "node == NULL\n");
7068 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
7069 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
7070 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
7071 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
7072 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7073 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7074 CHECK_CALLED(prov_callback_base_hwnd);
7075 CHECK_CALLED(prov_callback_nonclient);
7076 CHECK_CALLED(prov_callback_proxy);
7077 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7079 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7080 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7081 if (SUCCEEDED(hr))
7083 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7084 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
7085 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
7086 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
7087 VariantClear(&v);
7090 ok_method_sequence(reg_prov_cb3, "reg_prov_cb3");
7092 UiaNodeRelease(node);
7093 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
7094 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
7095 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
7097 /* Return an override provider from Provider_proxy2. */
7098 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
7099 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
7100 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
7101 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
7102 Provider_proxy2.override_hwnd = hwnd2;
7103 child_win_prov_root = prov_root = NULL;
7104 node = (void *)0xdeadbeef;
7105 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7106 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7107 SET_EXPECT(prov_callback_base_hwnd);
7108 SET_EXPECT(prov_callback_nonclient);
7109 SET_EXPECT(prov_callback_proxy);
7110 SET_EXPECT(prov_callback_parent_proxy);
7111 hr = UiaNodeFromHandle(hwnd2, &node);
7112 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7113 ok(!!node, "node == NULL\n");
7114 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
7115 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
7116 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
7117 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
7118 todo_wine ok(Provider_override.ref == 2, "Unexpected refcnt %ld\n", Provider_override.ref);
7119 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7120 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7121 CHECK_CALLED(prov_callback_base_hwnd);
7122 CHECK_CALLED(prov_callback_nonclient);
7123 CHECK_CALLED(prov_callback_proxy);
7124 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7126 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7127 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7128 if (SUCCEEDED(hr))
7130 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7131 check_node_provider_desc(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
7132 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", FALSE);
7133 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
7134 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
7135 VariantClear(&v);
7138 ok_method_sequence(reg_prov_cb4, "reg_prov_cb4");
7141 * Test the order that Providers are queried for properties. The order is:
7142 * Override provider.
7143 * Main provider.
7144 * Nonclient provider.
7145 * Hwnd provider.
7147 * UI Automation tries to get a property from each in this order until one
7148 * returns a value. If none do, the property isn't supported.
7150 if (Provider_override.ref == 2)
7152 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7153 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7154 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
7155 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7156 ok_method_sequence(reg_prov_cb5, "reg_prov_cb5");
7159 /* Property retrieved from Provider_proxy (Main) */
7160 Provider_override.ret_invalid_prop_type = TRUE;
7161 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7162 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7163 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
7164 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7165 ok_method_sequence(reg_prov_cb6, "reg_prov_cb6");
7167 /* Property retrieved from Provider_nc (Nonclient) */
7168 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
7169 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7170 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7171 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
7172 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7173 ok_method_sequence(reg_prov_cb7, "reg_prov_cb7");
7175 /* Property retrieved from Provider_hwnd (Hwnd) */
7176 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
7177 Provider_nc.ret_invalid_prop_type = TRUE;
7178 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7179 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7180 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
7181 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7182 ok_method_sequence(reg_prov_cb8, "reg_prov_cb8");
7184 /* Property retrieved from none of the providers. */
7185 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
7186 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = TRUE;
7187 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7188 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7189 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7190 ok_method_sequence(reg_prov_cb9, "reg_prov_cb9");
7192 UiaNodeRelease(node);
7193 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
7194 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
7195 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
7196 ok(Provider_override.ref == 1, "Unexpected refcnt %ld\n", Provider_override.ref);
7197 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = FALSE;
7198 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = FALSE;
7201 * Provider_hwnd has ProviderOptions_UseComThreading, and COM hasn't been
7202 * initialized. One provider failing will cause the entire node to fail
7203 * creation on Win10+.
7205 Provider_hwnd.prov_opts = ProviderOptions_ClientSideProvider | ProviderOptions_UseComThreading;
7206 node = (void *)0xdeadbeef;
7207 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7208 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7209 SET_EXPECT(prov_callback_base_hwnd);
7210 SET_EXPECT(prov_callback_nonclient);
7211 SET_EXPECT(prov_callback_proxy);
7212 SET_EXPECT(prov_callback_parent_proxy);
7213 hr = UiaNodeFromHandle(hwnd2, &node);
7214 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
7215 ok(!node || broken(!!node), "node != NULL\n");
7216 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7217 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7218 CHECK_CALLED(prov_callback_base_hwnd);
7219 CHECK_CALLED(prov_callback_nonclient);
7220 CHECK_CALLED(prov_callback_proxy);
7221 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7222 ok_method_sequence(reg_prov_cb10, "reg_prov_cb10");
7223 UiaNodeRelease(node);
7224 Provider_hwnd.prov_opts = ProviderOptions_ClientSideProvider;
7227 * Provider returned by UiaRootObjectId on hwnd2. No ProviderType_Proxy
7228 * callback for hwnd2.
7230 Provider.hwnd = hwnd2;
7231 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7232 child_win_prov_root = &Provider.IRawElementProviderSimple_iface;
7233 Provider_proxy2.override_hwnd = NULL;
7234 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7235 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7236 SET_EXPECT(prov_callback_base_hwnd);
7237 SET_EXPECT(prov_callback_nonclient);
7238 SET_EXPECT(prov_callback_parent_proxy);
7239 hr = UiaNodeFromHandle(hwnd2, &node);
7240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7241 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7242 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7243 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7244 CHECK_CALLED(prov_callback_base_hwnd);
7245 CHECK_CALLED(prov_callback_nonclient);
7246 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7248 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7249 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7250 if (SUCCEEDED(hr))
7252 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7253 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
7254 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
7255 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
7256 VariantClear(&v);
7258 ok_method_sequence(reg_prov_cb11, "reg_prov_cb11");
7260 UiaNodeRelease(node);
7263 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
7264 * doesn't give an HWND override provider, UIA will attempt to get a proxy
7265 * provider to check it for an HWND override provider.
7267 Provider.hwnd = hwnd2;
7268 Provider2.hwnd = hwnd;
7269 Provider.prov_opts = Provider2.prov_opts = ProviderOptions_ServerSideProvider;
7270 child_win_prov_root = &Provider.IRawElementProviderSimple_iface;
7271 prov_root = &Provider2.IRawElementProviderSimple_iface;
7272 Provider_proxy2.override_hwnd = NULL;
7273 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7274 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7275 SET_EXPECT(prov_callback_base_hwnd);
7276 SET_EXPECT(prov_callback_nonclient);
7277 SET_EXPECT(prov_callback_parent_proxy);
7278 hr = UiaNodeFromHandle(hwnd2, &node);
7279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7280 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7281 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7282 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7283 CHECK_CALLED(prov_callback_base_hwnd);
7284 CHECK_CALLED(prov_callback_nonclient);
7285 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
7287 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7288 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7289 if (SUCCEEDED(hr))
7291 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7292 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
7293 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
7294 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
7295 VariantClear(&v);
7297 ok_method_sequence(reg_prov_cb12, "reg_prov_cb12");
7299 UiaNodeRelease(node);
7302 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
7303 * returns an HWND override, no ProviderType_Proxy callback for hwnd.
7305 Provider.hwnd = hwnd2;
7306 Provider2.hwnd = hwnd;
7307 Provider2.override_hwnd = Provider_override.hwnd = hwnd2;
7308 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = TRUE;
7309 Provider.prov_opts = Provider2.prov_opts = ProviderOptions_ServerSideProvider;
7310 child_win_prov_root = &Provider.IRawElementProviderSimple_iface;
7311 prov_root = &Provider2.IRawElementProviderSimple_iface;
7312 Provider_proxy2.override_hwnd = NULL;
7313 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7314 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
7315 SET_EXPECT(prov_callback_base_hwnd);
7316 SET_EXPECT(prov_callback_nonclient);
7317 SET_EXPECT(prov_callback_parent_proxy);
7318 hr = UiaNodeFromHandle(hwnd2, &node);
7319 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7320 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7321 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7322 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
7323 CHECK_CALLED(prov_callback_base_hwnd);
7324 CHECK_CALLED(prov_callback_nonclient);
7326 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7327 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7328 if (SUCCEEDED(hr))
7330 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
7331 check_node_provider_desc(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
7332 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
7333 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
7334 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
7335 VariantClear(&v);
7337 ok_method_sequence(reg_prov_cb13, "reg_prov_cb13");
7339 UiaNodeRelease(node);
7341 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = FALSE;
7342 UiaRegisterProviderCallback(NULL);
7344 DestroyWindow(hwnd);
7345 UnregisterClassA("UiaRegisterProviderCallback class", NULL);
7346 UnregisterClassA("UiaRegisterProviderCallback child class", NULL);
7349 static void set_cache_request(struct UiaCacheRequest *req, struct UiaCondition *view_cond, int scope,
7350 PROPERTYID *prop_ids, int prop_ids_count, PATTERNID *pattern_ids, int pattern_ids_count, int elem_mode)
7352 req->pViewCondition = view_cond;
7353 req->Scope = scope;
7355 req->pProperties = prop_ids;
7356 req->cProperties = prop_ids_count;
7357 req->pPatterns = pattern_ids;
7358 req->cPatterns = pattern_ids_count;
7360 req->automationElementMode = elem_mode;
7363 static void set_property_condition(struct UiaPropertyCondition *cond, int prop_id, VARIANT *val, int flags)
7365 cond->ConditionType = ConditionType_Property;
7366 cond->PropertyId = prop_id;
7367 cond->Value = *val;
7368 cond->Flags = flags;
7371 static void set_and_or_condition(struct UiaAndOrCondition *cond, int cond_type,
7372 struct UiaCondition **conds, int cond_count)
7374 cond->ConditionType = cond_type;
7375 cond->ppConditions = conds;
7376 cond->cConditions = cond_count;
7379 static void set_not_condition(struct UiaNotCondition *cond, struct UiaCondition *not_cond)
7381 cond->ConditionType = ConditionType_Not;
7382 cond->pConditions = not_cond;
7385 #define MAX_NODE_PROVIDERS 4
7386 struct node_provider_desc {
7387 DWORD pid;
7388 HWND hwnd;
7390 const WCHAR *prov_type[MAX_NODE_PROVIDERS];
7391 const WCHAR *prov_name[MAX_NODE_PROVIDERS];
7392 BOOL parent_link[MAX_NODE_PROVIDERS];
7393 int prov_count;
7396 static void init_node_provider_desc(struct node_provider_desc *desc, DWORD pid, HWND hwnd)
7398 memset(desc, 0, sizeof(*desc));
7399 desc->pid = pid;
7400 desc->hwnd = hwnd;
7403 static void add_provider_desc(struct node_provider_desc *desc, const WCHAR *prov_type, const WCHAR *prov_name,
7404 BOOL parent_link)
7406 desc->prov_type[desc->prov_count] = prov_type;
7407 desc->prov_name[desc->prov_count] = prov_name;
7408 desc->parent_link[desc->prov_count] = parent_link;
7409 desc->prov_count++;
7412 #define test_node_provider_desc( desc, desc_str ) \
7413 test_node_provider_desc_( (desc), (desc_str), __FILE__, __LINE__)
7414 static void test_node_provider_desc_(struct node_provider_desc *desc, BSTR desc_str, const char *file, int line)
7416 int i;
7418 check_node_provider_desc_prefix_(desc_str, desc->pid, desc->hwnd, file, line);
7419 for (i = 0; i < desc->prov_count; i++)
7420 check_node_provider_desc_(desc_str, desc->prov_type[i], desc->prov_name[i], desc->parent_link[i], file, line);
7424 * Cache requests are returned as a two dimensional safearray, with the first
7425 * dimension being the element index, and the second index being the
7426 * node/property/pattern value index for the element. The first element value is
7427 * always an HUIANODE, followed by requested property values, and finally
7428 * requested pattern handles.
7430 #define test_cache_req_sa( sa, exp_lbound, exp_elems, exp_node_desc ) \
7431 test_cache_req_sa_( (sa), (exp_lbound), (exp_elems), (exp_node_desc), __FILE__, __LINE__)
7432 static void test_cache_req_sa_(SAFEARRAY *sa, LONG exp_lbound[2], LONG exp_elems[2],
7433 struct node_provider_desc *exp_node_desc, const char *file, int line)
7435 HUIANODE node;
7436 HRESULT hr;
7437 VARTYPE vt;
7438 VARIANT v;
7439 UINT dims;
7440 int i;
7442 hr = SafeArrayGetVartype(sa, &vt);
7443 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7444 ok_(file, line)(vt == VT_VARIANT, "Unexpected vt %d\n", vt);
7446 dims = SafeArrayGetDim(sa);
7447 ok_(file, line)(dims == 2, "Unexpected dims %d\n", dims);
7449 for (i = 0; i < 2; i++)
7451 LONG lbound, ubound, elems;
7453 lbound = ubound = elems = 0;
7454 hr = SafeArrayGetLBound(sa, 1 + i, &lbound);
7455 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
7456 ok_(file, line)(exp_lbound[i] == lbound, "Unexpected lbound[%d] %ld\n", i, lbound);
7458 hr = SafeArrayGetUBound(sa, 1 + i, &ubound);
7459 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
7461 elems = (ubound - lbound) + 1;
7462 ok_(file, line)(exp_elems[i] == elems, "Unexpected elems[%d] %ld\n", i, elems);
7465 for (i = 0; i < exp_elems[0]; i++)
7467 LONG idx[2] = { (exp_lbound[0] + i), exp_lbound[1] };
7469 hr = SafeArrayGetElement(sa, idx, &v);
7470 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7472 hr = UiaHUiaNodeFromVariant(&v, &node);
7473 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7474 VariantClear(&v);
7476 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7477 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7478 if (SUCCEEDED(hr))
7479 test_node_provider_desc_(&exp_node_desc[i], V_BSTR(&v), file, line);
7480 VariantClear(&v);
7482 UiaNodeRelease(node);
7486 static const struct prov_method_sequence cache_req_seq1[] = {
7487 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId. */
7488 { 0 }
7492 * Win10v1507 and below will attempt to do parent navigation if the
7493 * conditional check fails.
7495 static const struct prov_method_sequence cache_req_seq2[] = {
7496 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7497 { 0 }
7500 static const struct prov_method_sequence cache_req_seq3[] = {
7501 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
7502 NODE_CREATE_SEQ(&Provider_child),
7503 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
7504 NODE_CREATE_SEQ(&Provider_child2),
7505 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
7506 /* Navigates towards parent to check for clientside provider siblings. */
7507 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7508 NODE_CREATE_SEQ(&Provider),
7509 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId. */
7510 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId. */
7511 { 0 }
7514 static const struct prov_method_sequence cache_req_seq4[] = {
7515 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
7516 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId. */
7517 { 0 }
7520 /* Sequence for non-matching property condition. */
7521 static const struct prov_method_sequence cache_req_seq5[] = {
7522 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
7523 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* Dependent upon property condition. */
7524 /* Only done on Win10v1507 and below. */
7525 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7526 { 0 }
7529 static const struct prov_method_sequence cache_req_seq6[] = {
7530 { &Provider, FRAG_GET_RUNTIME_ID },
7531 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId. */
7532 /* Only done on Win10v1507 and below. */
7533 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7534 { 0 }
7537 static const struct UiaCondition UiaTrueCondition = { ConditionType_True };
7538 static const struct UiaCondition UiaFalseCondition = { ConditionType_False };
7539 static void test_UiaGetUpdatedCache(void)
7541 struct Provider_prop_override prop_override;
7542 struct node_provider_desc exp_node_desc[2];
7543 struct UiaPropertyCondition prop_cond;
7544 struct UiaAndOrCondition and_or_cond;
7545 LONG exp_lbound[2], exp_elems[2], i;
7546 struct UiaCacheRequest cache_req;
7547 struct UiaCondition *cond_arr[2];
7548 struct UiaNotCondition not_cond;
7549 SAFEARRAY *out_req;
7550 BSTR tree_struct;
7551 HUIANODE node;
7552 HRESULT hr;
7553 VARIANT v;
7555 CoInitializeEx(NULL, COINIT_MULTITHREADED);
7557 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
7558 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
7560 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7561 Provider.hwnd = NULL;
7562 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
7563 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7564 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7566 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7567 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7568 if (SUCCEEDED(hr))
7570 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
7571 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
7572 VariantClear(&v);
7575 ok_method_sequence(node_from_prov2, NULL);
7577 /* NULL arg tests. */
7578 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
7579 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, NULL);
7580 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7582 hr = UiaGetUpdatedCache(node, NULL, NormalizeState_None, NULL, &out_req, &tree_struct);
7583 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7585 hr = UiaGetUpdatedCache(NULL, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
7586 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7589 * Cache request with NULL view condition, doesn't matter with
7590 * NormalizeState_None as passed in HUIANODE isn't evaluated against any
7591 * condition.
7593 tree_struct = NULL; out_req = NULL;
7594 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
7595 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
7596 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
7597 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7598 ok(!!out_req, "out_req == NULL\n");
7599 ok(!!tree_struct, "tree_struct == NULL\n");
7601 exp_lbound[0] = exp_lbound[1] = 0;
7602 exp_elems[0] = exp_elems[1] = 1;
7603 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7604 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7605 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
7607 SafeArrayDestroy(out_req);
7608 SysFreeString(tree_struct);
7611 * NormalizeState_View, HUIANODE gets checked against the ConditionType_False
7612 * condition within the cache request structure, nothing is returned.
7614 tree_struct = NULL; out_req = NULL;
7615 set_cache_request(&cache_req, (struct UiaCondition *)&UiaFalseCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
7616 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7617 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7618 ok(!out_req, "out_req != NULL\n");
7620 /* Empty tree structure string. */
7621 ok(!!tree_struct, "tree_struct == NULL\n");
7622 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7623 SysFreeString(tree_struct);
7624 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
7627 * NormalizeState_View, HUIANODE gets checked against the ConditionType_True
7628 * condition within the cache request structure, returns this HUIANODE.
7630 tree_struct = NULL; out_req = NULL;
7631 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
7632 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7633 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7634 ok(!!out_req, "out_req == NULL\n");
7635 ok(!!tree_struct, "tree_struct == NULL\n");
7637 exp_lbound[0] = exp_lbound[1] = 0;
7638 exp_elems[0] = exp_elems[1] = 1;
7639 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7640 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7641 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
7643 SafeArrayDestroy(out_req);
7644 SysFreeString(tree_struct);
7647 * NormalizeState_Custom, HUIANODE gets checked against our passed in
7648 * ConditionType_False condition.
7650 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
7651 tree_struct = NULL; out_req = NULL;
7652 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaFalseCondition, &out_req, &tree_struct);
7653 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7654 ok(!out_req, "out_req != NULL\n");
7656 /* Empty tree structure string. */
7657 ok(!!tree_struct, "tree_struct == NULL\n");
7658 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7659 SysFreeString(tree_struct);
7661 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
7664 * NormalizeState_Custom, HUIANODE gets checked against the ConditionType_True
7665 * condition we pass in, returns this HUIANODE.
7667 tree_struct = NULL; out_req = NULL;
7668 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
7669 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaTrueCondition, &out_req, &tree_struct);
7670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7671 ok(!!out_req, "out_req == NULL\n");
7672 ok(!!tree_struct, "tree_struct == NULL\n");
7674 exp_lbound[0] = exp_lbound[1] = 0;
7675 exp_elems[0] = exp_elems[1] = 1;
7676 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7677 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7678 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
7680 SafeArrayDestroy(out_req);
7681 SysFreeString(tree_struct);
7684 * CacheRequest with TreeScope_Children.
7686 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
7687 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
7688 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
7689 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
7690 tree_struct = NULL; out_req = NULL;
7691 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Children, NULL, 0, NULL, 0, AutomationElementMode_Full);
7692 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
7693 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7694 todo_wine ok(!!out_req, "out_req == NULL\n");
7695 todo_wine ok(!!tree_struct, "tree_struct == NULL\n");
7696 todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7697 todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
7698 if (out_req)
7700 exp_elems[0] = 2;
7701 exp_elems[1] = 1;
7702 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7704 ok(!wcscmp(tree_struct, L"(P)P))"), "tree structure %s\n", debugstr_w(tree_struct));
7705 ok_method_sequence(cache_req_seq3, "cache_req_seq3");
7708 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7709 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
7710 SafeArrayDestroy(out_req);
7711 SysFreeString(tree_struct);
7714 * ConditionType_And tests.
7716 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
7717 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
7718 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
7719 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
7720 cond_arr[1] = (struct UiaCondition *)&UiaTrueCondition;
7721 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
7722 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
7723 AutomationElementMode_Full);
7724 tree_struct = NULL; out_req = NULL;
7726 /* Equivalent to: if (1 && 1) */
7727 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7728 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7729 ok(!!out_req, "out_req == NULL\n");
7730 ok(!!tree_struct, "tree_struct == NULL\n");
7732 exp_lbound[0] = exp_lbound[1] = 0;
7733 exp_elems[0] = exp_elems[1] = 1;
7734 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7735 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7736 ok_method_sequence(cache_req_seq1, NULL);
7738 SafeArrayDestroy(out_req);
7739 SysFreeString(tree_struct);
7741 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
7742 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
7743 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
7744 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
7745 AutomationElementMode_Full);
7746 tree_struct = NULL; out_req = NULL;
7748 /* Equivalent to: if (1 && 0) */
7749 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7750 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7751 ok_method_sequence(cache_req_seq2, NULL);
7752 ok(!out_req, "out_req != NULL\n");
7753 ok(!!tree_struct, "tree_struct == NULL\n");
7754 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7756 SysFreeString(tree_struct);
7759 * ConditionType_Or tests.
7761 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
7762 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
7763 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
7764 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
7765 AutomationElementMode_Full);
7766 tree_struct = NULL; out_req = NULL;
7768 /* Equivalent to: if (1 || 0) */
7769 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7770 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7771 ok(!!out_req, "out_req == NULL\n");
7772 ok(!!tree_struct, "tree_struct == NULL\n");
7774 exp_lbound[0] = exp_lbound[1] = 0;
7775 exp_elems[0] = exp_elems[1] = 1;
7776 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7777 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7778 ok_method_sequence(cache_req_seq1, NULL);
7780 SafeArrayDestroy(out_req);
7781 SysFreeString(tree_struct);
7783 cond_arr[0] = (struct UiaCondition *)&UiaFalseCondition;
7784 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
7785 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
7786 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
7787 AutomationElementMode_Full);
7788 tree_struct = NULL; out_req = NULL;
7790 /* Equivalent to: if (0 || 0) */
7791 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7792 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7793 ok_method_sequence(cache_req_seq2, NULL);
7794 ok(!out_req, "out_req != NULL\n");
7795 ok(!!tree_struct, "tree_struct == NULL\n");
7796 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7798 SysFreeString(tree_struct);
7801 * ConditionType_Not tests.
7803 set_not_condition(&not_cond, (struct UiaCondition *)&UiaFalseCondition);
7804 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
7805 AutomationElementMode_Full);
7806 tree_struct = NULL; out_req = NULL;
7808 /* Equivalent to: if (!0) */
7809 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7811 ok(!!out_req, "out_req == NULL\n");
7812 ok(!!tree_struct, "tree_struct == NULL\n");
7814 exp_lbound[0] = exp_lbound[1] = 0;
7815 exp_elems[0] = exp_elems[1] = 1;
7816 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7817 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7818 ok_method_sequence(cache_req_seq1, NULL);
7820 SafeArrayDestroy(out_req);
7821 SysFreeString(tree_struct);
7823 set_not_condition(&not_cond, (struct UiaCondition *)&UiaTrueCondition);
7824 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
7825 AutomationElementMode_Full);
7826 tree_struct = NULL; out_req = NULL;
7828 /* Equivalent to: if (!1) */
7829 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7830 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7831 ok(!out_req, "out_req != NULL\n");
7832 ok(!!tree_struct, "tree_struct == NULL\n");
7833 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7834 SysFreeString(tree_struct);
7835 ok_method_sequence(cache_req_seq2, NULL);
7838 * ConditionType_Property tests.
7840 Provider.ret_invalid_prop_type = FALSE;
7842 /* Test UIAutomationType_IntArray property conditions. */
7843 if (UiaLookupId(AutomationIdentifierType_Property, &OutlineColor_Property_GUID))
7845 V_VT(&v) = VT_I4 | VT_ARRAY;
7846 V_ARRAY(&v) = create_i4_safearray();
7847 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
7848 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
7849 AutomationElementMode_Full);
7850 tree_struct = NULL; out_req = NULL;
7852 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7853 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7854 ok(!!out_req, "out_req == NULL\n");
7855 ok(!!tree_struct, "tree_struct == NULL\n");
7857 exp_lbound[0] = exp_lbound[1] = 0;
7858 exp_elems[0] = exp_elems[1] = 1;
7859 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7860 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7861 ok_method_sequence(cache_req_seq4, NULL);
7863 SafeArrayDestroy(out_req);
7864 SysFreeString(tree_struct);
7865 VariantClear(&v);
7867 /* Same values, except we're short by one element. */
7868 V_VT(&v) = VT_I4 | VT_ARRAY;
7869 V_ARRAY(&v) = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(uia_i4_arr_prop_val) - 1);
7871 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val) - 1; i++)
7872 SafeArrayPutElement(V_ARRAY(&prop_cond.Value), &i, (void *)&uia_i4_arr_prop_val[i]);
7874 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
7875 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
7876 AutomationElementMode_Full);
7877 tree_struct = NULL; out_req = NULL;
7879 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7880 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7881 ok_method_sequence(cache_req_seq5, NULL);
7882 ok(!out_req, "out_req != NULL\n");
7883 ok(!!tree_struct, "tree_struct == NULL\n");
7884 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7886 SysFreeString(tree_struct);
7887 VariantClear(&v);
7889 else
7890 win_skip("UIA_OutlineColorPropertyId unavailable, skipping property condition tests for it.\n");
7892 /* UIA_RuntimeIdPropertyId comparison. */
7893 Provider.runtime_id[0] = 0xdeadbeef; Provider.runtime_id[1] = 0xfeedbeef;
7894 V_VT(&v) = VT_I4 | VT_ARRAY;
7895 V_ARRAY(&v) = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(Provider.runtime_id));
7896 for (i = 0; i < ARRAY_SIZE(Provider.runtime_id); i++)
7897 SafeArrayPutElement(V_ARRAY(&v), &i, (void *)&Provider.runtime_id[i]);
7899 set_property_condition(&prop_cond, UIA_RuntimeIdPropertyId, &v, PropertyConditionFlags_None);
7900 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
7901 AutomationElementMode_Full);
7902 tree_struct = NULL; out_req = NULL;
7904 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7905 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7906 ok(!!out_req, "out_req == NULL\n");
7907 ok(!!tree_struct, "tree_struct == NULL\n");
7909 exp_lbound[0] = exp_lbound[1] = 0;
7910 exp_elems[0] = exp_elems[1] = 1;
7911 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7912 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7913 ok_method_sequence(cache_req_seq6, NULL);
7915 SafeArrayDestroy(out_req);
7916 SysFreeString(tree_struct);
7917 VariantClear(&prop_cond.Value);
7919 /* UIAutomationType_Bool property condition tests. */
7920 prop_override.prop_id = UIA_IsControlElementPropertyId;
7921 V_VT(&prop_override.val) = VT_BOOL;
7922 V_BOOL(&prop_override.val) = VARIANT_FALSE;
7923 Provider.prop_override = &prop_override;
7924 Provider.prop_override_count = 1;
7926 V_VT(&v) = VT_BOOL;
7927 V_BOOL(&v) = VARIANT_FALSE;
7928 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
7929 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
7930 AutomationElementMode_Full);
7931 tree_struct = NULL; out_req = NULL;
7933 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7934 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7935 ok(!!out_req, "out_req == NULL\n");
7936 ok(!!tree_struct, "tree_struct == NULL\n");
7938 exp_lbound[0] = exp_lbound[1] = 0;
7939 exp_elems[0] = exp_elems[1] = 1;
7940 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
7941 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
7942 ok_method_sequence(cache_req_seq4, NULL);
7944 SafeArrayDestroy(out_req);
7945 SysFreeString(tree_struct);
7946 VariantClear(&v);
7949 * Provider now returns VARIANT_TRUE for UIA_IsControlElementPropertyId,
7950 * conditional check will fail.
7952 prop_override.prop_id = UIA_IsControlElementPropertyId;
7953 V_VT(&prop_override.val) = VT_BOOL;
7954 V_BOOL(&prop_override.val) = VARIANT_TRUE;
7955 Provider.prop_override = &prop_override;
7956 Provider.prop_override_count = 1;
7958 V_VT(&v) = VT_BOOL;
7959 V_BOOL(&v) = VARIANT_FALSE;
7960 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
7961 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
7962 AutomationElementMode_Full);
7963 tree_struct = NULL; out_req = NULL;
7965 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
7966 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7967 ok_method_sequence(cache_req_seq5, NULL);
7968 ok(!out_req, "out_req != NULL\n");
7969 ok(!!tree_struct, "tree_struct == NULL\n");
7970 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
7972 SysFreeString(tree_struct);
7973 VariantClear(&v);
7975 Provider.prop_override = NULL;
7976 Provider.prop_override_count = 0;
7978 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7979 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
7981 CoUninitialize();
7984 static const struct prov_method_sequence nav_seq1[] = {
7985 NODE_CREATE_SEQ2(&Provider),
7986 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7987 /* Only done on Win10v1809+ */
7988 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7989 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7990 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7991 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7992 /* Windows 10+ calls these. */
7993 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7994 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7995 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7996 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
7997 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
7998 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
7999 { 0 }
8002 static const struct prov_method_sequence nav_seq2[] = {
8003 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8004 NODE_CREATE_SEQ(&Provider_hwnd_child),
8005 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8006 { 0 }
8009 static const struct prov_method_sequence nav_seq3[] = {
8010 { &Provider_hwnd_child, FRAG_NAVIGATE}, /* NavigateDirection_NextSibling */
8011 NODE_CREATE_SEQ(&Provider_hwnd_child2),
8012 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8013 { 0 }
8016 static const struct prov_method_sequence nav_seq4[] = {
8017 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8018 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8019 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS },
8020 /* All Windows versions use the NativeWindowHandle provider type check here. */
8021 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
8022 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8023 NODE_CREATE_SEQ2(&Provider),
8024 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8025 /* Only done on Win10v1809+ */
8026 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8027 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8028 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8029 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8030 /* Windows 10+ calls these. */
8031 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8032 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8033 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8034 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8035 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS },
8036 /* Win10v1507 and below call this. */
8037 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8038 { &Provider_nc_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8039 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
8040 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8041 /* Only called on Windows versions past Win10v1507. */
8042 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8043 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8044 { 0 }
8047 static const struct prov_method_sequence nav_seq5[] = {
8048 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
8049 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8050 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS },
8051 { &Provider_nc, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8052 NODE_CREATE_SEQ2(&Provider),
8053 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8054 /* Only done on Win10v1809+ */
8055 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8056 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8057 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8058 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8059 /* Windows 10+ calls these. */
8060 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8061 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8062 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8063 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
8064 NODE_CREATE_SEQ(&Provider_hwnd_child2),
8065 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8066 { 0 }
8069 static const struct prov_method_sequence nav_seq6[] = {
8070 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8071 NODE_CREATE_SEQ(&Provider_nc_child2),
8072 { &Provider_nc_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8073 { 0 }
8076 static const struct prov_method_sequence nav_seq7[] = {
8077 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8078 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8079 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS },
8080 { &Provider_nc, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8081 NODE_CREATE_SEQ2(&Provider),
8082 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8083 /* Only done on Win10v1809+ */
8084 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8085 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8086 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8087 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8088 /* Windows 10+ calls these. */
8089 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8090 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8091 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8092 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8093 NODE_CREATE_SEQ(&Provider_child),
8094 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8095 { 0 }
8098 static const struct prov_method_sequence nav_seq8[] = {
8099 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8100 NODE_CREATE_SEQ(&Provider_child2),
8101 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8102 { 0 }
8105 static const struct prov_method_sequence nav_seq9[] = {
8106 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8107 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8108 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8109 /* Win10v1507 and below call this. */
8110 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8111 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8112 NODE_CREATE_SEQ2(&Provider),
8113 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8114 /* Only done on Win10v1809+ */
8115 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8116 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8117 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8118 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8119 /* Windows 10+ calls these. */
8120 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8121 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8122 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8123 /* Navigates to parent a second time. */
8124 { &Provider_child2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8125 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8126 /* Win10v1507 and below call this. */
8127 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8128 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
8129 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8130 /* Win10v1507 and below call this. */
8131 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8132 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
8133 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8134 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8135 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8136 /* Only done on Win10v1809+ */
8137 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8138 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8139 { &Provider_nc, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8140 { &Provider_hwnd, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8141 /* Windows 10+ calls these. */
8142 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8143 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8144 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8147 static const struct prov_method_sequence nav_seq10[] = {
8148 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
8149 NODE_CREATE_SEQ(&Provider_child2),
8150 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8151 { 0 }
8154 static const struct prov_method_sequence nav_seq11[] = {
8155 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8156 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS },
8157 /* All Windows versions use the NativeWindowHandle provider type check here. */
8158 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
8159 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8160 NODE_CREATE_SEQ2(&Provider),
8161 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8162 /* Only done on Win10v1809+ */
8163 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8164 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8165 /* Windows 10+ calls these. */
8166 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8167 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8168 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8169 { &Provider_hwnd_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8170 NODE_CREATE_SEQ(&Provider_hwnd_child2),
8171 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8172 { 0 }
8175 static const struct prov_method_sequence nav_seq12[] = {
8176 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
8177 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS },
8178 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8179 { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8180 NODE_CREATE_SEQ2(&Provider),
8181 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8182 /* Only done on Win10v1809+ */
8183 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8184 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8185 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8186 /* Windows 10+ calls these. */
8187 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8188 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8189 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8190 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
8191 NODE_CREATE_SEQ(&Provider_child),
8192 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8193 { 0 }
8196 static const struct prov_method_sequence nav_seq13[] = {
8197 NODE_CREATE_SEQ2(&Provider),
8198 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8199 /* Only done on Win10v1809+ */
8200 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8201 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8202 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8203 /* Windows 10+ calls these. */
8204 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8205 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8206 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8207 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8208 { &Provider_nc, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8209 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8210 { 0 }
8213 static const struct prov_method_sequence nav_seq14[] = {
8214 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8215 NODE_CREATE_SEQ(&Provider2),
8216 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8217 { 0 }
8220 static void set_provider_nav_ifaces(struct Provider *prov, struct Provider *parent, struct Provider *frag_root,
8221 struct Provider *prev_sibling, struct Provider *next_sibling, struct Provider *first_child,
8222 struct Provider *last_child)
8224 prov->parent = NULL;
8225 prov->frag_root = NULL;
8226 prov->prev_sibling = NULL;
8227 prov->next_sibling = NULL;
8228 prov->first_child = NULL;
8229 prov->last_child = NULL;
8231 if (parent)
8232 prov->parent = &parent->IRawElementProviderFragment_iface;
8233 if (frag_root)
8234 prov->frag_root = &frag_root->IRawElementProviderFragmentRoot_iface;
8235 if (prev_sibling)
8236 prov->prev_sibling = &prev_sibling->IRawElementProviderFragment_iface;
8237 if (next_sibling)
8238 prov->next_sibling = &next_sibling->IRawElementProviderFragment_iface;
8239 if (first_child)
8240 prov->first_child = &first_child->IRawElementProviderFragment_iface;
8241 if (last_child)
8242 prov->last_child = &last_child->IRawElementProviderFragment_iface;
8245 static void test_UiaNavigate(void)
8247 LONG exp_lbound[2], exp_elems[2], idx[2], i;
8248 struct node_provider_desc exp_node_desc[4];
8249 struct UiaCacheRequest cache_req;
8250 HUIANODE node, node2, node3;
8251 SAFEARRAY *out_req;
8252 BSTR tree_struct;
8253 WNDCLASSA cls;
8254 HRESULT hr;
8255 VARIANT v;
8256 HWND hwnd;
8258 CoInitializeEx(NULL, COINIT_MULTITHREADED);
8259 cls.style = 0;
8260 cls.lpfnWndProc = test_wnd_proc;
8261 cls.cbClsExtra = 0;
8262 cls.cbWndExtra = 0;
8263 cls.hInstance = GetModuleHandleA(NULL);
8264 cls.hIcon = 0;
8265 cls.hCursor = NULL;
8266 cls.hbrBackground = NULL;
8267 cls.lpszMenuName = NULL;
8268 cls.lpszClassName = "UiaNavigate class";
8270 RegisterClassA(&cls);
8272 hwnd = CreateWindowA("UiaNavigate class", "Test window", WS_OVERLAPPEDWINDOW,
8273 0, 0, 100, 100, NULL, NULL, NULL, NULL);
8275 UiaRegisterProviderCallback(test_uia_provider_callback);
8276 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
8277 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
8279 set_provider_nav_ifaces(&Provider_nc, NULL, NULL, NULL, NULL, &Provider_nc_child, &Provider_nc_child2);
8280 set_provider_nav_ifaces(&Provider_nc_child, &Provider_nc, &Provider_nc, NULL,
8281 &Provider_nc_child2, NULL, NULL);
8282 set_provider_nav_ifaces(&Provider_nc_child2, &Provider_nc, &Provider_nc, &Provider_nc_child,
8283 NULL, NULL, NULL);
8285 set_provider_nav_ifaces(&Provider_hwnd, NULL, NULL, NULL, NULL, &Provider_hwnd_child, &Provider_hwnd_child2);
8286 set_provider_nav_ifaces(&Provider_hwnd_child, &Provider_hwnd, &Provider_hwnd, NULL,
8287 &Provider_hwnd_child2, NULL, NULL);
8288 set_provider_nav_ifaces(&Provider_hwnd_child2, &Provider_hwnd, &Provider_hwnd, &Provider_hwnd_child,
8289 NULL, NULL, NULL);
8292 * Show navigation behavior for multi-provider nodes. Navigation order is:
8293 * HWND provider children.
8294 * Non-Client provider children.
8295 * Main provider children.
8296 * Override provider children.
8298 Provider.prov_opts = ProviderOptions_ServerSideProvider;
8299 Provider.hwnd = Provider_hwnd.hwnd = Provider_nc.hwnd = hwnd;
8300 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = TRUE;
8301 prov_root = &Provider.IRawElementProviderSimple_iface;
8302 node = (void *)0xdeadbeef;
8303 /* Only sent on Win7. */
8304 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8305 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8306 SET_EXPECT(prov_callback_base_hwnd);
8307 SET_EXPECT(prov_callback_nonclient);
8308 hr = UiaNodeFromHandle(hwnd, &node);
8309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8310 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8311 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8312 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
8313 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8314 CHECK_CALLED(prov_callback_base_hwnd);
8315 CHECK_CALLED(prov_callback_nonclient);
8316 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8318 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8319 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8320 if (SUCCEEDED(hr))
8322 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
8323 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
8324 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
8325 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8326 VariantClear(&v);
8329 ok_method_sequence(nav_seq1, "nav_seq1");
8331 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
8332 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
8333 idx[0] = idx[1] = 0;
8335 /* Navigate to Provider_hwnd_child. */
8336 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child", TRUE);
8337 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8338 tree_struct = NULL; out_req = NULL;
8339 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8340 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8341 ok(!!out_req, "out_req == NULL\n");
8342 ok(!!tree_struct, "tree_struct == NULL\n");
8343 ok(Provider_hwnd_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
8345 node2 = node3 = NULL;
8346 hr = SafeArrayGetElement(out_req, idx, &v);
8347 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8349 hr = UiaHUiaNodeFromVariant(&v, &node2);
8350 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8351 IUnknown_AddRef((IUnknown *)node2);
8353 exp_lbound[0] = exp_lbound[1] = 0;
8354 exp_elems[0] = exp_elems[1] = 1;
8355 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8357 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8358 ok_method_sequence(nav_seq2, "nav_seq2");
8360 SafeArrayDestroy(out_req);
8361 SysFreeString(tree_struct);
8363 /* Navigate to Provider_hwnd_child2. */
8364 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8365 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
8366 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8367 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8368 ok(!!out_req, "out_req == NULL\n");
8369 ok(!!tree_struct, "tree_struct == NULL\n");
8370 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8372 hr = SafeArrayGetElement(out_req, idx, &v);
8373 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8375 hr = UiaHUiaNodeFromVariant(&v, &node3);
8376 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8377 IUnknown_AddRef((IUnknown *)node3);
8379 exp_lbound[0] = exp_lbound[1] = 0;
8380 exp_elems[0] = exp_elems[1] = 1;
8381 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8383 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8384 ok_method_sequence(nav_seq3, "nav_seq3");
8386 SafeArrayDestroy(out_req);
8387 SysFreeString(tree_struct);
8389 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8390 ok(Provider_hwnd_child.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
8391 node2 = node3;
8393 /* Navigate to Provider_nc_child. */
8394 SET_EXPECT(prov_callback_nonclient);
8395 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8396 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8397 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child", TRUE);
8398 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8399 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8400 ok(!!out_req, "out_req == NULL\n");
8401 ok(!!tree_struct, "tree_struct == NULL\n");
8402 ok(Provider_nc_child.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
8403 CHECK_CALLED(prov_callback_nonclient);
8404 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8406 hr = SafeArrayGetElement(out_req, idx, &v);
8407 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8409 hr = UiaHUiaNodeFromVariant(&v, &node3);
8410 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8411 IUnknown_AddRef((IUnknown *)node3);
8413 exp_lbound[0] = exp_lbound[1] = 0;
8414 exp_elems[0] = exp_elems[1] = 1;
8415 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8417 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8418 ok_method_sequence(nav_seq4, "nav_seq4");
8420 SafeArrayDestroy(out_req);
8421 SysFreeString(tree_struct);
8423 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8424 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8425 node2 = node3;
8427 /* Navigate back to Provider_hwnd_child2. */
8428 SET_EXPECT(prov_callback_base_hwnd);
8429 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8430 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8431 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
8432 hr = UiaNavigate(node2, NavigateDirection_PreviousSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8433 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8434 ok(!!out_req, "out_req == NULL\n");
8435 ok(!!tree_struct, "tree_struct == NULL\n");
8436 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8437 CHECK_CALLED(prov_callback_base_hwnd);
8438 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8440 hr = SafeArrayGetElement(out_req, idx, &v);
8441 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8443 hr = UiaHUiaNodeFromVariant(&v, &node3);
8444 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8445 IUnknown_AddRef((IUnknown *)node3);
8447 exp_lbound[0] = exp_lbound[1] = 0;
8448 exp_elems[0] = exp_elems[1] = 1;
8449 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8451 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8452 ok_method_sequence(nav_seq5, "nav_seq5");
8454 SafeArrayDestroy(out_req);
8455 SysFreeString(tree_struct);
8457 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
8458 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8460 /* Navigate to Provider_nc_child2. */
8461 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8462 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child2", TRUE);
8463 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8464 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8465 ok(!!out_req, "out_req == NULL\n");
8466 ok(!!tree_struct, "tree_struct == NULL\n");
8467 ok(Provider_nc_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
8469 hr = SafeArrayGetElement(out_req, idx, &v);
8470 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8472 hr = UiaHUiaNodeFromVariant(&v, &node3);
8473 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8474 IUnknown_AddRef((IUnknown *)node3);
8476 exp_lbound[0] = exp_lbound[1] = 0;
8477 exp_elems[0] = exp_elems[1] = 1;
8478 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8480 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8481 ok_method_sequence(nav_seq6, "nav_seq6");
8483 SafeArrayDestroy(out_req);
8484 SysFreeString(tree_struct);
8486 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8487 ok(Provider_nc_child.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
8488 node2 = node3;
8490 /* Navigate to Provider_child. */
8491 SET_EXPECT(prov_callback_base_hwnd);
8492 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8493 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8494 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
8495 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8496 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8497 ok(!!out_req, "out_req == NULL\n");
8498 ok(!!tree_struct, "tree_struct == NULL\n");
8499 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
8500 CHECK_CALLED(prov_callback_base_hwnd);
8501 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8503 hr = SafeArrayGetElement(out_req, idx, &v);
8504 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8506 hr = UiaHUiaNodeFromVariant(&v, &node3);
8507 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8508 IUnknown_AddRef((IUnknown *)node3);
8510 exp_lbound[0] = exp_lbound[1] = 0;
8511 exp_elems[0] = exp_elems[1] = 1;
8512 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8514 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8515 ok_method_sequence(nav_seq7, "nav_seq7");
8517 SafeArrayDestroy(out_req);
8518 SysFreeString(tree_struct);
8520 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8521 ok(Provider_nc_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
8522 node2 = node3;
8524 /* Navigate to Provider_child2. */
8525 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8526 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
8527 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8528 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8529 ok(!!out_req, "out_req == NULL\n");
8530 ok(!!tree_struct, "tree_struct == NULL\n");
8531 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
8533 hr = SafeArrayGetElement(out_req, idx, &v);
8534 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8536 hr = UiaHUiaNodeFromVariant(&v, &node3);
8537 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8538 IUnknown_AddRef((IUnknown *)node3);
8540 exp_lbound[0] = exp_lbound[1] = 0;
8541 exp_elems[0] = exp_elems[1] = 1;
8542 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8544 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8545 ok_method_sequence(nav_seq8, "nav_seq8");
8547 SafeArrayDestroy(out_req);
8548 SysFreeString(tree_struct);
8550 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8551 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8552 node2 = node3;
8554 /* Try navigating to next sibling on the final child of the node. */
8555 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
8556 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
8557 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
8558 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8559 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8560 ok_method_sequence(nav_seq9, "nav_seq9");
8561 ok(!out_req, "out_req != NULL\n");
8562 ok(!tree_struct, "tree_struct != NULL\n");
8563 todo_wine CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
8564 todo_wine CHECK_CALLED_MULTI(prov_callback_base_hwnd, 2);
8565 todo_wine CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, 2);
8567 SafeArrayDestroy(out_req);
8568 SysFreeString(tree_struct);
8569 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8570 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
8572 /* Navigate to Provider_child2, last child. */
8573 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8574 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
8575 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8576 tree_struct = NULL;
8577 out_req = NULL;
8578 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8579 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8580 ok(!!out_req, "out_req == NULL\n");
8581 ok(!!tree_struct, "tree_struct == NULL\n");
8582 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
8584 exp_lbound[0] = exp_lbound[1] = 0;
8585 exp_elems[0] = exp_elems[1] = 1;
8586 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8588 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8589 ok_method_sequence(nav_seq10, "nav_seq10");
8591 SafeArrayDestroy(out_req);
8592 SysFreeString(tree_struct);
8595 * If the child we navigate to from a parent isn't considered the "parent
8596 * link" of it's HUIANODE, it is skipped. Here, we set Provider_hwnd_child
8597 * to an HWND provider, and set its main provider as Provider, which is
8598 * the parent link of the node.
8600 Provider_hwnd_child.hwnd = hwnd;
8601 Provider_hwnd_child.prov_opts = ProviderOptions_ClientSideProvider;
8602 Provider.parent = &Provider2.IRawElementProviderFragment_iface;
8603 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8604 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
8605 tree_struct = NULL;
8606 out_req = NULL;
8607 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8608 SET_EXPECT(prov_callback_nonclient);
8609 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8610 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8611 ok(!!out_req, "out_req == NULL\n");
8612 ok(!!tree_struct, "tree_struct == NULL\n");
8613 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8614 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8615 CHECK_CALLED(prov_callback_nonclient);
8617 hr = SafeArrayGetElement(out_req, idx, &v);
8618 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8620 hr = UiaHUiaNodeFromVariant(&v, &node2);
8621 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8622 IUnknown_AddRef((IUnknown *)node2);
8624 exp_lbound[0] = exp_lbound[1] = 0;
8625 exp_elems[0] = exp_elems[1] = 1;
8626 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8628 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8629 ok_method_sequence(nav_seq11, "nav_seq11");
8631 SafeArrayDestroy(out_req);
8632 SysFreeString(tree_struct);
8634 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8635 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8638 * Same test as before, except with NavigateDirection_LastChild. This will
8639 * end up with Provider_nc as the parent link for the node instead of
8640 * Provider_child2.
8642 Provider_child2.hwnd = hwnd;
8643 Provider_child2.ignore_hwnd_prop = TRUE;
8644 Provider_child2.parent = NULL;
8645 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
8646 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
8647 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8648 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
8649 tree_struct = NULL;
8650 out_req = NULL;
8651 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8652 SET_EXPECT(prov_callback_nonclient);
8653 SET_EXPECT(prov_callback_base_hwnd);
8654 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8655 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8656 ok(!!out_req, "out_req == NULL\n");
8657 ok(!!tree_struct, "tree_struct == NULL\n");
8658 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
8659 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8660 CHECK_CALLED(prov_callback_nonclient);
8661 CHECK_CALLED(prov_callback_base_hwnd);
8663 hr = SafeArrayGetElement(out_req, idx, &v);
8664 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8666 hr = UiaHUiaNodeFromVariant(&v, &node2);
8667 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8668 IUnknown_AddRef((IUnknown *)node2);
8670 exp_lbound[0] = exp_lbound[1] = 0;
8671 exp_elems[0] = exp_elems[1] = 1;
8672 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8674 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8675 ok_method_sequence(nav_seq12, "nav_seq12");
8677 SafeArrayDestroy(out_req);
8678 SysFreeString(tree_struct);
8680 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8681 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8683 Provider_child2.hwnd = NULL;
8684 Provider_child2.ignore_hwnd_prop = FALSE;
8685 Provider_child2.parent = &Provider.IRawElementProviderFragment_iface;
8687 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8688 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8689 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8690 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
8692 /* Create a node with Provider_nc as the parent link. */
8693 Provider.parent = Provider_hwnd.parent = NULL;
8694 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
8695 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
8696 Provider2.hwnd = NULL;
8698 node = (void *)0xdeadbeef;
8699 /* Only sent on Win7. */
8700 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8701 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8702 SET_EXPECT(prov_callback_base_hwnd);
8703 SET_EXPECT(prov_callback_nonclient);
8704 hr = UiaNodeFromHandle(hwnd, &node);
8705 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8706 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8707 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8708 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
8709 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8710 CHECK_CALLED(prov_callback_base_hwnd);
8711 CHECK_CALLED(prov_callback_nonclient);
8712 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8714 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8715 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8716 if (SUCCEEDED(hr))
8718 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
8719 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
8720 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
8721 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8722 VariantClear(&v);
8725 ok_method_sequence(nav_seq13, "nav_seq13");
8727 /* Navigate to Provider2, parent of Provider_nc. */
8728 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
8729 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider2", TRUE);
8730 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8731 tree_struct = NULL;
8732 out_req = NULL;
8733 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
8734 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8735 ok(!!out_req, "out_req == NULL\n");
8736 ok(!!tree_struct, "tree_struct == NULL\n");
8737 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
8739 exp_lbound[0] = exp_lbound[1] = 0;
8740 exp_elems[0] = exp_elems[1] = 1;
8741 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8743 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8745 SafeArrayDestroy(out_req);
8746 SysFreeString(tree_struct);
8747 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
8748 ok_method_sequence(nav_seq14, "nav_seq14");
8750 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8751 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8752 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8753 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
8755 Provider_hwnd_child.hwnd = NULL;
8756 Provider_hwnd_child.prov_opts = ProviderOptions_ServerSideProvider;
8757 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = FALSE;
8758 base_hwnd_prov = nc_prov = NULL;
8759 prov_root = NULL;
8760 UiaRegisterProviderCallback(NULL);
8762 CoUninitialize();
8763 DestroyWindow(hwnd);
8764 UnregisterClassA("UiaNavigate class", NULL);
8767 static void set_find_params(struct UiaFindParams *params, int max_depth, BOOL find_first, BOOL exclude_root,
8768 struct UiaCondition *find_cond)
8770 params->MaxDepth = max_depth;
8771 params->FindFirst = find_first;
8772 params->ExcludeRoot = exclude_root;
8773 params->pFindCondition = find_cond;
8776 static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count)
8778 prov->prop_override = override;
8779 prov->prop_override_count = count;
8782 static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val)
8784 override->prop_id = prop_id;
8785 override->val = *val;
8788 static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links)
8790 prov->prov_opts = prov_opts;
8791 prov->hwnd = hwnd;
8792 prov->ret_invalid_prop_type = FALSE;
8793 prov->expected_tid = 0;
8794 prov->runtime_id[0] = prov->runtime_id[1] = 0;
8795 prov->last_call_tid = 0;
8796 prov->ignore_hwnd_prop = FALSE;
8797 prov->override_hwnd = NULL;
8798 prov->prop_override = NULL;
8799 prov->prop_override_count = 0;
8800 memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect));
8801 memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data));
8802 if (initialize_nav_links)
8804 prov->frag_root = NULL;
8805 prov->parent = prov->prev_sibling = prov->next_sibling = prov->first_child = prov->last_child = NULL;
8809 static void initialize_provider_tree(BOOL initialize_nav_links)
8811 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8812 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8813 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8814 initialize_provider(&Provider_child_child2, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8815 initialize_provider(&Provider_child2, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8816 initialize_provider(&Provider_child2_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8817 initialize_provider(&Provider_child2_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
8820 static void provider_add_child(struct Provider *prov, struct Provider *child)
8822 if (!prov->first_child)
8824 prov->first_child = prov->last_child = &child->IRawElementProviderFragment_iface;
8825 child->next_sibling = child->prev_sibling = NULL;
8827 else
8829 struct Provider *tmp = impl_from_ProviderFragment(prov->last_child);
8831 tmp->next_sibling = &child->IRawElementProviderFragment_iface;
8832 child->prev_sibling = prov->last_child;
8833 prov->last_child = &child->IRawElementProviderFragment_iface;
8836 child->parent = &prov->IRawElementProviderFragment_iface;
8837 child->frag_root = prov->frag_root;
8840 #define test_find_sa_results( tree_structs, offsets, exp_elems, exp_tree_struct, exp_offsets ) \
8841 test_find_sa_results_( (tree_structs), (offsets), (exp_elems), (exp_tree_struct), (exp_offsets), __FILE__, __LINE__)
8842 static void test_find_sa_results_(SAFEARRAY *tree_structs, SAFEARRAY *offsets, LONG exp_elems,
8843 const WCHAR **exp_tree_struct, int *exp_offset, const char *file, int line)
8845 LONG lbound, ubound, elems;
8846 HRESULT hr;
8847 VARTYPE vt;
8848 UINT dims;
8849 LONG i;
8851 /* Tree structures SA. */
8852 hr = SafeArrayGetVartype(tree_structs, &vt);
8853 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8854 ok_(file, line)(vt == VT_BSTR, "Unexpected tree structures sa vt %d\n", vt);
8855 dims = SafeArrayGetDim(tree_structs);
8856 ok_(file, line)(dims == 1, "Unexpected tree structures sa dims %d\n", dims);
8858 lbound = ubound = elems = 0;
8859 hr = SafeArrayGetLBound(tree_structs, 1, &lbound);
8860 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
8861 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
8863 hr = SafeArrayGetUBound(tree_structs, 1, &ubound);
8864 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
8866 elems = (ubound - lbound) + 1;
8867 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
8869 /* Offsets SA. */
8870 hr = SafeArrayGetVartype(offsets, &vt);
8871 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8872 ok_(file, line)(vt == VT_I4, "Unexpected offsets sa vt %d\n", vt);
8873 dims = SafeArrayGetDim(offsets);
8874 ok_(file, line)(dims == 1, "Unexpected offsets sa dims %d\n", dims);
8876 lbound = ubound = elems = 0;
8877 hr = SafeArrayGetLBound(offsets, 1, &lbound);
8878 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
8879 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
8881 hr = SafeArrayGetUBound(offsets, 1, &ubound);
8882 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
8884 elems = (ubound - lbound) + 1;
8885 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
8887 for (i = 0; i < exp_elems; i++)
8889 BSTR tree_struct;
8890 int offset;
8892 hr = SafeArrayGetElement(tree_structs, &i, &tree_struct);
8893 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
8894 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct[i]), "Unexpected tree structure %s\n", debugstr_w(tree_struct));
8895 SysFreeString(tree_struct);
8897 hr = SafeArrayGetElement(offsets, &i, &offset);
8898 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
8899 ok_(file, line)(exp_offset[i] == offset, "Unexpected offset %d\n", offset);
8903 static const struct prov_method_sequence find_seq1[] = {
8904 { &Provider, FRAG_GET_RUNTIME_ID },
8905 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8906 NODE_CREATE_SEQ(&Provider_child),
8907 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8908 NODE_CREATE_SEQ(&Provider_child_child),
8909 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8910 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8911 NODE_CREATE_SEQ(&Provider_child_child2),
8912 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8913 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8914 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8915 NODE_CREATE_SEQ(&Provider_child),
8916 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8917 NODE_CREATE_SEQ(&Provider_child2),
8918 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8919 NODE_CREATE_SEQ(&Provider_child2_child),
8920 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8921 NODE_CREATE_SEQ(&Provider_child2_child_child),
8922 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8923 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8924 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8925 NODE_CREATE_SEQ(&Provider_child2_child),
8926 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8927 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8928 NODE_CREATE_SEQ(&Provider_child2),
8929 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8930 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8931 NODE_CREATE_SEQ(&Provider),
8932 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8933 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8934 /* Only done on Win10v1507 and below. */
8935 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8936 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8937 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8938 { &Provider_child_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8939 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8940 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8941 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8942 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8943 { 0 },
8946 static const struct prov_method_sequence find_seq2[] = {
8947 { &Provider, FRAG_GET_RUNTIME_ID },
8948 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8949 NODE_CREATE_SEQ(&Provider_child),
8950 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8951 NODE_CREATE_SEQ(&Provider_child2),
8952 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8953 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8954 NODE_CREATE_SEQ(&Provider),
8955 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8956 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8957 /* Only done on Win10v1507 and below. */
8958 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8959 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8960 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8961 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8962 { 0 },
8965 static const struct prov_method_sequence find_seq3[] = {
8966 { &Provider, FRAG_GET_RUNTIME_ID },
8967 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8968 NODE_CREATE_SEQ(&Provider_child),
8969 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8970 NODE_CREATE_SEQ(&Provider_child2),
8971 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8972 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8973 NODE_CREATE_SEQ(&Provider),
8974 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8975 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8976 /* Only done on Win10v1507 and below. */
8977 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8978 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8979 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8980 { 0 },
8983 static const struct prov_method_sequence find_seq4[] = {
8984 { &Provider, FRAG_GET_RUNTIME_ID },
8985 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8986 NODE_CREATE_SEQ(&Provider_child),
8987 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8988 { 0 },
8991 static const struct prov_method_sequence find_seq5[] = {
8992 { &Provider_child, FRAG_GET_RUNTIME_ID },
8993 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8994 NODE_CREATE_SEQ(&Provider_child2),
8995 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8996 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8997 NODE_CREATE_SEQ(&Provider),
8998 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8999 NODE_CREATE_SEQ(&Provider),
9000 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9001 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9002 { 0 },
9005 static const struct prov_method_sequence find_seq6[] = {
9006 { &Provider_child, FRAG_GET_RUNTIME_ID },
9007 { &Provider_child, FRAG_GET_RUNTIME_ID },
9008 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9009 { 0 },
9012 static const struct prov_method_sequence find_seq7[] = {
9013 { &Provider, FRAG_GET_RUNTIME_ID },
9014 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9015 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9016 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9017 NODE_CREATE_SEQ(&Provider_child),
9018 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9019 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9020 NODE_CREATE_SEQ(&Provider_child_child),
9021 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9022 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9023 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9024 NODE_CREATE_SEQ(&Provider_child_child2),
9025 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9026 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9027 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9028 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9029 NODE_CREATE_SEQ(&Provider_child),
9030 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9031 NODE_CREATE_SEQ(&Provider_child2),
9032 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9033 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9034 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9035 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9036 NODE_CREATE_SEQ(&Provider),
9037 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9038 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9039 /* Only done on Win10v1507 and below. */
9040 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9041 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9042 { &Provider_child_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9043 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9044 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9045 { 0 },
9048 static const struct prov_method_sequence find_seq8[] = {
9049 { &Provider, FRAG_GET_RUNTIME_ID },
9050 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9051 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9052 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9053 NODE_CREATE_SEQ(&Provider_child),
9054 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9055 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9056 NODE_CREATE_SEQ(&Provider_child_child),
9057 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9058 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9059 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
9060 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9061 NODE_CREATE_SEQ(&Provider_child_child2),
9062 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9063 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9064 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
9065 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9066 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9067 NODE_CREATE_SEQ(&Provider_child),
9068 { &Provider_child, FRAG_GET_RUNTIME_ID },
9069 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9070 NODE_CREATE_SEQ(&Provider_child2),
9071 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9072 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9073 { &Provider_child2, FRAG_GET_RUNTIME_ID },
9074 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9075 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9076 NODE_CREATE_SEQ(&Provider),
9077 { &Provider, FRAG_GET_RUNTIME_ID },
9078 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9079 { &Provider_child_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9080 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9081 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9082 { 0 },
9085 static const struct prov_method_sequence find_seq9[] = {
9086 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
9087 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9088 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9089 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9090 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9091 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9092 NODE_CREATE_SEQ(&Provider_child),
9093 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9094 NODE_CREATE_SEQ(&Provider_child),
9095 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9096 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9097 NODE_CREATE_SEQ(&Provider_child2),
9098 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9099 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9100 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9101 NODE_CREATE_SEQ(&Provider_child2_child),
9102 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9103 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9104 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9105 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9106 NODE_CREATE_SEQ(&Provider_child2),
9107 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9108 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9109 NODE_CREATE_SEQ(&Provider),
9110 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9111 NODE_CREATE_SEQ(&Provider),
9112 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9113 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9114 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9115 /* Only done on Win10v1507 and below. */
9116 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9117 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9118 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9119 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9120 { 0 },
9123 static const struct prov_method_sequence find_seq10[] = {
9124 { &Provider, FRAG_GET_RUNTIME_ID },
9125 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9126 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9127 NODE_CREATE_SEQ(&Provider_child),
9128 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9129 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9130 NODE_CREATE_SEQ(&Provider_child_child),
9131 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9132 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9133 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9134 NODE_CREATE_SEQ(&Provider_child_child2),
9135 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9136 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9137 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9138 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9139 NODE_CREATE_SEQ(&Provider_child),
9140 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9141 NODE_CREATE_SEQ(&Provider_child2),
9142 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9143 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9144 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9145 NODE_CREATE_SEQ(&Provider_child2_child),
9146 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9147 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9148 NODE_CREATE_SEQ(&Provider_child2_child_child),
9149 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9150 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9151 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9152 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9153 NODE_CREATE_SEQ(&Provider_child2_child),
9154 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9155 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9156 NODE_CREATE_SEQ(&Provider_child2),
9157 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9158 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9159 NODE_CREATE_SEQ(&Provider),
9160 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9161 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9162 /* Only done on Win10v1507 and below. */
9163 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9164 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9165 { 0 },
9168 static const struct prov_method_sequence find_seq11[] = {
9169 { &Provider, FRAG_GET_RUNTIME_ID },
9170 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9171 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9172 NODE_CREATE_SEQ(&Provider_child),
9173 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9174 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9175 NODE_CREATE_SEQ(&Provider_child_child),
9176 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9177 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9178 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9179 NODE_CREATE_SEQ(&Provider_child_child2),
9180 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
9181 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9182 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
9183 { 0 },
9186 static void test_UiaFind(void)
9188 struct Provider_prop_override prop_override;
9189 LONG exp_lbound[2], exp_elems[2], idx[2], i;
9190 SAFEARRAY *out_req, *offsets, *tree_structs;
9191 struct node_provider_desc exp_node_desc[7];
9192 struct UiaPropertyCondition prop_cond[2];
9193 struct UiaCacheRequest cache_req;
9194 struct UiaFindParams find_params;
9195 const WCHAR *exp_tree_struct[7];
9196 HUIANODE node, node2;
9197 int exp_offset[7];
9198 HRESULT hr;
9199 VARIANT v;
9201 CoInitializeEx(NULL, COINIT_MULTITHREADED);
9203 initialize_provider_tree(TRUE);
9204 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
9205 provider_add_child(&Provider, &Provider_child);
9206 provider_add_child(&Provider, &Provider_child2);
9207 provider_add_child(&Provider_child, &Provider_child_child);
9208 provider_add_child(&Provider_child, &Provider_child_child2);
9209 provider_add_child(&Provider_child2, &Provider_child2_child);
9210 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
9212 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9213 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9215 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
9216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9217 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9219 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9220 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9221 if (SUCCEEDED(hr))
9223 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
9224 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9225 VariantClear(&v);
9228 ok_method_sequence(node_from_prov2, NULL);
9231 * Maximum find depth of -1, find first is FALSE, exclude root is FALSE. A
9232 * maximum depth of -1 will search the entire tree.
9234 out_req = offsets = tree_structs = NULL;
9235 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
9236 AutomationElementMode_Full);
9237 set_find_params(&find_params, -1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
9238 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9239 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9240 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9241 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
9242 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
9243 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9244 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
9245 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
9247 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9248 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
9249 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child", TRUE);
9250 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child_child2", TRUE);
9251 add_provider_desc(&exp_node_desc[4], L"Main", L"Provider_child2", TRUE);
9252 add_provider_desc(&exp_node_desc[5], L"Main", L"Provider_child2_child", TRUE);
9253 add_provider_desc(&exp_node_desc[6], L"Main", L"Provider_child2_child_child", TRUE);
9254 exp_lbound[0] = exp_lbound[1] = 0;
9255 exp_elems[0] = 7;
9256 exp_elems[1] = 1;
9258 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9260 for (i = 0; i < exp_elems[0]; i++)
9262 exp_offset[i] = i;
9263 exp_tree_struct[i] = L"P)";
9265 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9266 ok_method_sequence(find_seq1, "find_seq1");
9268 SafeArrayDestroy(out_req);
9269 SafeArrayDestroy(offsets);
9270 SafeArrayDestroy(tree_structs);
9272 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9273 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9276 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
9278 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
9279 AutomationElementMode_Full);
9280 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
9281 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9283 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9284 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9286 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9287 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
9288 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2", TRUE);
9289 exp_lbound[0] = exp_lbound[1] = 0;
9290 exp_elems[0] = 3;
9291 exp_elems[1] = 1;
9293 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9295 for (i = 0; i < exp_elems[0]; i++)
9297 exp_offset[i] = i;
9298 exp_tree_struct[i] = L"P)";
9301 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9302 ok_method_sequence(find_seq2, "find_seq2");
9304 SafeArrayDestroy(out_req);
9305 SafeArrayDestroy(offsets);
9306 SafeArrayDestroy(tree_structs);
9308 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9309 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9312 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
9314 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
9315 AutomationElementMode_Full);
9316 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
9317 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9319 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9320 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9322 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9323 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
9324 exp_lbound[0] = exp_lbound[1] = 0;
9325 exp_elems[0] = 2;
9326 exp_elems[1] = 1;
9328 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9330 for (i = 0; i < exp_elems[0]; i++)
9332 exp_offset[i] = i;
9333 exp_tree_struct[i] = L"P)";
9335 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9336 ok_method_sequence(find_seq3, "find_seq3");
9338 SafeArrayDestroy(out_req);
9339 SafeArrayDestroy(offsets);
9340 SafeArrayDestroy(tree_structs);
9342 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9343 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9346 * Maximum find depth of 1, find first is TRUE, exclude root is TRUE. Will
9347 * retrieve only Provider_child.
9349 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
9350 AutomationElementMode_Full);
9351 set_find_params(&find_params, 1, TRUE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
9352 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9353 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9354 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9356 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9357 exp_lbound[0] = exp_lbound[1] = 0;
9358 exp_elems[0] = exp_elems[1] = 1;
9360 idx[0] = idx[1] = 0;
9361 hr = SafeArrayGetElement(out_req, idx, &v);
9362 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9364 /* node2 is now set as Provider_child. */
9365 hr = UiaHUiaNodeFromVariant(&v, &node2);
9366 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9367 IUnknown_AddRef((IUnknown *)node2);
9369 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9371 for (i = 0; i < exp_elems[0]; i++)
9373 exp_offset[i] = i;
9374 exp_tree_struct[i] = L"P)";
9376 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9377 ok_method_sequence(find_seq4, "find_seq4");
9379 SafeArrayDestroy(out_req);
9380 SafeArrayDestroy(offsets);
9381 SafeArrayDestroy(tree_structs);
9383 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9384 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9387 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
9388 * Provider_child doesn't have a runtime id for UI Automation to use as a
9389 * way to check if it has navigated back to the node that began the
9390 * search, so it will get siblings.
9392 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
9393 AutomationElementMode_Full);
9394 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
9395 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9396 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9397 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9399 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9400 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
9401 exp_lbound[0] = exp_lbound[1] = 0;
9402 exp_elems[0] = 2;
9403 exp_elems[1] = 1;
9405 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9407 for (i = 0; i < exp_elems[0]; i++)
9409 exp_offset[i] = i;
9410 exp_tree_struct[i] = L"P)";
9412 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9413 ok_method_sequence(find_seq5, "find_seq5");
9415 SafeArrayDestroy(out_req);
9416 SafeArrayDestroy(offsets);
9417 SafeArrayDestroy(tree_structs);
9419 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9420 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9423 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
9424 * Provider_child has a runtime id for UI Automation to use as a
9425 * way to check if it has navigated back to the node that began the
9426 * search, so it will stop at Provider_child.
9428 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
9429 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
9430 AutomationElementMode_Full);
9431 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
9432 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9435 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9436 exp_lbound[0] = exp_lbound[1] = 0;
9437 exp_elems[0] = exp_elems[1] = 1;
9439 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9441 for (i = 0; i < exp_elems[0]; i++)
9443 exp_offset[i] = i;
9444 exp_tree_struct[i] = L"P)";
9446 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9447 ok_method_sequence(find_seq6, "find_seq6");
9449 SafeArrayDestroy(out_req);
9450 SafeArrayDestroy(offsets);
9451 SafeArrayDestroy(tree_structs);
9453 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9454 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
9456 initialize_provider_tree(FALSE);
9457 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9458 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9461 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
9462 * The cache request view condition is used to determine tree depth, if an
9463 * element matches the cache request view condition, depth is incremented.
9464 * Since Provider_child does not, Provider_child_child, Provider_child_child2,
9465 * and Provider_child2 are all considered to be at depth 1.
9467 V_VT(&v) = VT_BOOL;
9468 V_BOOL(&v) = VARIANT_FALSE;
9469 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
9470 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
9472 V_VT(&v) = VT_BOOL;
9473 V_BOOL(&v) = VARIANT_TRUE;
9474 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
9476 set_provider_prop_override(&Provider, &prop_override, 1);
9477 set_provider_prop_override(&Provider_child2, &prop_override, 1);
9478 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
9479 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
9481 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, NULL, 0, NULL, 0,
9482 AutomationElementMode_Full);
9483 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
9484 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9486 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
9487 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
9488 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9490 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9491 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
9492 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
9493 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
9494 exp_lbound[0] = exp_lbound[1] = 0;
9495 exp_elems[0] = 4;
9496 exp_elems[1] = 1;
9498 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9500 for (i = 0; i < exp_elems[0]; i++)
9502 exp_offset[i] = i;
9503 exp_tree_struct[i] = L"P)";
9505 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9506 ok_method_sequence(find_seq7, "find_seq7");
9508 SafeArrayDestroy(out_req);
9509 SafeArrayDestroy(offsets);
9510 SafeArrayDestroy(tree_structs);
9512 initialize_provider_tree(FALSE);
9513 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9514 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9517 * Same test as before, except Provider has a runtime id.
9519 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
9520 V_VT(&v) = VT_BOOL;
9521 V_BOOL(&v) = VARIANT_FALSE;
9522 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
9523 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
9525 V_VT(&v) = VT_BOOL;
9526 V_BOOL(&v) = VARIANT_TRUE;
9527 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
9529 set_provider_prop_override(&Provider, &prop_override, 1);
9530 set_provider_prop_override(&Provider_child2, &prop_override, 1);
9531 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
9532 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
9534 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, NULL, 0, NULL, 0,
9535 AutomationElementMode_Full);
9536 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
9537 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9538 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9539 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
9540 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
9541 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9543 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9544 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
9545 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
9546 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
9547 exp_lbound[0] = exp_lbound[1] = 0;
9548 exp_elems[0] = 4;
9549 exp_elems[1] = 1;
9551 idx[0] = 2;
9552 idx[1] = 0;
9553 hr = SafeArrayGetElement(out_req, idx, &v);
9554 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9556 /* node2 is now set as Provider_child_child2. */
9557 hr = UiaHUiaNodeFromVariant(&v, &node2);
9558 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9559 IUnknown_AddRef((IUnknown *)node2);
9561 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9563 for (i = 0; i < exp_elems[0]; i++)
9565 exp_offset[i] = i;
9566 exp_tree_struct[i] = L"P)";
9568 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9569 ok_method_sequence(find_seq8, "find_seq8");
9571 SafeArrayDestroy(out_req);
9572 SafeArrayDestroy(offsets);
9573 SafeArrayDestroy(tree_structs);
9575 initialize_provider_tree(FALSE);
9576 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9577 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9580 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
9581 * Starting at Provider_child_child2, find will be able to traverse the
9582 * tree in the same order as it would if we had started at the tree root
9583 * Provider, retrieving Provider_child2 as a sibling and
9584 * Provider_child2_child as a node at depth 1.
9586 V_VT(&v) = VT_BOOL;
9587 V_BOOL(&v) = VARIANT_FALSE;
9588 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
9590 V_VT(&v) = VT_BOOL;
9591 V_BOOL(&v) = VARIANT_TRUE;
9592 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
9594 prop_override.prop_id = UIA_IsContentElementPropertyId;
9595 V_VT(&prop_override.val) = VT_BOOL;
9596 V_BOOL(&prop_override.val) = VARIANT_FALSE;
9597 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
9598 set_provider_prop_override(&Provider_child2, &prop_override, 1);
9599 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
9601 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, NULL, 0, NULL, 0,
9602 AutomationElementMode_Full);
9603 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
9604 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9605 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9606 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9607 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
9609 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
9610 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
9611 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2_child", TRUE);
9612 exp_lbound[0] = exp_lbound[1] = 0;
9613 exp_elems[0] = 3;
9614 exp_elems[1] = 1;
9616 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9618 for (i = 0; i < exp_elems[0]; i++)
9620 exp_offset[i] = i;
9621 exp_tree_struct[i] = L"P)";
9623 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9624 ok_method_sequence(find_seq9, "find_seq9");
9626 SafeArrayDestroy(out_req);
9627 SafeArrayDestroy(offsets);
9628 SafeArrayDestroy(tree_structs);
9630 initialize_provider_tree(FALSE);
9631 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9632 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9634 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9635 ok(Provider_child_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
9638 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
9639 * Exclude root applies to the first node that matches the view
9640 * condition, and not the node that is passed into UiaFind(). Since
9641 * Provider doesn't match our view condition here, Provider_child will be
9642 * excluded.
9644 V_VT(&v) = VT_BOOL;
9645 V_BOOL(&v) = VARIANT_FALSE;
9646 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
9647 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
9649 V_VT(&v) = VT_BOOL;
9650 V_BOOL(&v) = VARIANT_TRUE;
9651 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
9653 set_provider_prop_override(&Provider_child, &prop_override, 1);
9654 set_provider_prop_override(&Provider_child2, &prop_override, 1);
9656 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, NULL, 0, NULL, 0,
9657 AutomationElementMode_Full);
9658 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&prop_cond[1]);
9659 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9660 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9661 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9663 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
9664 exp_lbound[0] = exp_lbound[1] = 0;
9665 exp_elems[0] = 1;
9666 exp_elems[1] = 1;
9668 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9670 for (i = 0; i < exp_elems[0]; i++)
9672 exp_offset[i] = i;
9673 exp_tree_struct[i] = L"P)";
9675 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9677 ok_method_sequence(find_seq10, "find_seq10");
9679 SafeArrayDestroy(out_req);
9680 SafeArrayDestroy(offsets);
9681 SafeArrayDestroy(tree_structs);
9683 initialize_provider_tree(FALSE);
9684 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9685 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9688 * Maximum find depth of -1, find first is TRUE, exclude root is FALSE.
9689 * Provider_child_child2 is the only element in the tree to match our
9690 * condition.
9692 V_VT(&v) = VT_BOOL;
9693 V_BOOL(&v) = VARIANT_FALSE;
9694 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
9695 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
9697 V_VT(&v) = VT_BOOL;
9698 V_BOOL(&v) = VARIANT_TRUE;
9699 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
9701 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
9703 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, NULL, 0, NULL, 0,
9704 AutomationElementMode_Full);
9705 set_find_params(&find_params, -1, TRUE, FALSE, (struct UiaCondition *)&prop_cond[1]);
9706 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
9707 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9708 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
9710 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
9711 exp_lbound[0] = exp_lbound[1] = 0;
9712 exp_elems[0] = 1;
9713 exp_elems[1] = 1;
9715 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9717 for (i = 0; i < exp_elems[0]; i++)
9719 exp_offset[i] = i;
9720 exp_tree_struct[i] = L"P)";
9722 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
9723 ok_method_sequence(find_seq11, "find_seq11");
9725 SafeArrayDestroy(out_req);
9726 SafeArrayDestroy(offsets);
9727 SafeArrayDestroy(tree_structs);
9729 initialize_provider_tree(TRUE);
9731 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
9732 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
9734 CoUninitialize();
9737 static HWND create_test_hwnd(const char *class_name)
9739 WNDCLASSA cls = { 0 };
9741 cls.lpfnWndProc = test_wnd_proc;
9742 cls.hInstance = GetModuleHandleA(NULL);
9743 cls.lpszClassName = class_name;
9744 RegisterClassA(&cls);
9746 return CreateWindowA(class_name, "Test window", WS_OVERLAPPEDWINDOW,
9747 0, 0, 100, 100, NULL, NULL, NULL, NULL);
9750 static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd, BOOL block_hwnd_provs)
9752 IUIAutomationElement *element;
9753 HRESULT hr;
9754 VARIANT v;
9756 if (block_hwnd_provs)
9758 SET_EXPECT(prov_callback_base_hwnd);
9759 SET_EXPECT(prov_callback_nonclient);
9760 base_hwnd_prov = proxy_prov = parent_proxy_prov = nc_prov = NULL;
9761 UiaRegisterProviderCallback(test_uia_provider_callback);
9763 else
9764 UiaRegisterProviderCallback(NULL);
9766 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
9767 prov_root = &Provider.IRawElementProviderSimple_iface;
9768 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9769 /* Only sent on Win7. */
9770 SET_EXPECT(winproc_GETOBJECT_CLIENT);
9771 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &element);
9772 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9773 ok(!!element, "element == NULL\n");
9774 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9775 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9776 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
9777 if (block_hwnd_provs)
9779 CHECK_CALLED(prov_callback_base_hwnd);
9780 CHECK_CALLED(prov_callback_nonclient);
9783 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
9784 todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9785 if (SUCCEEDED(hr))
9787 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
9788 if (!block_hwnd_provs)
9790 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
9791 check_node_provider_desc(V_BSTR(&v), L"Nonclient", NULL, FALSE);
9792 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
9794 else
9795 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9797 VariantClear(&v);
9800 ok_method_sequence(node_from_hwnd2, "create_test_element");
9801 UiaRegisterProviderCallback(NULL);
9803 return element;
9806 static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8)
9808 HWND hwnd = create_test_hwnd("test_ElementFromHandle class");
9809 IUIAutomationElement2 *element_2;
9810 IUIAutomationElement *element;
9811 HRESULT hr;
9813 element = create_test_element_from_hwnd(uia_iface, hwnd, FALSE);
9814 hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2);
9815 if (is_cui8)
9817 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9818 ok(!!element_2, "element_2 == NULL\n");
9819 IUIAutomationElement2_Release(element_2);
9821 else
9822 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
9824 IUIAutomationElement_Release(element);
9825 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
9827 DestroyWindow(hwnd);
9828 UnregisterClassA("test_ElementFromHandle class", NULL);
9829 prov_root = NULL;
9832 static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
9834 HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class");
9835 const struct uia_element_property *elem_prop;
9836 struct Provider_prop_override prop_override;
9837 IUIAutomationElement *element, *element2;
9838 int i, prop_id, tmp_int;
9839 struct UiaRect uia_rect;
9840 IUnknown *unk_ns;
9841 BSTR tmp_bstr;
9842 HRESULT hr;
9843 RECT rect;
9844 VARIANT v;
9846 element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
9847 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
9848 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
9849 provider_add_child(&Provider, &Provider_child);
9851 hr = UiaGetReservedNotSupportedValue(&unk_ns);
9852 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9854 VariantInit(&v);
9855 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
9857 elem_prop = &element_properties[i];
9859 /* Skip ElementArray properties for now. */
9860 if (elem_prop->type == UIAutomationType_ElementArray)
9861 continue;
9863 Provider.ret_invalid_prop_type = FALSE;
9864 VariantClear(&v);
9865 if (!(prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid)))
9867 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
9868 break;
9871 winetest_push_context("Element prop_id %d", prop_id);
9872 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
9873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9874 check_uia_prop_val(prop_id, elem_prop->type, &v, TRUE);
9877 * Some properties have special behavior if an invalid value is
9878 * returned, skip them here.
9880 if (!elem_prop->skip_invalid)
9882 Provider.ret_invalid_prop_type = TRUE;
9883 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
9884 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9885 if (SUCCEEDED(hr))
9887 ok_method_sequence(get_prop_invalid_type_seq, NULL);
9888 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
9889 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
9890 VariantClear(&v);
9894 winetest_pop_context();
9898 * IUIAutomationElement_get_CurrentControlType tests. If the value
9899 * returned for UIA_ControlTypePropertyId is not a registered control
9900 * type ID, we'll get back UIA_CustomControlTypeId.
9902 tmp_int = 0xdeadb33f;
9903 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
9904 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9907 * Win10v1507 and below don't check whether or not the returned control
9908 * type ID is valid.
9910 ok(tmp_int == UIA_CustomControlTypeId || broken(tmp_int == 0xdeadbeef), "Unexpected control type %#x\n", tmp_int);
9911 ok_method_sequence(get_prop_seq, NULL);
9913 Provider.ret_invalid_prop_type = TRUE;
9914 tmp_int = 0xdeadbeef;
9915 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
9916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9917 ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
9918 Provider.ret_invalid_prop_type = FALSE;
9919 ok_method_sequence(get_prop_invalid_type_seq, NULL);
9921 /* Finally, a valid control type. */
9922 V_VT(&v) = VT_I4;
9923 V_I4(&v) = UIA_HyperlinkControlTypeId;
9924 set_property_override(&prop_override, UIA_ControlTypePropertyId, &v);
9925 set_provider_prop_override(&Provider, &prop_override, 1);
9926 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
9927 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9928 ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
9929 set_provider_prop_override(&Provider, NULL, 0);
9930 ok_method_sequence(get_prop_seq, NULL);
9933 * IUIAutomationElement_get_CurrentName tests.
9935 tmp_bstr = NULL;
9936 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
9937 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9938 ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
9939 SysFreeString(tmp_bstr);
9940 ok_method_sequence(get_prop_seq, NULL);
9942 tmp_bstr = NULL;
9943 Provider.ret_invalid_prop_type = TRUE;
9944 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
9945 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9946 ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
9947 SysFreeString(tmp_bstr);
9948 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
9949 ok_method_sequence(get_prop_invalid_type_seq, NULL);
9952 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
9953 * It's the only version with this behavior.
9955 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
9957 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
9958 goto exit;
9962 * IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests.
9964 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
9965 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9966 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
9967 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9969 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
9970 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9971 ok(!!element2, "element2 == NULL\n");
9972 VariantClear(&v);
9974 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
9975 set_uia_rect(&uia_rect, 0, 0, 50, 50);
9976 Provider_child.bounds_rect = uia_rect;
9977 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
9978 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9979 check_uia_rect_val(&v, &uia_rect);
9980 VariantClear(&v);
9981 ok_method_sequence(get_bounding_rect_seq2, "get_bounding_rect_seq2");
9983 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
9984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9985 check_uia_rect_rect_val(&rect, &uia_rect);
9986 memset(&rect, 0, sizeof(rect));
9987 ok_method_sequence(get_bounding_rect_seq3, "get_bounding_rect_seq3");
9989 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
9990 set_uia_rect(&uia_rect, 0, 0, 0, 0);
9991 Provider_child.bounds_rect = uia_rect;
9992 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
9993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9994 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
9995 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
9996 VariantClear(&v);
9997 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
9999 /* Returns an all 0 rect. */
10000 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
10001 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10002 check_uia_rect_rect_val(&rect, &uia_rect);
10003 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
10005 IUIAutomationElement_Release(element2);
10006 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10007 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
10009 exit:
10010 IUIAutomationElement_Release(element);
10011 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10013 DestroyWindow(hwnd);
10014 UnregisterClassA("test_Element_GetPropertyValue class", NULL);
10017 static void test_CUIAutomation_value_conversion(IUIAutomation *uia_iface)
10019 static const VARTYPE invalid_int_vts[] = { VT_I8, VT_INT };
10020 int *out_arr, out_arr_count, i;
10021 SAFEARRAY *sa;
10022 VARTYPE vt;
10023 HRESULT hr;
10025 for (i = 0; i < ARRAY_SIZE(invalid_int_vts); i++)
10027 vt = invalid_int_vts[i];
10028 sa = SafeArrayCreateVector(vt, 0, 2);
10029 ok(!!sa, "sa == NULL\n");
10031 out_arr_count = 0xdeadbeef;
10032 out_arr = (int *)0xdeadbeef;
10033 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
10034 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
10035 ok(!out_arr, "out_arr != NULL\n");
10036 ok(out_arr_count == 0xdeadbeef, "Unexpected out_arr_count %#x\n", out_arr_count);
10037 SafeArrayDestroy(sa);
10040 /* Only accepts VT_I4 as an input array type. */
10041 sa = create_i4_safearray();
10042 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
10043 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10044 ok(out_arr_count == ARRAY_SIZE(uia_i4_arr_prop_val), "Unexpected out_arr_count %#x\n", out_arr_count);
10045 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val); i++)
10046 ok(out_arr[i] == uia_i4_arr_prop_val[i], "out_arr[%d]: Expected %ld, got %d\n", i, uia_i4_arr_prop_val[i], out_arr[i]);
10048 SafeArrayDestroy(sa);
10049 CoTaskMemFree(out_arr);
10052 struct uia_com_classes {
10053 const GUID *clsid;
10054 const GUID *iid;
10057 static const struct uia_com_classes com_classes[] = {
10058 { &CLSID_CUIAutomation, &IID_IUnknown },
10059 { &CLSID_CUIAutomation, &IID_IUIAutomation },
10060 { &CLSID_CUIAutomation8, &IID_IUnknown },
10061 { &CLSID_CUIAutomation8, &IID_IUIAutomation },
10062 { &CLSID_CUIAutomation8, &IID_IUIAutomation2 },
10063 { &CLSID_CUIAutomation8, &IID_IUIAutomation3 },
10064 { &CLSID_CUIAutomation8, &IID_IUIAutomation4 },
10065 { &CLSID_CUIAutomation8, &IID_IUIAutomation5 },
10066 { &CLSID_CUIAutomation8, &IID_IUIAutomation6 },
10069 static void test_CUIAutomation(void)
10071 IUIAutomation *uia_iface;
10072 BOOL has_cui8 = TRUE;
10073 HRESULT hr;
10074 int i;
10076 CoInitializeEx(NULL, COINIT_MULTITHREADED);
10078 for (i = 0; i < ARRAY_SIZE(com_classes); i++)
10080 IUnknown *iface = NULL;
10082 hr = CoCreateInstance(com_classes[i].clsid, NULL, CLSCTX_INPROC_SERVER, com_classes[i].iid,
10083 (void **)&iface);
10085 if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG))
10087 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
10088 has_cui8 = FALSE;
10089 break;
10091 else if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == E_NOINTERFACE) &&
10092 (com_classes[i].iid != &IID_IUIAutomation2) && (com_classes[i].iid != &IID_IUIAutomation) &&
10093 (com_classes[i].iid != &IID_IUnknown))
10095 win_skip("No object for clsid %s, iid %s, skipping further tests.\n", debugstr_guid(com_classes[i].clsid),
10096 debugstr_guid(com_classes[i].iid));
10097 break;
10100 ok(hr == S_OK, "Failed to create interface for clsid %s, iid %s, hr %#lx\n",
10101 debugstr_guid(com_classes[i].clsid), debugstr_guid(com_classes[i].iid), hr);
10102 ok(!!iface, "iface == NULL\n");
10103 IUnknown_Release(iface);
10106 if (has_cui8)
10107 hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
10108 (void **)&uia_iface);
10109 else
10110 hr = CoCreateInstance(&CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
10111 (void **)&uia_iface);
10112 ok(hr == S_OK, "Failed to create IUIAutomation interface, hr %#lx\n", hr);
10113 ok(!!uia_iface, "uia_iface == NULL\n");
10115 test_CUIAutomation_value_conversion(uia_iface);
10116 test_ElementFromHandle(uia_iface, has_cui8);
10117 test_Element_GetPropertyValue(uia_iface);
10119 IUIAutomation_Release(uia_iface);
10120 CoUninitialize();
10124 * Once a process returns a UI Automation provider with
10125 * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This
10126 * messes with tests around COM initialization, so we run these tests in
10127 * separate processes.
10129 static void launch_test_process(const char *name, const char *test_name)
10131 PROCESS_INFORMATION proc;
10132 STARTUPINFOA startup;
10133 char cmdline[MAX_PATH];
10135 sprintf(cmdline, "\"%s\" uiautomation %s", name, test_name);
10136 memset(&startup, 0, sizeof(startup));
10137 startup.cb = sizeof(startup);
10138 CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
10139 wait_child_process(proc.hProcess);
10142 START_TEST(uiautomation)
10144 HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll");
10145 BOOL (WINAPI *pImmDisableIME)(DWORD);
10146 HMODULE hModuleImm32;
10147 char **argv;
10148 int argc;
10150 /* Make sure COM isn't initialized by imm32. */
10151 hModuleImm32 = LoadLibraryA("imm32.dll");
10152 if (hModuleImm32) {
10153 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME");
10154 if (pImmDisableIME)
10155 pImmDisableIME(0);
10157 pImmDisableIME = NULL;
10158 FreeLibrary(hModuleImm32);
10160 if (uia_dll)
10161 pUiaDisconnectProvider = (void *)GetProcAddress(uia_dll, "UiaDisconnectProvider");
10163 argc = winetest_get_mainargs(&argv);
10164 if (argc == 3)
10166 if (!strcmp(argv[2], "UiaNodeFromHandle"))
10167 test_UiaNodeFromHandle(argv[0]);
10168 else if (!strcmp(argv[2], "UiaNodeFromHandle_client_proc"))
10169 test_UiaNodeFromHandle_client_proc();
10170 else if (!strcmp(argv[2], "UiaRegisterProviderCallback"))
10171 test_UiaRegisterProviderCallback();
10173 FreeLibrary(uia_dll);
10174 return;
10177 test_UiaHostProviderFromHwnd();
10178 test_uia_reserved_value_ifaces();
10179 test_UiaLookupId();
10180 test_UiaNodeFromProvider();
10181 test_UiaGetPropertyValue();
10182 test_UiaGetRuntimeId();
10183 test_UiaHUiaNodeFromVariant();
10184 launch_test_process(argv[0], "UiaNodeFromHandle");
10185 launch_test_process(argv[0], "UiaRegisterProviderCallback");
10186 test_UiaGetUpdatedCache();
10187 test_UiaNavigate();
10188 test_UiaFind();
10189 test_CUIAutomation();
10190 if (uia_dll)
10192 pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible");
10193 if (pUiaProviderFromIAccessible)
10194 test_UiaProviderFromIAccessible();
10195 else
10196 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
10198 FreeLibrary(uia_dll);