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
25 #include "uiautomation.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) \
45 ok(expect_ ##func, "unexpected call " #func "\n"); \
49 #define CHECK_EXPECT(func) \
51 CHECK_EXPECT2(func); \
55 #define CHECK_CALLED(func) \
57 ok(called_ ## func, "expected " #func "\n"); \
58 expect_ ## func = called_ ## func = 0; \
61 #define CHECK_CALLED_MULTI(func, num) \
63 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
64 expect_ ## func = called_ ## func = 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
)
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
))
125 static BOOL
iface_cmp(IUnknown
*iface1
, IUnknown
*iface2
)
127 IUnknown
*unk1
, *unk2
;
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
);
139 static struct Accessible
141 IAccessible IAccessible_iface
;
142 IAccessible2 IAccessible2_iface
;
143 IOleWindow IOleWindow_iface
;
144 IServiceProvider IServiceProvider_iface
;
154 LONG left
, top
, width
, height
;
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
);
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
))
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
;
187 return E_NOINTERFACE
;
189 IAccessible_AddRef(iface
);
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");
211 static HRESULT WINAPI
Accessible_GetTypeInfo(IAccessible
*iface
, UINT iTInfo
,
212 LCID lcid
, ITypeInfo
**out_tinfo
)
214 ok(0, "unexpected call\n");
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");
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");
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
);
244 CHECK_EXPECT(Accessible_get_accParent
);
247 return IAccessible_QueryInterface(This
->parent
, &IID_IDispatch
, (void **)out_parent
);
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
);
264 CHECK_EXPECT(Accessible_get_accChildCount
);
266 if (This
->child_count
)
268 *out_count
= This
->child_count
;
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");
284 if (V_VT(&child_id
) != VT_I4
)
287 if (This
== &Accessible
)
289 switch (V_I4(&child_id
))
292 return IAccessible_QueryInterface(&This
->IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
294 /* Simple element children. */
300 return IAccessible_QueryInterface(&Accessible_child
.IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
303 return IAccessible_QueryInterface(&Accessible_child2
.IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
313 static HRESULT WINAPI
Accessible_get_accName(IAccessible
*iface
, VARIANT child_id
,
316 struct Accessible
*This
= impl_from_Accessible(iface
);
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
);
326 CHECK_EXPECT(Accessible_get_accName
);
330 *out_name
= SysAllocString(This
->name
);
337 static HRESULT WINAPI
Accessible_get_accValue(IAccessible
*iface
, VARIANT child_id
,
340 ok(0, "unexpected call\n");
344 static HRESULT WINAPI
Accessible_get_accDescription(IAccessible
*iface
, VARIANT child_id
,
345 BSTR
*out_description
)
347 ok(0, "unexpected call\n");
351 static HRESULT WINAPI
Accessible_get_accRole(IAccessible
*iface
, VARIANT child_id
,
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
);
363 CHECK_EXPECT(Accessible_get_accRole
);
367 V_VT(out_role
) = VT_I4
;
368 V_I4(out_role
) = This
->role
;
375 static HRESULT WINAPI
Accessible_get_accState(IAccessible
*iface
, VARIANT child_id
,
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
);
387 CHECK_EXPECT(Accessible_get_accState
);
389 if (V_VT(&child_id
) != VT_I4
)
392 if (This
== &Accessible
&& V_I4(&child_id
) != CHILDID_SELF
)
394 switch (V_I4(&child_id
))
397 V_VT(out_state
) = VT_I4
;
398 V_I4(out_state
) = STATE_SYSTEM_INVISIBLE
;
402 V_VT(out_state
) = VT_I4
;
403 V_I4(out_state
) = STATE_SYSTEM_FOCUSABLE
;
415 V_VT(out_state
) = VT_I4
;
416 V_I4(out_state
) = This
->state
;
423 static HRESULT WINAPI
Accessible_get_accHelp(IAccessible
*iface
, VARIANT child_id
,
426 ok(0, "unexpected call\n");
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");
437 static HRESULT WINAPI
Accessible_get_accKeyboardShortcut(IAccessible
*iface
, VARIANT child_id
,
438 BSTR
*out_kbd_shortcut
)
440 ok(0, "unexpected call\n");
444 static HRESULT WINAPI
Accessible_get_accFocus(IAccessible
*iface
, VARIANT
*pchild_id
)
446 ok(0, "unexpected call\n");
450 static HRESULT WINAPI
Accessible_get_accSelection(IAccessible
*iface
, VARIANT
*out_selection
)
452 ok(0, "unexpected call\n");
456 static HRESULT WINAPI
Accessible_get_accDefaultAction(IAccessible
*iface
, VARIANT child_id
,
457 BSTR
*out_default_action
)
459 ok(0, "unexpected call\n");
463 static HRESULT WINAPI
Accessible_accSelect(IAccessible
*iface
, LONG select_flags
,
466 ok(0, "unexpected call\n");
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
);
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
;
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
);
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
) &&
516 V_VT(out_var
) = VT_I4
;
517 V_I4(out_var
) = HandleToUlong(This
->acc_hwnd
);
523 static HRESULT WINAPI
Accessible_accHitTest(IAccessible
*iface
, LONG left
, LONG top
,
524 VARIANT
*out_child_id
)
526 ok(0, "unexpected call\n");
530 static HRESULT WINAPI
Accessible_accDoDefaultAction(IAccessible
*iface
, VARIANT child_id
)
532 ok(0, "unexpected call\n");
536 static HRESULT WINAPI
Accessible_put_accName(IAccessible
*iface
, VARIANT child_id
,
539 ok(0, "unexpected call\n");
543 static HRESULT WINAPI
Accessible_put_accValue(IAccessible
*iface
, VARIANT child_id
,
546 ok(0, "unexpected call\n");
550 static IAccessibleVtbl AccessibleVtbl
= {
551 Accessible_QueryInterface
,
554 Accessible_GetTypeInfoCount
,
555 Accessible_GetTypeInfo
,
556 Accessible_GetIDsOfNames
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
731 static HRESULT WINAPI
Accessible2_accSelect(IAccessible2
*iface
, LONG select_flags
,
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
,
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
,
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
,
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");
787 static HRESULT WINAPI
Accessible2_get_relation(IAccessible2
*iface
, LONG relation_idx
,
788 IAccessibleRelation
**out_relation
)
790 ok(0, "unexpected call\n");
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");
801 static HRESULT WINAPI
Accessible2_role(IAccessible2
*iface
, LONG
*out_role
)
803 ok(0, "unexpected call\n");
807 static HRESULT WINAPI
Accessible2_scrollTo(IAccessible2
*iface
, enum IA2ScrollType scroll_type
)
809 ok(0, "unexpected call\n");
813 static HRESULT WINAPI
Accessible2_scrollToPoint(IAccessible2
*iface
,
814 enum IA2CoordinateType coordinate_type
, LONG x
, LONG y
)
816 ok(0, "unexpected call\n");
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");
827 static HRESULT WINAPI
Accessible2_get_states(IAccessible2
*iface
, AccessibleStates
*out_states
)
829 ok(0, "unexpected call\n");
833 static HRESULT WINAPI
Accessible2_get_extendedRole(IAccessible2
*iface
, BSTR
*out_extended_role
)
835 ok(0, "unexpected call\n");
839 static HRESULT WINAPI
Accessible2_get_localizedExtendedRole(IAccessible2
*iface
,
840 BSTR
*out_localized_extended_role
)
842 ok(0, "unexpected call\n");
846 static HRESULT WINAPI
Accessible2_get_nExtendedStates(IAccessible2
*iface
, LONG
*out_nExtendedStates
)
848 ok(0, "unexpected call\n");
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");
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");
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
);
873 CHECK_EXPECT(Accessible_get_uniqueID
);
878 *out_unique_id
= This
->unique_id
;
885 static HRESULT WINAPI
Accessible2_get_windowHandle(IAccessible2
*iface
, HWND
*out_hwnd
)
887 ok(0, "unexpected call\n");
891 static HRESULT WINAPI
Accessible2_get_indexInParent(IAccessible2
*iface
, LONG
*out_idx_in_parent
)
893 ok(0, "unexpected call\n");
897 static HRESULT WINAPI
Accessible2_get_locale(IAccessible2
*iface
, IA2Locale
*out_locale
)
899 ok(0, "unexpected call\n");
903 static HRESULT WINAPI
Accessible2_get_attributes(IAccessible2
*iface
, BSTR
*out_attributes
)
905 ok(0, "unexpected call\n");
909 static const IAccessible2Vtbl Accessible2Vtbl
= {
910 Accessible2_QueryInterface
,
913 Accessible2_GetTypeInfoCount
,
914 Accessible2_GetTypeInfo
,
915 Accessible2_GetIDsOfNames
,
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
,
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
)
994 static const IOleWindowVtbl OleWindowVtbl
= {
995 OleWindow_QueryInterface
,
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
) &&
1032 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, obj
);
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
},
1049 { &ServiceProviderVtbl
},
1058 static struct Accessible Accessible2
=
1060 { &AccessibleVtbl
},
1061 { &Accessible2Vtbl
},
1063 { &ServiceProviderVtbl
},
1072 static struct Accessible Accessible_child
=
1074 { &AccessibleVtbl
},
1075 { &Accessible2Vtbl
},
1077 { &ServiceProviderVtbl
},
1079 &Accessible
.IAccessible_iface
,
1086 static struct Accessible Accessible_child2
=
1088 { &AccessibleVtbl
},
1089 { &Accessible2Vtbl
},
1091 { &ServiceProviderVtbl
},
1093 &Accessible
.IAccessible_iface
,
1100 struct Provider_prop_override
1106 struct Provider_value_pattern_data
1112 static struct Provider
1114 IRawElementProviderSimple IRawElementProviderSimple_iface
;
1115 IRawElementProviderFragment IRawElementProviderFragment_iface
;
1116 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface
;
1117 IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface
;
1118 IValueProvider IValueProvider_iface
;
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
;
1130 BOOL ret_invalid_prop_type
;
1133 DWORD last_call_tid
;
1134 BOOL ignore_hwnd_prop
;
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)
1156 if (!(sa
= SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(uia_i4_arr_prop_val
))))
1159 for (idx
= 0; idx
< ARRAY_SIZE(uia_i4_arr_prop_val
); idx
++)
1160 SafeArrayPutElement(sa
, &idx
, (void *)&uia_i4_arr_prop_val
[idx
]);
1165 static SAFEARRAY
*create_r8_safearray(void)
1170 if (!(sa
= SafeArrayCreateVector(VT_R8
, 0, ARRAY_SIZE(uia_r8_arr_prop_val
))))
1173 for (idx
= 0; idx
< ARRAY_SIZE(uia_r8_arr_prop_val
); idx
++)
1174 SafeArrayPutElement(sa
, &idx
, (void *)&uia_r8_arr_prop_val
[idx
]);
1179 static SAFEARRAY
*create_unk_safearray(void)
1184 if (!(sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, ARRAY_SIZE(uia_unk_arr_prop_val
))))
1187 for (idx
= 0; idx
< ARRAY_SIZE(uia_unk_arr_prop_val
); idx
++)
1188 SafeArrayPutElement(sa
, &idx
, (void *)uia_unk_arr_prop_val
[idx
]);
1194 PROV_GET_PROVIDER_OPTIONS
,
1195 PROV_GET_PATTERN_PROV
,
1196 PROV_GET_PROPERTY_VALUE
,
1197 PROV_GET_HOST_RAW_ELEMENT_PROVIDER
,
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",
1209 "get_HostRawElementProvider",
1213 "get_BoundingRectangle",
1214 "GetOverrideProviderForHwnd",
1217 static const char *get_prov_method_str(int method
)
1219 if (method
>= ARRAY_SIZE(prov_method_str
))
1222 return prov_method_str
[method
];
1226 METHOD_OPTIONAL
= 0x01,
1230 struct prov_method_sequence
{
1231 struct Provider
*prov
;
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
);
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};
1284 sequence
= HeapAlloc(GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
));
1286 if (sequence_cnt
== sequence_size
)
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);
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
));
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
));
1329 else if (expected
->flags
& METHOD_OPTIONAL
)
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
));
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
));
1352 if (expected
->prov
|| actual
->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
));
1358 ok_( file
, line
)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual
->prov
->prov_name
,
1359 get_prov_method_str(actual
->method
));
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
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
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>"
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
);
1411 str
+= wcslen(prov_type
);
1412 str2
= wcschr(str
, L
'(');
1413 lstrcpynW(out_name
, str
, ((str2
- str
)));
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
)
1426 wsprintfW(buf
, L
"%s(parent link):", prov_type
);
1428 wsprintfW(buf
, L
"%s:", prov_type
);
1430 if (!get_provider_desc(prov_desc
, buf
, buf
))
1433 wsprintfW(buf
, L
"%s:", prov_type
);
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
));
1445 ok_(file
, line
)(0, "expected parent link provider %s\n", debugstr_w(prov_type
));
1447 ok_(file
, line
)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type
));
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
;
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:");
1474 str
+= wcslen(L
"providerId:");
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
;
1496 wsprintfW(buf
, L
"%s:Nested ", prov_type
);
1498 wsprintfW(buf
, L
"%s(parent link):Nested ", prov_type
);
1499 str
= wcsstr(prov_desc
, buf
);
1500 /* Check with and without parent-link. */
1508 str2
= wcschr(str
, L
']');
1509 /* We want to include the ']' character, so + 2. */
1510 lstrcpynW(out_desc
, str
, ((str2
- str
) + 2));
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
;
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
++)
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
);
1555 if (IsEqualIID(riid
, &IID_IRawElementProviderSimple
) || IsEqualIID(riid
, &IID_IUnknown
))
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
;
1566 return E_NOINTERFACE
;
1568 IRawElementProviderSimple_AddRef(iface
);
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();
1595 if (This
->prov_opts
)
1597 *ret_val
= This
->prov_opts
;
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();
1617 case UIA_ValuePatternId
:
1618 if (This
->value_pattern_data
.is_supported
)
1619 *ret_val
= (IUnknown
*)iface
;
1627 IUnknown_AddRef(*ret_val
);
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
)
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
;
1656 VariantInit(ret_val
);
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
);
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
;
1692 V_VT(ret_val
) = VT_I4
;
1693 V_I4(ret_val
) = uia_i4_prop_val
;
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
;
1705 V_VT(ret_val
) = VT_R8
;
1706 V_R8(ret_val
) = uia_r8_prop_val
;
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
;
1731 V_VT(ret_val
) = VT_BSTR
;
1732 V_BSTR(ret_val
) = SysAllocString(uia_bstr_prop_str
);
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
;
1755 V_VT(ret_val
) = VT_BOOL
;
1756 V_BOOL(ret_val
) = VARIANT_TRUE
;
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();
1769 V_VT(ret_val
) = VT_ARRAY
| VT_I4
;
1770 V_ARRAY(ret_val
) = create_i4_safearray();
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();
1783 V_VT(ret_val
) = VT_ARRAY
| VT_R8
;
1784 V_ARRAY(ret_val
) = create_r8_safearray();
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
;
1796 V_VT(ret_val
) = VT_UNKNOWN
;
1797 V_UNKNOWN(ret_val
) = (IUnknown
*)&Provider_child
.IRawElementProviderSimple_iface
;
1798 IUnknown_AddRef(V_UNKNOWN(ret_val
));
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();
1814 V_VT(ret_val
) = VT_UNKNOWN
| VT_ARRAY
;
1815 V_ARRAY(ret_val
) = create_unk_safearray();
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
);
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();
1848 return UiaHostProviderFromHwnd(This
->hwnd
, ret_val
);
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
,
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();
1900 case NavigateDirection_Parent
:
1901 *ret_val
= This
->parent
;
1904 case NavigateDirection_NextSibling
:
1905 *ret_val
= This
->next_sibling
;
1908 case NavigateDirection_PreviousSibling
:
1909 *ret_val
= This
->prev_sibling
;
1912 case NavigateDirection_FirstChild
:
1913 *ret_val
= This
->first_child
;
1916 case NavigateDirection_LastChild
:
1917 *ret_val
= This
->last_child
;
1921 trace("Invalid navigate direction %d\n", direction
);
1926 IRawElementProviderFragment_AddRef(*ret_val
);
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();
1942 if (This
->runtime_id
[0] || This
->runtime_id
[1])
1947 if (!(sa
= SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(This
->runtime_id
))))
1950 for (idx
= 0; idx
< ARRAY_SIZE(This
->runtime_id
); idx
++)
1951 SafeArrayPutElement(sa
, &idx
, (void *)&This
->runtime_id
[idx
]);
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
;
1973 static HRESULT WINAPI
ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment
*iface
,
1974 SAFEARRAY
**ret_val
)
1976 ok(0, "unexpected call\n");
1981 static HRESULT WINAPI
ProviderFragment_SetFocus(IRawElementProviderFragment
*iface
)
1983 ok(0, "unexpected call\n");
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();
1998 if (This
->frag_root
)
2000 *ret_val
= This
->frag_root
;
2001 IRawElementProviderFragmentRoot_AddRef(This
->frag_root
);
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
,
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");
2050 static HRESULT WINAPI
ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot
*iface
,
2051 IRawElementProviderFragment
**ret_val
)
2053 ok(0, "unexpected call\n");
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
,
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
);
2097 if (This
->override_hwnd
== hwnd
)
2099 return IRawElementProviderSimple_QueryInterface(&Provider_override
.IRawElementProviderSimple_iface
,
2100 &IID_IRawElementProviderSimple
, (void **)ret_val
);
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
,
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");
2143 static HRESULT WINAPI
ProviderValuePattern_get_Value(IValueProvider
*iface
, BSTR
*ret_val
)
2145 ok(0, "unexpected call\n");
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
;
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
},
2178 &Provider_child
.IRawElementProviderFragment_iface
, &Provider_child2
.IRawElementProviderFragment_iface
,
2182 static struct Provider Provider2
=
2184 { &ProviderSimpleVtbl
},
2185 { &ProviderFragmentVtbl
},
2186 { &ProviderFragmentRootVtbl
},
2187 { &ProviderHwndOverrideVtbl
},
2188 { &ProviderValuePatternVtbl
},
2197 static struct Provider Provider_child
=
2199 { &ProviderSimpleVtbl
},
2200 { &ProviderFragmentVtbl
},
2201 { &ProviderFragmentRootVtbl
},
2202 { &ProviderHwndOverrideVtbl
},
2203 { &ProviderValuePatternVtbl
},
2206 &Provider
.IRawElementProviderFragment_iface
, &Provider
.IRawElementProviderFragmentRoot_iface
,
2207 NULL
, &Provider_child2
.IRawElementProviderFragment_iface
,
2209 ProviderOptions_ServerSideProvider
, 0, 0,
2212 static struct Provider Provider_child2
=
2214 { &ProviderSimpleVtbl
},
2215 { &ProviderFragmentVtbl
},
2216 { &ProviderFragmentRootVtbl
},
2217 { &ProviderHwndOverrideVtbl
},
2218 { &ProviderValuePatternVtbl
},
2221 &Provider
.IRawElementProviderFragment_iface
, &Provider
.IRawElementProviderFragmentRoot_iface
,
2222 &Provider_child
.IRawElementProviderFragment_iface
, NULL
,
2224 ProviderOptions_ServerSideProvider
, 0, 0,
2227 static struct Provider Provider_hwnd
=
2229 { &ProviderSimpleVtbl
},
2230 { &ProviderFragmentVtbl
},
2231 { &ProviderFragmentRootVtbl
},
2232 { &ProviderHwndOverrideVtbl
},
2233 { &ProviderValuePatternVtbl
},
2239 ProviderOptions_ClientSideProvider
, 0, 0,
2242 static struct Provider Provider_nc
=
2244 { &ProviderSimpleVtbl
},
2245 { &ProviderFragmentVtbl
},
2246 { &ProviderFragmentRootVtbl
},
2247 { &ProviderHwndOverrideVtbl
},
2248 { &ProviderValuePatternVtbl
},
2254 ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
,
2258 static struct Provider Provider_proxy
=
2260 { &ProviderSimpleVtbl
},
2261 { &ProviderFragmentVtbl
},
2262 { &ProviderFragmentRootVtbl
},
2263 { &ProviderHwndOverrideVtbl
},
2264 { &ProviderValuePatternVtbl
},
2270 ProviderOptions_ClientSideProvider
,
2274 static struct Provider Provider_proxy2
=
2276 { &ProviderSimpleVtbl
},
2277 { &ProviderFragmentVtbl
},
2278 { &ProviderFragmentRootVtbl
},
2279 { &ProviderHwndOverrideVtbl
},
2280 { &ProviderValuePatternVtbl
},
2286 ProviderOptions_ClientSideProvider
,
2290 static struct Provider Provider_override
=
2292 { &ProviderSimpleVtbl
},
2293 { &ProviderFragmentVtbl
},
2294 { &ProviderFragmentRootVtbl
},
2295 { &ProviderHwndOverrideVtbl
},
2296 { &ProviderValuePatternVtbl
},
2298 "Provider_override",
2302 ProviderOptions_ServerSideProvider
| ProviderOptions_OverrideProvider
,
2306 #define DEFINE_PROVIDER(name) \
2307 static struct Provider Provider_ ## name = \
2309 { &ProviderSimpleVtbl }, \
2310 { &ProviderFragmentVtbl }, \
2311 { &ProviderFragmentRootVtbl }, \
2312 { &ProviderHwndOverrideVtbl }, \
2313 { &ProviderValuePatternVtbl }, \
2315 "Provider_" # name "", \
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
)
2338 if (lParam
== (DWORD
)OBJID_CLIENT
)
2340 CHECK_EXPECT(winproc_GETOBJECT_CLIENT
);
2342 return LresultFromObject(&IID_IAccessible
, wParam
, (IUnknown
*)acc_client
);
2346 else if (lParam
== UiaRootObjectId
)
2348 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot
);
2350 return UiaReturnRawElementProvider(hwnd
, wParam
, lParam
, prov_root
);
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
)
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
);
2385 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2388 static void test_UiaHostProviderFromHwnd(void)
2390 IRawElementProviderSimple
*p
, *p2
;
2391 enum ProviderOptions prov_opt
;
2399 cls
.lpfnWndProc
= test_wnd_proc
;
2402 cls
.hInstance
= GetModuleHandleA(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
);
2425 hr
= UiaHostProviderFromHwnd(hwnd
, &p
);
2426 ok(hr
== S_OK
, "Failed to get host provider, hr %#lx.\n", hr
);
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
));
2448 /* No patterns are implemented on the HWND Host provider. */
2449 for (i
= UIA_InvokePatternId
; i
< (UIA_CustomNavigationPatternId
+ 1); i
++)
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
));
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
;
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
);
2517 static void test_uia_reserved_value_ifaces(void)
2519 IUnknown
*unk_ns
, *unk_ns2
, *unk_ma
, *unk_ma2
;
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
);
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
);
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
)
2610 while(PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
2612 TranslateMessage(&msg
);
2613 DispatchMessageW(&msg
);
2616 CloseHandle(thread
);
2621 struct msaa_role_uia_type
{
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
{
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
)
2711 acc
->child_count
= child_count
;
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
;
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");
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;
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;
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;
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;
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
,
2884 ILegacyIAccessibleProvider
*accprov
;
2885 IAccessible
*accessible
;
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
;
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
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
);
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
);
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
);
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
);
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
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
;
3352 /* MSAA role to UIA control type test. */
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
);
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
));
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
);
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
));
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
);
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
);
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
);
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
)));
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
)));
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
;
3488 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3490 cls
.lpfnWndProc
= test_wnd_proc
;
3493 cls
.hInstance
= GetModuleHandleA(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
);
3548 /* Skip tests on Win10v1507. */
3549 if (called_winproc_GETOBJECT_CLIENT
)
3551 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
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
));
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
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
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;
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;
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
);
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;
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;
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;
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;
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. */
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
);
4074 test_uia_prov_from_acc_properties();
4075 test_uia_prov_from_acc_navigation();
4076 test_uia_prov_from_acc_ia2();
4079 DestroyWindow(hwnd
);
4080 UnregisterClassA("pUiaProviderFromIAccessible class", NULL
);
4081 Accessible
.acc_hwnd
= NULL
;
4082 Accessible
.ow_hwnd
= NULL
;
4085 struct uia_lookup_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
;
4401 const struct uia_lookup_id
*ids
;
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
) },
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
);
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
));
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
},
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 */
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 */
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 */
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 */
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 */
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 */
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
},
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
;
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
);
4611 static void test_uia_node_from_prov_com_threading(void)
4617 /* Test ProviderOptions_UseComThreading. */
4618 Provider
.hwnd
= 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.
4630 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
4631 UiaNodeRelease(node
);
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
)
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;
4661 static void test_UiaNodeFromProvider(void)
4671 cls
.lpfnWndProc
= test_wnd_proc
;
4674 cls
.hInstance
= GetModuleHandleA(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
);
4715 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
4716 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
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
);
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
);
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
;
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
);
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
);
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
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
);
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
);
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
);
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
);
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
);
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
);
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
);
4902 DestroyWindow(hwnd
);
4903 UnregisterClassA("UiaNodeFromProvider class", 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
},
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
},
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
},
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
},
4958 static const struct prov_method_sequence get_pattern_prop_seq
[] = {
4959 { &Provider
, PROV_GET_PATTERN_PROV
},
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
},
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
},
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
},
5005 static const struct prov_method_sequence get_empty_bounding_rect_seq
[] = {
5006 { &Provider_child
, FRAG_GET_BOUNDING_RECT
},
5010 static void set_uia_rect(struct UiaRect
*rect
, double left
, double top
, double width
, double height
)
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
;
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
))
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
)
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
);
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
));
5097 ok(check_variant_bool(v
, TRUE
), "Unexpected BOOL %#x\n", V_BOOL(v
));
5098 ok_method_sequence(get_prop_seq
, NULL
);
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
));
5107 ok(V_I4(v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(v
));
5108 ok_method_sequence(get_prop_seq
, NULL
);
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
++)
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
);
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
);
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
++)
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
);
5142 case UIAutomationType_Element
:
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
);
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
);
5165 ok(V_VT(v
) == VT_I8
, "Unexpected VT %d\n", V_VT(v
));
5166 tmp_node
= (HUIANODE
)V_I8(v
);
5168 ok(V_VT(v
) == VT_I4
, "Unexpected VT %d\n", V_VT(v
));
5169 tmp_node
= (HUIANODE
)V_I4(v
);
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
);
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
))
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
++)
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
);
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
);
5224 struct uia_element_property
{
5225 const GUID
*prop_guid
;
5226 enum UIAutomationType type
;
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
;
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
;
5318 prop_id
= UiaLookupId(AutomationIdentifierType_Property
, elem_prop
->prop_guid
);
5321 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop
->prop_guid
));
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
);
5340 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", 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
));
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
);
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
);
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");
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
);
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
));
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
);
5421 IUnknown_Release(unk_ns
);
5425 static const struct prov_method_sequence get_runtime_id1
[] = {
5426 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5430 static const struct prov_method_sequence get_runtime_id2
[] = {
5431 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5432 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
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
},
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
},
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
},
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
;
5486 cls
.lpfnWndProc
= test_wnd_proc
;
5489 cls
.hInstance
= GetModuleHandleA(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
);
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
);
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
));
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;
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
++)
5623 Provider
.prov_opts
= root_prov_opts
[i
];
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
);
5636 ok(rt_id
[2] != tmp
, "Expected different runtime id value from previous\n");
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;
5662 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5663 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx\n", 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
);
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
);
5691 static const struct prov_method_sequence node_from_var_seq
[] = {
5692 NODE_CREATE_SEQ(&Provider
),
5696 static void test_UiaHUiaNodeFromVariant(void)
5698 HUIANODE node
, node2
;
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;
5711 hr
= UiaHUiaNodeFromVariant(&v
, &node
);
5712 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5713 ok(!node
, "node != NULL\n");
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
);
5733 IUnknown_Release((IUnknown
*)node
);
5736 node2
= (void *)0xdeadbeef;
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;
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");
5750 node2
= (void *)0xdeadbeef;
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;
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");
5765 UiaNodeRelease(node
);
5768 static const struct prov_method_sequence node_from_hwnd1
[] = {
5769 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
},
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
},
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
},
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
},
5960 static void test_UiaNodeFromHandle_client_proc(void)
5962 APTTYPEQUALIFIER apt_qualifier
;
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
);
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
);
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
);
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
);
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
;
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
);
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
);
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
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
);
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
);
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
);
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
6141 if (Provider_child
.ref
!= 1)
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
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
);
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
);
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)
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)
6190 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
6192 if (!pUiaDisconnectProvider
)
6194 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
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
);
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
);
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
);
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
);
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
);
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
);
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");
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
;
6363 cls
.lpfnWndProc
= test_wnd_proc
;
6366 cls
.hInstance
= GetModuleHandleA(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. */
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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"))
6595 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
6597 todo_wine
ok(hr
== S_OK
|| broken(hr
== CO_E_NOTINITIALIZED
), "Unexpected hr %#lx\n", 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
)
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
)
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
));
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");
6654 DestroyWindow(hwnd
);
6655 UnregisterClassA("UiaNodeFromHandle class", 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 */
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 */
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 */
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 */
6715 static const struct prov_method_sequence reg_prov_cb5
[] = {
6716 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
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 */
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 */
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 */
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. */
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
},
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 */
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 */
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 */
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
;
6883 case ProviderType_BaseHwnd
:
6884 CHECK_EXPECT(prov_callback_base_hwnd
);
6885 elprov
= base_hwnd_prov
;
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
;
6901 case ProviderType_NonClientArea
:
6902 CHECK_EXPECT(prov_callback_nonclient
);
6915 sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, 1);
6917 SafeArrayPutElement(sa
, &idx
, (void *)elprov
);
6925 static void test_UiaRegisterProviderCallback(void)
6934 cls
.lpfnWndProc
= test_wnd_proc
;
6937 cls
.hInstance
= GetModuleHandleA(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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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.
7144 * Nonclient 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
);
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
);
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
);
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
);
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
);
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
);
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
;
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
;
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
{
7390 const WCHAR
*prov_type
[MAX_NODE_PROVIDERS
];
7391 const WCHAR
*prov_name
[MAX_NODE_PROVIDERS
];
7392 BOOL parent_link
[MAX_NODE_PROVIDERS
];
7396 static void init_node_provider_desc(struct node_provider_desc
*desc
, DWORD pid
, HWND hwnd
)
7398 memset(desc
, 0, sizeof(*desc
));
7403 static void add_provider_desc(struct node_provider_desc
*desc
, const WCHAR
*prov_type
, const WCHAR
*prov_name
,
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
;
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
)
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
)
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
);
7476 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7477 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7479 test_node_provider_desc_(&exp_node_desc
[i
], V_BSTR(&v
), file
, line
);
7482 UiaNodeRelease(node
);
7486 static const struct prov_method_sequence cache_req_seq1
[] = {
7487 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ProviderDescriptionPropertyId. */
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 */
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. */
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. */
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 */
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 */
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
;
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
);
7570 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
7571 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
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
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
);
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(¬_cond
, (struct UiaCondition
*)&UiaFalseCondition
);
7804 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_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(¬_cond
, (struct UiaCondition
*)&UiaTrueCondition
);
7824 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_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
);
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
);
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;
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
);
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;
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
);
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
);
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
;
8232 prov
->parent
= &parent
->IRawElementProviderFragment_iface
;
8234 prov
->frag_root
= &frag_root
->IRawElementProviderFragmentRoot_iface
;
8236 prov
->prev_sibling
= &prev_sibling
->IRawElementProviderFragment_iface
;
8238 prov
->next_sibling
= &next_sibling
->IRawElementProviderFragment_iface
;
8240 prov
->first_child
= &first_child
->IRawElementProviderFragment_iface
;
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
;
8258 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
8260 cls
.lpfnWndProc
= test_wnd_proc
;
8263 cls
.hInstance
= GetModuleHandleA(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
,
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
,
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
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
);
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
);
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
);
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
);
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
;
8760 UiaRegisterProviderCallback(NULL
);
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
;
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
;
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
;
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
);
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
++)
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
;
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
);
9223 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
9224 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
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;
9258 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9260 for (i
= 0; i
< exp_elems
[0]; 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;
9293 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9295 for (i
= 0; i
< exp_elems
[0]; 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;
9328 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9330 for (i
= 0; i
< exp_elems
[0]; 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
++)
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;
9405 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9407 for (i
= 0; i
< exp_elems
[0]; 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
++)
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.
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
);
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;
9498 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9500 for (i
= 0; i
< exp_elems
[0]; 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;
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
);
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;
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
++)
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.
9587 V_BOOL(&v
) = VARIANT_FALSE
;
9588 set_property_condition(&prop_cond
[0], UIA_IsContentElementPropertyId
, &v
, 0);
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;
9616 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9618 for (i
= 0; i
< exp_elems
[0]; 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
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
);
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;
9668 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9670 for (i
= 0; i
< exp_elems
[0]; 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
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
);
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;
9715 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9717 for (i
= 0; i
< exp_elems
[0]; 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
);
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
;
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
);
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
);
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
);
9795 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
9800 ok_method_sequence(node_from_hwnd2
, "create_test_element");
9801 UiaRegisterProviderCallback(NULL
);
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
;
9813 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, FALSE
);
9814 hr
= IUIAutomationElement_QueryInterface(element
, &IID_IUIAutomationElement2
, (void **)&element_2
);
9817 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9818 ok(!!element_2
, "element_2 == NULL\n");
9819 IUIAutomationElement2_Release(element_2
);
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
);
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
;
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
);
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
)
9863 Provider
.ret_invalid_prop_type
= FALSE
;
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
));
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
);
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
));
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
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. */
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.
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
);
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");
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");
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
);
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
));
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
);
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
;
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
{
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
;
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
,
10085 if ((com_classes
[i
].clsid
== &CLSID_CUIAutomation8
) && (hr
== REGDB_E_CLASSNOTREG
))
10087 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
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
));
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
);
10107 hr
= CoCreateInstance(&CLSID_CUIAutomation8
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUIAutomation
,
10108 (void **)&uia_iface
);
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
);
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
;
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
)
10157 pImmDisableIME
= NULL
;
10158 FreeLibrary(hModuleImm32
);
10161 pUiaDisconnectProvider
= (void *)GetProcAddress(uia_dll
, "UiaDisconnectProvider");
10163 argc
= winetest_get_mainargs(&argv
);
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
);
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();
10189 test_CUIAutomation();
10192 pUiaProviderFromIAccessible
= (void *)GetProcAddress(uia_dll
, "UiaProviderFromIAccessible");
10193 if (pUiaProviderFromIAccessible
)
10194 test_UiaProviderFromIAccessible();
10196 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
10198 FreeLibrary(uia_dll
);