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
26 #include "uiautomation.h"
28 #include "wine/iaccessible2.h"
30 #include "wine/test.h"
32 static HRESULT (WINAPI
*pUiaProviderFromIAccessible
)(IAccessible
*, long, DWORD
, IRawElementProviderSimple
**);
33 static HRESULT (WINAPI
*pUiaDisconnectProvider
)(IRawElementProviderSimple
*);
35 #define DEFINE_EXPECT(func) \
36 static int expect_ ## func = 0, called_ ## func = 0
38 #define SET_EXPECT(func) \
39 do { called_ ## func = 0; expect_ ## func = 1; } while(0)
41 #define SET_EXPECT_MULTI(func, num) \
42 do { called_ ## func = 0; expect_ ## func = num; } while(0)
44 #define CHECK_EXPECT2(func) \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
50 #define CHECK_EXPECT(func) \
52 CHECK_EXPECT2(func); \
56 #define CHECK_CALLED(func) \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = 0; \
62 #define CHECK_CALLED_MULTI(func, num) \
64 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
65 expect_ ## func = called_ ## func = 0; \
68 #define NAVDIR_INTERNAL_HWND 10
69 #define UIA_RUNTIME_ID_PREFIX 42
71 DEFINE_EXPECT(winproc_GETOBJECT_CLIENT
);
72 DEFINE_EXPECT(prov_callback_base_hwnd
);
73 DEFINE_EXPECT(prov_callback_nonclient
);
74 DEFINE_EXPECT(prov_callback_proxy
);
75 DEFINE_EXPECT(prov_callback_parent_proxy
);
76 DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot
);
77 DEFINE_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
78 DEFINE_EXPECT(Accessible_accNavigate
);
79 DEFINE_EXPECT(Accessible_get_accParent
);
80 DEFINE_EXPECT(Accessible_get_accChildCount
);
81 DEFINE_EXPECT(Accessible_get_accName
);
82 DEFINE_EXPECT(Accessible_get_accRole
);
83 DEFINE_EXPECT(Accessible_get_accState
);
84 DEFINE_EXPECT(Accessible_accLocation
);
85 DEFINE_EXPECT(Accessible_get_accChild
);
86 DEFINE_EXPECT(Accessible_get_uniqueID
);
87 DEFINE_EXPECT(Accessible2_get_accParent
);
88 DEFINE_EXPECT(Accessible2_get_accChildCount
);
89 DEFINE_EXPECT(Accessible2_get_accName
);
90 DEFINE_EXPECT(Accessible2_get_accRole
);
91 DEFINE_EXPECT(Accessible2_get_accState
);
92 DEFINE_EXPECT(Accessible2_accLocation
);
93 DEFINE_EXPECT(Accessible_QI_IAccIdentity
);
94 DEFINE_EXPECT(Accessible2_QI_IAccIdentity
);
95 DEFINE_EXPECT(Accessible2_get_uniqueID
);
96 DEFINE_EXPECT(Accessible_child_accNavigate
);
97 DEFINE_EXPECT(Accessible_child_get_accParent
);
98 DEFINE_EXPECT(Accessible_child_get_accChildCount
);
99 DEFINE_EXPECT(Accessible_child_get_accName
);
100 DEFINE_EXPECT(Accessible_child_get_accRole
);
101 DEFINE_EXPECT(Accessible_child_get_accState
);
102 DEFINE_EXPECT(Accessible_child_accLocation
);
103 DEFINE_EXPECT(Accessible_child2_accNavigate
);
104 DEFINE_EXPECT(Accessible_child2_get_accParent
);
105 DEFINE_EXPECT(Accessible_child2_get_accChildCount
);
106 DEFINE_EXPECT(Accessible_child2_get_accName
);
107 DEFINE_EXPECT(Accessible_child2_get_accRole
);
108 DEFINE_EXPECT(Accessible_child2_get_accState
);
109 DEFINE_EXPECT(Accessible_child2_accLocation
);
111 static BOOL
check_variant_i4(VARIANT
*v
, int val
)
113 if (V_VT(v
) == VT_I4
&& V_I4(v
) == val
)
119 static BOOL
check_variant_bool(VARIANT
*v
, BOOL val
)
121 if (V_VT(v
) == VT_BOOL
&& V_BOOL(v
) == (val
? VARIANT_TRUE
: VARIANT_FALSE
))
127 static void variant_init_bool(VARIANT
*v
, BOOL val
)
130 V_BOOL(v
) = val
? VARIANT_TRUE
: VARIANT_FALSE
;
133 static BOOL
iface_cmp(IUnknown
*iface1
, IUnknown
*iface2
)
135 IUnknown
*unk1
, *unk2
;
138 IUnknown_QueryInterface(iface1
, &IID_IUnknown
, (void**)&unk1
);
139 IUnknown_QueryInterface(iface2
, &IID_IUnknown
, (void**)&unk2
);
142 IUnknown_Release(unk1
);
143 IUnknown_Release(unk2
);
147 static struct Accessible
149 IAccessible IAccessible_iface
;
150 IAccessible2 IAccessible2_iface
;
151 IOleWindow IOleWindow_iface
;
152 IServiceProvider IServiceProvider_iface
;
162 LONG left
, top
, width
, height
;
165 } Accessible
, Accessible2
, Accessible_child
, Accessible_child2
;
167 static inline struct Accessible
* impl_from_Accessible(IAccessible
*iface
)
169 return CONTAINING_RECORD(iface
, struct Accessible
, IAccessible_iface
);
172 static HRESULT WINAPI
Accessible_QueryInterface(IAccessible
*iface
, REFIID riid
, void **obj
)
174 struct Accessible
*This
= impl_from_Accessible(iface
);
177 if (IsEqualIID(riid
, &IID_IAccIdentity
))
179 if (This
== &Accessible2
)
180 CHECK_EXPECT(Accessible2_QI_IAccIdentity
);
181 else if (This
== &Accessible
)
182 CHECK_EXPECT(Accessible_QI_IAccIdentity
);
184 ok(This
== &Accessible2
|| This
== &Accessible
, "unexpected call\n");
185 return E_NOINTERFACE
;
188 if (IsEqualIID(riid
, &IID_IUnknown
) || IsEqualIID(riid
, &IID_IDispatch
) ||
189 IsEqualIID(riid
, &IID_IAccessible
))
191 else if (IsEqualIID(riid
, &IID_IOleWindow
))
192 *obj
= &This
->IOleWindow_iface
;
193 else if (IsEqualIID(riid
, &IID_IServiceProvider
))
194 *obj
= &This
->IServiceProvider_iface
;
195 else if (IsEqualIID(riid
, &IID_IAccessible2
) && This
->enable_ia2
)
196 *obj
= &This
->IAccessible2_iface
;
198 return E_NOINTERFACE
;
200 IAccessible_AddRef(iface
);
204 static ULONG WINAPI
Accessible_AddRef(IAccessible
*iface
)
206 struct Accessible
*This
= impl_from_Accessible(iface
);
207 return InterlockedIncrement(&This
->ref
);
210 static ULONG WINAPI
Accessible_Release(IAccessible
*iface
)
212 struct Accessible
*This
= impl_from_Accessible(iface
);
213 return InterlockedDecrement(&This
->ref
);
216 static HRESULT WINAPI
Accessible_GetTypeInfoCount(IAccessible
*iface
, UINT
*pctinfo
)
218 ok(0, "unexpected call\n");
222 static HRESULT WINAPI
Accessible_GetTypeInfo(IAccessible
*iface
, UINT iTInfo
,
223 LCID lcid
, ITypeInfo
**out_tinfo
)
225 ok(0, "unexpected call\n");
229 static HRESULT WINAPI
Accessible_GetIDsOfNames(IAccessible
*iface
, REFIID riid
,
230 LPOLESTR
*rg_names
, UINT name_count
, LCID lcid
, DISPID
*rg_disp_id
)
232 ok(0, "unexpected call\n");
236 static HRESULT WINAPI
Accessible_Invoke(IAccessible
*iface
, DISPID disp_id_member
,
237 REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
*disp_params
,
238 VARIANT
*var_result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
240 ok(0, "unexpected call\n");
244 static HRESULT WINAPI
Accessible_get_accParent(IAccessible
*iface
, IDispatch
**out_parent
)
246 struct Accessible
*This
= impl_from_Accessible(iface
);
248 if (This
== &Accessible_child
)
249 CHECK_EXPECT(Accessible_child_get_accParent
);
250 else if (This
== &Accessible_child2
)
251 CHECK_EXPECT(Accessible_child2_get_accParent
);
252 else if (This
== &Accessible2
)
253 CHECK_EXPECT(Accessible2_get_accParent
);
255 CHECK_EXPECT(Accessible_get_accParent
);
258 return IAccessible_QueryInterface(This
->parent
, &IID_IDispatch
, (void **)out_parent
);
264 static HRESULT WINAPI
Accessible_get_accChildCount(IAccessible
*iface
, LONG
*out_count
)
266 struct Accessible
*This
= impl_from_Accessible(iface
);
268 if (This
== &Accessible_child
)
269 CHECK_EXPECT(Accessible_child_get_accChildCount
);
270 else if (This
== &Accessible_child2
)
271 CHECK_EXPECT(Accessible_child2_get_accChildCount
);
272 else if (This
== &Accessible2
)
273 CHECK_EXPECT(Accessible2_get_accChildCount
);
275 CHECK_EXPECT(Accessible_get_accChildCount
);
277 if (This
->child_count
)
279 *out_count
= This
->child_count
;
286 static HRESULT WINAPI
Accessible_get_accChild(IAccessible
*iface
, VARIANT child_id
,
287 IDispatch
**out_child
)
289 struct Accessible
*This
= impl_from_Accessible(iface
);
291 CHECK_EXPECT(Accessible_get_accChild
);
292 ok(This
== &Accessible
, "unexpected call\n");
295 if (V_VT(&child_id
) != VT_I4
)
298 if (This
== &Accessible
)
300 switch (V_I4(&child_id
))
303 return IAccessible_QueryInterface(&This
->IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
305 /* Simple element children. */
311 return IAccessible_QueryInterface(&Accessible_child
.IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
314 return IAccessible_QueryInterface(&Accessible_child2
.IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
324 static HRESULT WINAPI
Accessible_get_accName(IAccessible
*iface
, VARIANT child_id
,
327 struct Accessible
*This
= impl_from_Accessible(iface
);
330 if (This
== &Accessible_child
)
331 CHECK_EXPECT(Accessible_child_get_accName
);
332 else if (This
== &Accessible_child2
)
333 CHECK_EXPECT(Accessible_child2_get_accName
);
334 else if (This
== &Accessible2
)
335 CHECK_EXPECT(Accessible2_get_accName
);
337 CHECK_EXPECT(Accessible_get_accName
);
341 *out_name
= SysAllocString(This
->name
);
348 static HRESULT WINAPI
Accessible_get_accValue(IAccessible
*iface
, VARIANT child_id
,
351 ok(0, "unexpected call\n");
355 static HRESULT WINAPI
Accessible_get_accDescription(IAccessible
*iface
, VARIANT child_id
,
356 BSTR
*out_description
)
358 ok(0, "unexpected call\n");
362 static HRESULT WINAPI
Accessible_get_accRole(IAccessible
*iface
, VARIANT child_id
,
365 struct Accessible
*This
= impl_from_Accessible(iface
);
367 if (This
== &Accessible_child
)
368 CHECK_EXPECT(Accessible_child_get_accRole
);
369 else if (This
== &Accessible_child2
)
370 CHECK_EXPECT(Accessible_child2_get_accRole
);
371 else if (This
== &Accessible2
)
372 CHECK_EXPECT(Accessible2_get_accRole
);
374 CHECK_EXPECT(Accessible_get_accRole
);
378 V_VT(out_role
) = VT_I4
;
379 V_I4(out_role
) = This
->role
;
386 static HRESULT WINAPI
Accessible_get_accState(IAccessible
*iface
, VARIANT child_id
,
389 struct Accessible
*This
= impl_from_Accessible(iface
);
391 if (This
== &Accessible_child
)
392 CHECK_EXPECT(Accessible_child_get_accState
);
393 else if (This
== &Accessible_child2
)
394 CHECK_EXPECT(Accessible_child2_get_accState
);
395 else if (This
== &Accessible2
)
396 CHECK_EXPECT(Accessible2_get_accState
);
398 CHECK_EXPECT(Accessible_get_accState
);
400 if (V_VT(&child_id
) != VT_I4
)
403 if (This
== &Accessible
&& V_I4(&child_id
) != CHILDID_SELF
)
405 switch (V_I4(&child_id
))
408 V_VT(out_state
) = VT_I4
;
409 V_I4(out_state
) = STATE_SYSTEM_INVISIBLE
;
413 V_VT(out_state
) = VT_I4
;
414 V_I4(out_state
) = STATE_SYSTEM_FOCUSABLE
;
426 V_VT(out_state
) = VT_I4
;
427 V_I4(out_state
) = This
->state
;
434 static HRESULT WINAPI
Accessible_get_accHelp(IAccessible
*iface
, VARIANT child_id
,
437 ok(0, "unexpected call\n");
441 static HRESULT WINAPI
Accessible_get_accHelpTopic(IAccessible
*iface
,
442 BSTR
*out_help_file
, VARIANT child_id
, LONG
*out_topic_id
)
444 ok(0, "unexpected call\n");
448 static HRESULT WINAPI
Accessible_get_accKeyboardShortcut(IAccessible
*iface
, VARIANT child_id
,
449 BSTR
*out_kbd_shortcut
)
451 ok(0, "unexpected call\n");
455 static HRESULT WINAPI
Accessible_get_accFocus(IAccessible
*iface
, VARIANT
*pchild_id
)
457 ok(0, "unexpected call\n");
461 static HRESULT WINAPI
Accessible_get_accSelection(IAccessible
*iface
, VARIANT
*out_selection
)
463 ok(0, "unexpected call\n");
467 static HRESULT WINAPI
Accessible_get_accDefaultAction(IAccessible
*iface
, VARIANT child_id
,
468 BSTR
*out_default_action
)
470 ok(0, "unexpected call\n");
474 static HRESULT WINAPI
Accessible_accSelect(IAccessible
*iface
, LONG select_flags
,
477 ok(0, "unexpected call\n");
481 static HRESULT WINAPI
Accessible_accLocation(IAccessible
*iface
, LONG
*out_left
,
482 LONG
*out_top
, LONG
*out_width
, LONG
*out_height
, VARIANT child_id
)
484 struct Accessible
*This
= impl_from_Accessible(iface
);
486 if (This
== &Accessible_child
)
487 CHECK_EXPECT(Accessible_child_accLocation
);
488 else if (This
== &Accessible_child2
)
489 CHECK_EXPECT(Accessible_child2_accLocation
);
490 else if (This
== &Accessible2
)
491 CHECK_EXPECT(Accessible2_accLocation
);
493 CHECK_EXPECT(Accessible_accLocation
);
495 if (This
->width
&& This
->height
)
497 *out_left
= This
->left
;
498 *out_top
= This
->top
;
499 *out_width
= This
->width
;
500 *out_height
= This
->height
;
507 static HRESULT WINAPI
Accessible_accNavigate(IAccessible
*iface
, LONG nav_direction
,
508 VARIANT child_id_start
, VARIANT
*out_var
)
510 struct Accessible
*This
= impl_from_Accessible(iface
);
512 if (This
== &Accessible_child
)
513 CHECK_EXPECT(Accessible_child_accNavigate
);
514 else if (This
== &Accessible_child2
)
515 CHECK_EXPECT(Accessible_child2_accNavigate
);
517 CHECK_EXPECT(Accessible_accNavigate
);
518 VariantInit(out_var
);
521 * This is an undocumented way for UI Automation to get an HWND for
522 * IAccessible's contained in a Direct Annotation wrapper object.
524 if ((nav_direction
== NAVDIR_INTERNAL_HWND
) && check_variant_i4(&child_id_start
, CHILDID_SELF
) &&
527 V_VT(out_var
) = VT_I4
;
528 V_I4(out_var
) = HandleToUlong(This
->acc_hwnd
);
534 static HRESULT WINAPI
Accessible_accHitTest(IAccessible
*iface
, LONG left
, LONG top
,
535 VARIANT
*out_child_id
)
537 ok(0, "unexpected call\n");
541 static HRESULT WINAPI
Accessible_accDoDefaultAction(IAccessible
*iface
, VARIANT child_id
)
543 ok(0, "unexpected call\n");
547 static HRESULT WINAPI
Accessible_put_accName(IAccessible
*iface
, VARIANT child_id
,
550 ok(0, "unexpected call\n");
554 static HRESULT WINAPI
Accessible_put_accValue(IAccessible
*iface
, VARIANT child_id
,
557 ok(0, "unexpected call\n");
561 static IAccessibleVtbl AccessibleVtbl
= {
562 Accessible_QueryInterface
,
565 Accessible_GetTypeInfoCount
,
566 Accessible_GetTypeInfo
,
567 Accessible_GetIDsOfNames
,
569 Accessible_get_accParent
,
570 Accessible_get_accChildCount
,
571 Accessible_get_accChild
,
572 Accessible_get_accName
,
573 Accessible_get_accValue
,
574 Accessible_get_accDescription
,
575 Accessible_get_accRole
,
576 Accessible_get_accState
,
577 Accessible_get_accHelp
,
578 Accessible_get_accHelpTopic
,
579 Accessible_get_accKeyboardShortcut
,
580 Accessible_get_accFocus
,
581 Accessible_get_accSelection
,
582 Accessible_get_accDefaultAction
,
583 Accessible_accSelect
,
584 Accessible_accLocation
,
585 Accessible_accNavigate
,
586 Accessible_accHitTest
,
587 Accessible_accDoDefaultAction
,
588 Accessible_put_accName
,
589 Accessible_put_accValue
592 static inline struct Accessible
* impl_from_Accessible2(IAccessible2
*iface
)
594 return CONTAINING_RECORD(iface
, struct Accessible
, IAccessible2_iface
);
597 static HRESULT WINAPI
Accessible2_QueryInterface(IAccessible2
*iface
, REFIID riid
, void **obj
)
599 struct Accessible
*This
= impl_from_Accessible2(iface
);
600 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, obj
);
603 static ULONG WINAPI
Accessible2_AddRef(IAccessible2
*iface
)
605 struct Accessible
*This
= impl_from_Accessible2(iface
);
606 return IAccessible_AddRef(&This
->IAccessible_iface
);
609 static ULONG WINAPI
Accessible2_Release(IAccessible2
*iface
)
611 struct Accessible
*This
= impl_from_Accessible2(iface
);
612 return IAccessible_Release(&This
->IAccessible_iface
);
615 static HRESULT WINAPI
Accessible2_GetTypeInfoCount(IAccessible2
*iface
, UINT
*pctinfo
)
617 struct Accessible
*This
= impl_from_Accessible2(iface
);
618 return IAccessible_GetTypeInfoCount(&This
->IAccessible_iface
, pctinfo
);
621 static HRESULT WINAPI
Accessible2_GetTypeInfo(IAccessible2
*iface
, UINT iTInfo
,
622 LCID lcid
, ITypeInfo
**out_tinfo
)
624 struct Accessible
*This
= impl_from_Accessible2(iface
);
625 return IAccessible_GetTypeInfo(&This
->IAccessible_iface
, iTInfo
, lcid
, out_tinfo
);
628 static HRESULT WINAPI
Accessible2_GetIDsOfNames(IAccessible2
*iface
, REFIID riid
,
629 LPOLESTR
*rg_names
, UINT name_count
, LCID lcid
, DISPID
*rg_disp_id
)
631 struct Accessible
*This
= impl_from_Accessible2(iface
);
632 return IAccessible_GetIDsOfNames(&This
->IAccessible_iface
, riid
, rg_names
, name_count
,
636 static HRESULT WINAPI
Accessible2_Invoke(IAccessible2
*iface
, DISPID disp_id_member
,
637 REFIID riid
, LCID lcid
, WORD flags
, DISPPARAMS
*disp_params
,
638 VARIANT
*var_result
, EXCEPINFO
*excep_info
, UINT
*arg_err
)
640 struct Accessible
*This
= impl_from_Accessible2(iface
);
641 return IAccessible_Invoke(&This
->IAccessible_iface
, disp_id_member
, riid
, lcid
, flags
,
642 disp_params
, var_result
, excep_info
, arg_err
);
645 static HRESULT WINAPI
Accessible2_get_accParent(IAccessible2
*iface
, IDispatch
**out_parent
)
647 struct Accessible
*This
= impl_from_Accessible2(iface
);
648 return IAccessible_get_accParent(&This
->IAccessible_iface
, out_parent
);
651 static HRESULT WINAPI
Accessible2_get_accChildCount(IAccessible2
*iface
, LONG
*out_count
)
653 struct Accessible
*This
= impl_from_Accessible2(iface
);
654 return IAccessible_get_accChildCount(&This
->IAccessible_iface
, out_count
);
657 static HRESULT WINAPI
Accessible2_get_accChild(IAccessible2
*iface
, VARIANT child_id
,
658 IDispatch
**out_child
)
660 struct Accessible
*This
= impl_from_Accessible2(iface
);
661 return IAccessible_get_accChild(&This
->IAccessible_iface
, child_id
, out_child
);
664 static HRESULT WINAPI
Accessible2_get_accName(IAccessible2
*iface
, VARIANT child_id
,
667 struct Accessible
*This
= impl_from_Accessible2(iface
);
668 return IAccessible_get_accName(&This
->IAccessible_iface
, child_id
, out_name
);
671 static HRESULT WINAPI
Accessible2_get_accValue(IAccessible2
*iface
, VARIANT child_id
,
674 struct Accessible
*This
= impl_from_Accessible2(iface
);
675 return IAccessible_get_accValue(&This
->IAccessible_iface
, child_id
, out_value
);
678 static HRESULT WINAPI
Accessible2_get_accDescription(IAccessible2
*iface
, VARIANT child_id
,
679 BSTR
*out_description
)
681 struct Accessible
*This
= impl_from_Accessible2(iface
);
682 return IAccessible_get_accDescription(&This
->IAccessible_iface
, child_id
, out_description
);
685 static HRESULT WINAPI
Accessible2_get_accRole(IAccessible2
*iface
, VARIANT child_id
,
688 struct Accessible
*This
= impl_from_Accessible2(iface
);
689 return IAccessible_get_accRole(&This
->IAccessible_iface
, child_id
, out_role
);
692 static HRESULT WINAPI
Accessible2_get_accState(IAccessible2
*iface
, VARIANT child_id
,
695 struct Accessible
*This
= impl_from_Accessible2(iface
);
696 return IAccessible_get_accState(&This
->IAccessible_iface
, child_id
, out_state
);
699 static HRESULT WINAPI
Accessible2_get_accHelp(IAccessible2
*iface
, VARIANT child_id
,
702 struct Accessible
*This
= impl_from_Accessible2(iface
);
703 return IAccessible_get_accHelp(&This
->IAccessible_iface
, child_id
, out_help
);
706 static HRESULT WINAPI
Accessible2_get_accHelpTopic(IAccessible2
*iface
,
707 BSTR
*out_help_file
, VARIANT child_id
, LONG
*out_topic_id
)
709 struct Accessible
*This
= impl_from_Accessible2(iface
);
710 return IAccessible_get_accHelpTopic(&This
->IAccessible_iface
, out_help_file
, child_id
,
714 static HRESULT WINAPI
Accessible2_get_accKeyboardShortcut(IAccessible2
*iface
, VARIANT child_id
,
715 BSTR
*out_kbd_shortcut
)
717 struct Accessible
*This
= impl_from_Accessible2(iface
);
718 return IAccessible_get_accKeyboardShortcut(&This
->IAccessible_iface
, child_id
,
722 static HRESULT WINAPI
Accessible2_get_accFocus(IAccessible2
*iface
, VARIANT
*pchild_id
)
724 struct Accessible
*This
= impl_from_Accessible2(iface
);
725 return IAccessible_get_accFocus(&This
->IAccessible_iface
, pchild_id
);
728 static HRESULT WINAPI
Accessible2_get_accSelection(IAccessible2
*iface
, VARIANT
*out_selection
)
730 struct Accessible
*This
= impl_from_Accessible2(iface
);
731 return IAccessible_get_accSelection(&This
->IAccessible_iface
, out_selection
);
734 static HRESULT WINAPI
Accessible2_get_accDefaultAction(IAccessible2
*iface
, VARIANT child_id
,
735 BSTR
*out_default_action
)
737 struct Accessible
*This
= impl_from_Accessible2(iface
);
738 return IAccessible_get_accDefaultAction(&This
->IAccessible_iface
, child_id
,
742 static HRESULT WINAPI
Accessible2_accSelect(IAccessible2
*iface
, LONG select_flags
,
745 struct Accessible
*This
= impl_from_Accessible2(iface
);
746 return IAccessible_accSelect(&This
->IAccessible_iface
, select_flags
, child_id
);
749 static HRESULT WINAPI
Accessible2_accLocation(IAccessible2
*iface
, LONG
*out_left
,
750 LONG
*out_top
, LONG
*out_width
, LONG
*out_height
, VARIANT child_id
)
752 struct Accessible
*This
= impl_from_Accessible2(iface
);
753 return IAccessible_accLocation(&This
->IAccessible_iface
, out_left
, out_top
, out_width
,
754 out_height
, child_id
);
757 static HRESULT WINAPI
Accessible2_accNavigate(IAccessible2
*iface
, LONG nav_direction
,
758 VARIANT child_id_start
, VARIANT
*out_var
)
760 struct Accessible
*This
= impl_from_Accessible2(iface
);
761 return IAccessible_accNavigate(&This
->IAccessible_iface
, nav_direction
, child_id_start
,
765 static HRESULT WINAPI
Accessible2_accHitTest(IAccessible2
*iface
, LONG left
, LONG top
,
766 VARIANT
*out_child_id
)
768 struct Accessible
*This
= impl_from_Accessible2(iface
);
769 return IAccessible_accHitTest(&This
->IAccessible_iface
, left
, top
, out_child_id
);
772 static HRESULT WINAPI
Accessible2_accDoDefaultAction(IAccessible2
*iface
, VARIANT child_id
)
774 struct Accessible
*This
= impl_from_Accessible2(iface
);
775 return IAccessible_accDoDefaultAction(&This
->IAccessible_iface
, child_id
);
778 static HRESULT WINAPI
Accessible2_put_accName(IAccessible2
*iface
, VARIANT child_id
,
781 struct Accessible
*This
= impl_from_Accessible2(iface
);
782 return IAccessible_put_accName(&This
->IAccessible_iface
, child_id
, name
);
785 static HRESULT WINAPI
Accessible2_put_accValue(IAccessible2
*iface
, VARIANT child_id
,
788 struct Accessible
*This
= impl_from_Accessible2(iface
);
789 return IAccessible_put_accValue(&This
->IAccessible_iface
, child_id
, value
);
792 static HRESULT WINAPI
Accessible2_get_nRelations(IAccessible2
*iface
, LONG
*out_nRelations
)
794 ok(0, "unexpected call\n");
798 static HRESULT WINAPI
Accessible2_get_relation(IAccessible2
*iface
, LONG relation_idx
,
799 IAccessibleRelation
**out_relation
)
801 ok(0, "unexpected call\n");
805 static HRESULT WINAPI
Accessible2_get_relations(IAccessible2
*iface
, LONG count
,
806 IAccessibleRelation
**out_relations
, LONG
*out_relation_count
)
808 ok(0, "unexpected call\n");
812 static HRESULT WINAPI
Accessible2_role(IAccessible2
*iface
, LONG
*out_role
)
814 ok(0, "unexpected call\n");
818 static HRESULT WINAPI
Accessible2_scrollTo(IAccessible2
*iface
, enum IA2ScrollType scroll_type
)
820 ok(0, "unexpected call\n");
824 static HRESULT WINAPI
Accessible2_scrollToPoint(IAccessible2
*iface
,
825 enum IA2CoordinateType coordinate_type
, LONG x
, LONG y
)
827 ok(0, "unexpected call\n");
831 static HRESULT WINAPI
Accessible2_get_groupPosition(IAccessible2
*iface
, LONG
*out_group_level
,
832 LONG
*out_similar_items_in_group
, LONG
*out_position_in_group
)
834 ok(0, "unexpected call\n");
838 static HRESULT WINAPI
Accessible2_get_states(IAccessible2
*iface
, AccessibleStates
*out_states
)
840 ok(0, "unexpected call\n");
844 static HRESULT WINAPI
Accessible2_get_extendedRole(IAccessible2
*iface
, BSTR
*out_extended_role
)
846 ok(0, "unexpected call\n");
850 static HRESULT WINAPI
Accessible2_get_localizedExtendedRole(IAccessible2
*iface
,
851 BSTR
*out_localized_extended_role
)
853 ok(0, "unexpected call\n");
857 static HRESULT WINAPI
Accessible2_get_nExtendedStates(IAccessible2
*iface
, LONG
*out_nExtendedStates
)
859 ok(0, "unexpected call\n");
863 static HRESULT WINAPI
Accessible2_get_extendedStates(IAccessible2
*iface
, LONG count
,
864 BSTR
**out_extended_states
, LONG
*out_extended_states_count
)
866 ok(0, "unexpected call\n");
870 static HRESULT WINAPI
Accessible2_get_localizedExtendedStates(IAccessible2
*iface
, LONG count
,
871 BSTR
**out_localized_extended_states
, LONG
*out_localized_extended_states_count
)
873 ok(0, "unexpected call\n");
877 static HRESULT WINAPI
Accessible2_get_uniqueID(IAccessible2
*iface
, LONG
*out_unique_id
)
879 struct Accessible
*This
= impl_from_Accessible2(iface
);
881 if (This
== &Accessible2
)
882 CHECK_EXPECT(Accessible2_get_uniqueID
);
884 CHECK_EXPECT(Accessible_get_uniqueID
);
889 *out_unique_id
= This
->unique_id
;
896 static HRESULT WINAPI
Accessible2_get_windowHandle(IAccessible2
*iface
, HWND
*out_hwnd
)
898 ok(0, "unexpected call\n");
902 static HRESULT WINAPI
Accessible2_get_indexInParent(IAccessible2
*iface
, LONG
*out_idx_in_parent
)
904 ok(0, "unexpected call\n");
908 static HRESULT WINAPI
Accessible2_get_locale(IAccessible2
*iface
, IA2Locale
*out_locale
)
910 ok(0, "unexpected call\n");
914 static HRESULT WINAPI
Accessible2_get_attributes(IAccessible2
*iface
, BSTR
*out_attributes
)
916 ok(0, "unexpected call\n");
920 static const IAccessible2Vtbl Accessible2Vtbl
= {
921 Accessible2_QueryInterface
,
924 Accessible2_GetTypeInfoCount
,
925 Accessible2_GetTypeInfo
,
926 Accessible2_GetIDsOfNames
,
928 Accessible2_get_accParent
,
929 Accessible2_get_accChildCount
,
930 Accessible2_get_accChild
,
931 Accessible2_get_accName
,
932 Accessible2_get_accValue
,
933 Accessible2_get_accDescription
,
934 Accessible2_get_accRole
,
935 Accessible2_get_accState
,
936 Accessible2_get_accHelp
,
937 Accessible2_get_accHelpTopic
,
938 Accessible2_get_accKeyboardShortcut
,
939 Accessible2_get_accFocus
,
940 Accessible2_get_accSelection
,
941 Accessible2_get_accDefaultAction
,
942 Accessible2_accSelect
,
943 Accessible2_accLocation
,
944 Accessible2_accNavigate
,
945 Accessible2_accHitTest
,
946 Accessible2_accDoDefaultAction
,
947 Accessible2_put_accName
,
948 Accessible2_put_accValue
,
949 Accessible2_get_nRelations
,
950 Accessible2_get_relation
,
951 Accessible2_get_relations
,
953 Accessible2_scrollTo
,
954 Accessible2_scrollToPoint
,
955 Accessible2_get_groupPosition
,
956 Accessible2_get_states
,
957 Accessible2_get_extendedRole
,
958 Accessible2_get_localizedExtendedRole
,
959 Accessible2_get_nExtendedStates
,
960 Accessible2_get_extendedStates
,
961 Accessible2_get_localizedExtendedStates
,
962 Accessible2_get_uniqueID
,
963 Accessible2_get_windowHandle
,
964 Accessible2_get_indexInParent
,
965 Accessible2_get_locale
,
966 Accessible2_get_attributes
,
969 static inline struct Accessible
* impl_from_OleWindow(IOleWindow
*iface
)
971 return CONTAINING_RECORD(iface
, struct Accessible
, IOleWindow_iface
);
974 static HRESULT WINAPI
OleWindow_QueryInterface(IOleWindow
*iface
, REFIID riid
, void **obj
)
976 struct Accessible
*This
= impl_from_OleWindow(iface
);
977 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, obj
);
980 static ULONG WINAPI
OleWindow_AddRef(IOleWindow
*iface
)
982 struct Accessible
*This
= impl_from_OleWindow(iface
);
983 return IAccessible_AddRef(&This
->IAccessible_iface
);
986 static ULONG WINAPI
OleWindow_Release(IOleWindow
*iface
)
988 struct Accessible
*This
= impl_from_OleWindow(iface
);
989 return IAccessible_Release(&This
->IAccessible_iface
);
992 static HRESULT WINAPI
OleWindow_GetWindow(IOleWindow
*iface
, HWND
*hwnd
)
994 struct Accessible
*This
= impl_from_OleWindow(iface
);
996 *hwnd
= This
->ow_hwnd
;
997 return *hwnd
? S_OK
: E_FAIL
;
1000 static HRESULT WINAPI
OleWindow_ContextSensitiveHelp(IOleWindow
*iface
, BOOL f_enter_mode
)
1005 static const IOleWindowVtbl OleWindowVtbl
= {
1006 OleWindow_QueryInterface
,
1009 OleWindow_GetWindow
,
1010 OleWindow_ContextSensitiveHelp
1013 static inline struct Accessible
* impl_from_ServiceProvider(IServiceProvider
*iface
)
1015 return CONTAINING_RECORD(iface
, struct Accessible
, IServiceProvider_iface
);
1018 static HRESULT WINAPI
ServiceProvider_QueryInterface(IServiceProvider
*iface
, REFIID riid
, void **obj
)
1020 struct Accessible
*This
= impl_from_ServiceProvider(iface
);
1021 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, obj
);
1024 static ULONG WINAPI
ServiceProvider_AddRef(IServiceProvider
*iface
)
1026 struct Accessible
*This
= impl_from_ServiceProvider(iface
);
1027 return IAccessible_AddRef(&This
->IAccessible_iface
);
1030 static ULONG WINAPI
ServiceProvider_Release(IServiceProvider
*iface
)
1032 struct Accessible
*This
= impl_from_ServiceProvider(iface
);
1033 return IAccessible_Release(&This
->IAccessible_iface
);
1036 static HRESULT WINAPI
ServiceProvider_QueryService(IServiceProvider
*iface
, REFGUID service_guid
,
1037 REFIID riid
, void **obj
)
1039 struct Accessible
*This
= impl_from_ServiceProvider(iface
);
1041 if (IsEqualIID(riid
, &IID_IAccessible2
) && IsEqualIID(service_guid
, &IID_IAccessible2
) &&
1043 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, obj
);
1048 static const IServiceProviderVtbl ServiceProviderVtbl
= {
1049 ServiceProvider_QueryInterface
,
1050 ServiceProvider_AddRef
,
1051 ServiceProvider_Release
,
1052 ServiceProvider_QueryService
,
1055 static struct Accessible Accessible
=
1057 { &AccessibleVtbl
},
1058 { &Accessible2Vtbl
},
1060 { &ServiceProviderVtbl
},
1069 static struct Accessible Accessible2
=
1071 { &AccessibleVtbl
},
1072 { &Accessible2Vtbl
},
1074 { &ServiceProviderVtbl
},
1083 static struct Accessible Accessible_child
=
1085 { &AccessibleVtbl
},
1086 { &Accessible2Vtbl
},
1088 { &ServiceProviderVtbl
},
1090 &Accessible
.IAccessible_iface
,
1097 static struct Accessible Accessible_child2
=
1099 { &AccessibleVtbl
},
1100 { &Accessible2Vtbl
},
1102 { &ServiceProviderVtbl
},
1104 &Accessible
.IAccessible_iface
,
1111 struct Provider_prop_override
1117 struct Provider_value_pattern_data
1123 struct Provider_legacy_accessible_pattern_data
1130 static struct Provider
1132 IRawElementProviderSimple IRawElementProviderSimple_iface
;
1133 IRawElementProviderFragment IRawElementProviderFragment_iface
;
1134 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface
;
1135 IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface
;
1136 IValueProvider IValueProvider_iface
;
1137 ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface
;
1140 const char *prov_name
;
1141 IRawElementProviderFragment
*parent
;
1142 IRawElementProviderFragmentRoot
*frag_root
;
1143 IRawElementProviderFragment
*prev_sibling
;
1144 IRawElementProviderFragment
*next_sibling
;
1145 IRawElementProviderFragment
*first_child
;
1146 IRawElementProviderFragment
*last_child
;
1147 enum ProviderOptions prov_opts
;
1149 BOOL ret_invalid_prop_type
;
1152 DWORD last_call_tid
;
1153 BOOL ignore_hwnd_prop
;
1155 struct Provider_prop_override
*prop_override
;
1156 int prop_override_count
;
1157 struct UiaRect bounds_rect
;
1158 struct Provider_value_pattern_data value_pattern_data
;
1159 struct Provider_legacy_accessible_pattern_data legacy_acc_pattern_data
;
1160 IRawElementProviderFragment
*focus_prov
;
1161 } Provider
, Provider2
, Provider_child
, Provider_child2
;
1162 static struct Provider Provider_hwnd
, Provider_nc
, Provider_proxy
, Provider_proxy2
, Provider_override
;
1163 static void initialize_provider(struct Provider
*prov
, int prov_opts
, HWND hwnd
, BOOL initialize_nav_links
);
1164 static void set_provider_prop_override(struct Provider
*prov
, struct Provider_prop_override
*override
, int count
);
1165 static void set_property_override(struct Provider_prop_override
*override
, int prop_id
, VARIANT
*val
);
1166 static void initialize_provider_tree(BOOL initialize_nav_links
);
1167 static void provider_add_child(struct Provider
*prov
, struct Provider
*child
);
1169 static const WCHAR
*uia_bstr_prop_str
= L
"uia-string";
1170 static const ULONG uia_i4_prop_val
= 0xdeadbeef;
1171 static const ULONG uia_i4_arr_prop_val
[] = { 0xfeedbeef, 0xdeadcafe, 0xfefedede };
1172 static const double uia_r8_prop_val
= 128.256f
;
1173 static const double uia_r8_arr_prop_val
[] = { 2.4, 8.16, 32.64 };
1174 static const IRawElementProviderSimple
*uia_unk_arr_prop_val
[] = { &Provider_child
.IRawElementProviderSimple_iface
,
1175 &Provider_child2
.IRawElementProviderSimple_iface
};
1176 static SAFEARRAY
*create_i4_safearray(void)
1181 if (!(sa
= SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(uia_i4_arr_prop_val
))))
1184 for (idx
= 0; idx
< ARRAY_SIZE(uia_i4_arr_prop_val
); idx
++)
1185 SafeArrayPutElement(sa
, &idx
, (void *)&uia_i4_arr_prop_val
[idx
]);
1190 static SAFEARRAY
*create_r8_safearray(void)
1195 if (!(sa
= SafeArrayCreateVector(VT_R8
, 0, ARRAY_SIZE(uia_r8_arr_prop_val
))))
1198 for (idx
= 0; idx
< ARRAY_SIZE(uia_r8_arr_prop_val
); idx
++)
1199 SafeArrayPutElement(sa
, &idx
, (void *)&uia_r8_arr_prop_val
[idx
]);
1204 static SAFEARRAY
*create_unk_safearray(void)
1209 if (!(sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, ARRAY_SIZE(uia_unk_arr_prop_val
))))
1212 for (idx
= 0; idx
< ARRAY_SIZE(uia_unk_arr_prop_val
); idx
++)
1213 SafeArrayPutElement(sa
, &idx
, (void *)uia_unk_arr_prop_val
[idx
]);
1219 PROV_GET_PROVIDER_OPTIONS
,
1220 PROV_GET_PATTERN_PROV
,
1221 PROV_GET_PROPERTY_VALUE
,
1222 PROV_GET_HOST_RAW_ELEMENT_PROVIDER
,
1224 FRAG_GET_RUNTIME_ID
,
1225 FRAG_GET_FRAGMENT_ROOT
,
1226 FRAG_GET_BOUNDING_RECT
,
1227 FRAG_ROOT_GET_FOCUS
,
1228 HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
,
1231 static const char *prov_method_str
[] = {
1232 "get_ProviderOptions",
1233 "GetPatternProvider",
1235 "get_HostRawElementProvider",
1239 "get_BoundingRectangle",
1241 "GetOverrideProviderForHwnd",
1244 static const char *get_prov_method_str(int method
)
1246 if (method
>= ARRAY_SIZE(prov_method_str
))
1249 return prov_method_str
[method
];
1253 METHOD_OPTIONAL
= 0x01,
1257 struct prov_method_sequence
{
1258 struct Provider
*prov
;
1263 static int sequence_cnt
, sequence_size
;
1264 static struct prov_method_sequence
*sequence
;
1267 * This sequence of method calls is always used when creating an HUIANODE from
1268 * an IRawElementProviderSimple.
1270 #define NODE_CREATE_SEQ(prov) \
1271 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1272 /* Win10v1507 and below call this. */ \
1273 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1274 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1275 { prov , PROV_GET_PROPERTY_VALUE }, \
1276 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1277 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1280 * This sequence of method calls is always used when creating an HUIANODE from
1281 * an IRawElementProviderSimple that returns an HWND from get_HostRawElementProvider.
1283 #define NODE_CREATE_SEQ2(prov) \
1284 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1285 /* Win10v1507 and below call this. */ \
1286 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1287 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1288 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1289 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1291 #define NODE_CREATE_SEQ2_OPTIONAL(prov) \
1292 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1293 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1294 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1295 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1297 static void flush_method_sequence(void)
1299 HeapFree(GetProcessHeap(), 0, sequence
);
1301 sequence_cnt
= sequence_size
= 0;
1304 static BOOL method_sequences_enabled
= TRUE
;
1305 static void add_method_call(struct Provider
*prov
, int method
)
1307 struct prov_method_sequence prov_method
= {0};
1309 if (!method_sequences_enabled
)
1315 sequence
= HeapAlloc(GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
));
1317 if (sequence_cnt
== sequence_size
)
1320 sequence
= HeapReAlloc(GetProcessHeap(), 0, sequence
, sequence_size
* sizeof(*sequence
));
1323 prov_method
.prov
= prov
;
1324 prov_method
.method
= method
;
1325 prov_method
.flags
= 0;
1326 sequence
[sequence_cnt
++] = prov_method
;
1329 #define ok_method_sequence( exp, context ) \
1330 ok_method_sequence_( (exp), (context), __FILE__, __LINE__)
1331 static void ok_method_sequence_(const struct prov_method_sequence
*expected_list
, const char *context
,
1332 const char *file
, int line
)
1334 const struct prov_method_sequence
*expected
= expected_list
;
1335 const struct prov_method_sequence
*actual
;
1336 unsigned int count
= 0;
1338 assert(method_sequences_enabled
);
1339 add_method_call(NULL
, 0);
1343 winetest_push_context("%s", context
);
1345 while (expected
->prov
&& actual
->prov
)
1347 if (expected
->prov
== actual
->prov
&& expected
->method
== actual
->method
)
1349 if (expected
->flags
& METHOD_TODO
)
1350 todo_wine
ok_(file
, line
)(1, "%d: expected %s_%s, got %s_%s\n", count
, expected
->prov
->prov_name
,
1351 get_prov_method_str(expected
->method
), actual
->prov
->prov_name
, get_prov_method_str(actual
->method
));
1355 else if (expected
->flags
& METHOD_TODO
)
1357 todo_wine
ok_(file
, line
)(0, "%d: expected %s_%s, got %s_%s\n", count
, expected
->prov
->prov_name
,
1358 get_prov_method_str(expected
->method
), actual
->prov
->prov_name
, get_prov_method_str(actual
->method
));
1361 else if (expected
->flags
& METHOD_OPTIONAL
)
1365 ok_(file
, line
)(0, "%d: expected %s_%s, got %s_%s\n", count
, expected
->prov
->prov_name
,
1366 get_prov_method_str(expected
->method
), actual
->prov
->prov_name
, get_prov_method_str(actual
->method
));
1373 /* Handle trailing optional/todo_wine methods. */
1374 while (expected
->prov
&& ((expected
->flags
& METHOD_OPTIONAL
) ||
1375 ((expected
->flags
& METHOD_TODO
) && !strcmp(winetest_platform
, "wine"))))
1377 if (expected
->flags
& METHOD_TODO
)
1378 todo_wine
ok_(file
, line
)(0, "%d: expected %s_%s\n", count
, expected
->prov
->prov_name
,
1379 get_prov_method_str(expected
->method
));
1384 if (expected
->prov
|| actual
->prov
)
1387 ok_( file
, line
)(0, "incomplete sequence: expected %s_%s, got nothing\n", expected
->prov
->prov_name
,
1388 get_prov_method_str(expected
->method
));
1390 ok_( file
, line
)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual
->prov
->prov_name
,
1391 get_prov_method_str(actual
->method
));
1395 winetest_pop_context();
1397 flush_method_sequence();
1401 * Parsing the string returned by UIA_ProviderDescriptionPropertyId is
1402 * the only way to know what an HUIANODE represents internally. It
1403 * returns a formatted string which always starts with:
1404 * "[pid:<process-id>,providerId:0x<hwnd-ptr> "
1405 * On Windows versions 10v1507 and below, "providerId:" is "hwnd:"
1407 * This is followed by strings for each provider it represents. These are
1409 * "<prov-type>:<prov-desc> (<origin>)"
1410 * and are terminated with ";", the final provider has no ";" terminator,
1411 * instead it has "]".
1413 * If the given provider is the one used for navigation towards a parent, it has
1414 * "(parent link)" as a suffix on "<prov-type>".
1416 * <prov-type> is one of "Annotation", "Main", "Override", "Hwnd", or
1419 * <prov-desc> is the string returned from calling GetPropertyValue on the
1420 * IRawElementProviderSimple being represented with a property ID of
1421 * UIA_ProviderDescriptionPropertyId.
1423 * <origin> is the name of the module that the
1424 * IRawElementProviderSimple comes from. For unmanaged code, it's:
1425 * "unmanaged:<executable>"
1426 * and for managed code, it's:
1427 * "managed:<assembly-qualified-name>"
1430 * [pid:1500,providerId:0x2F054C Main:Provider (unmanaged:uiautomation_test.exe); Hwnd(parent link):HWND Proxy (unmanaged:uiautomationcore.dll)]
1432 static BOOL
get_provider_desc(BSTR prov_desc
, const WCHAR
*prov_type
, WCHAR
*out_name
)
1434 const WCHAR
*str
, *str2
;
1436 str
= wcsstr(prov_desc
, prov_type
);
1443 str
+= wcslen(prov_type
);
1444 str2
= wcschr(str
, L
'(');
1445 lstrcpynW(out_name
, str
, ((str2
- str
)));
1450 #define check_node_provider_desc_todo( prov_desc, prov_type, prov_name, parent_link ) \
1451 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), TRUE, __FILE__, __LINE__)
1452 #define check_node_provider_desc( prov_desc, prov_type, prov_name, parent_link ) \
1453 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), FALSE, __FILE__, __LINE__)
1454 static void check_node_provider_desc_(BSTR prov_desc
, const WCHAR
*prov_type
, const WCHAR
*prov_name
,
1455 BOOL parent_link
, BOOL todo
, const char *file
, int line
)
1460 wsprintfW(buf
, L
"%s(parent link):", prov_type
);
1462 wsprintfW(buf
, L
"%s:", prov_type
);
1464 if (!get_provider_desc(prov_desc
, buf
, buf
))
1467 wsprintfW(buf
, L
"%s:", prov_type
);
1469 wsprintfW(buf
, L
"%s(parent link):", prov_type
);
1471 if (!get_provider_desc(prov_desc
, buf
, buf
))
1472 todo_wine_if(todo
) ok_(file
, line
)(0, "failed to get provider string for %s\n", debugstr_w(prov_type
));
1476 todo_wine_if(todo
) ok_(file
, line
)(0, "expected parent link provider %s\n", debugstr_w(prov_type
));
1478 todo_wine_if(todo
) ok_(file
, line
)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type
));
1485 ok_(file
, line
)(!wcscmp(prov_name
, buf
), "unexpected provider name %s\n", debugstr_w(buf
));
1488 #define check_node_provider_desc_prefix( prov_desc, pid, prov_id ) \
1489 check_node_provider_desc_prefix_( (prov_desc), (pid), (prov_id), __FILE__, __LINE__)
1490 static void check_node_provider_desc_prefix_(BSTR prov_desc
, DWORD pid
, HWND prov_id
, const char *file
, int line
)
1492 const WCHAR
*str
, *str2
;
1498 str
= wcsstr(prov_desc
, L
"pid:");
1499 str
+= wcslen(L
"pid:");
1500 str2
= wcschr(str
, L
',');
1501 lstrcpynW(buf
, str
, (str2
- str
) + 1);
1502 prov_pid
= wcstoul(buf
, &end
, 10);
1503 ok_(file
, line
)(prov_pid
== pid
, "Unexpected pid %lu\n", prov_pid
);
1505 str
= wcsstr(prov_desc
, L
"providerId:");
1507 str
+= wcslen(L
"providerId:");
1510 str
= wcsstr(prov_desc
, L
"hwnd:");
1511 str
+= wcslen(L
"hwnd:");
1513 str2
= wcschr(str
, L
' ');
1514 lstrcpynW(buf
, str
, (str2
- str
) + 1);
1515 prov_hwnd
= ULongToHandle(wcstoul(buf
, &end
, 16));
1516 ok_(file
, line
)(prov_hwnd
== prov_id
, "Unexpected hwnd %p\n", prov_hwnd
);
1520 * For node providers that come from an HWND belonging to another process
1521 * or another thread, the provider is considered 'nested', a node in a node.
1523 static BOOL
get_nested_provider_desc(BSTR prov_desc
, const WCHAR
*prov_type
, BOOL parent_link
, WCHAR
*out_desc
)
1525 const WCHAR
*str
, *str2
;
1529 wsprintfW(buf
, L
"%s:Nested ", prov_type
);
1531 wsprintfW(buf
, L
"%s(parent link):Nested ", prov_type
);
1532 str
= wcsstr(prov_desc
, buf
);
1533 /* Check with and without parent-link. */
1541 str2
= wcschr(str
, L
']');
1542 /* We want to include the ']' character, so + 2. */
1543 lstrcpynW(out_desc
, str
, ((str2
- str
) + 2));
1548 #define check_runtime_id( exp_runtime_id, exp_size, runtime_id ) \
1549 check_runtime_id_( (exp_runtime_id), (exp_size), (runtime_id), __FILE__, __LINE__)
1550 static void check_runtime_id_(int *exp_runtime_id
, int exp_size
, SAFEARRAY
*runtime_id
, const char *file
, int line
)
1552 LONG i
, idx
, lbound
, ubound
, elems
;
1557 dims
= SafeArrayGetDim(runtime_id
);
1558 ok_(file
, line
)(dims
== 1, "Unexpected array dims %d\n", dims
);
1560 hr
= SafeArrayGetLBound(runtime_id
, 1, &lbound
);
1561 ok_(file
, line
)(hr
== S_OK
, "Failed to get LBound with hr %#lx\n", hr
);
1563 hr
= SafeArrayGetUBound(runtime_id
, 1, &ubound
);
1564 ok_(file
, line
)(hr
== S_OK
, "Failed to get UBound with hr %#lx\n", hr
);
1566 elems
= (ubound
- lbound
) + 1;
1567 ok_(file
, line
)(exp_size
== elems
, "Unexpected runtime_id array size %#lx\n", elems
);
1569 for (i
= 0; i
< elems
; i
++)
1572 hr
= SafeArrayGetElement(runtime_id
, &idx
, &val
);
1573 ok_(file
, line
)(hr
== S_OK
, "Failed to get element with hr %#lx\n", hr
);
1574 ok_(file
, line
)(val
== exp_runtime_id
[i
], "Unexpected runtime_id[%ld] %#x\n", i
, val
);
1578 static inline struct Provider
*impl_from_ProviderSimple(IRawElementProviderSimple
*iface
)
1580 return CONTAINING_RECORD(iface
, struct Provider
, IRawElementProviderSimple_iface
);
1583 HRESULT WINAPI
ProviderSimple_QueryInterface(IRawElementProviderSimple
*iface
, REFIID riid
, void **ppv
)
1585 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1588 if (IsEqualIID(riid
, &IID_IRawElementProviderSimple
) || IsEqualIID(riid
, &IID_IUnknown
))
1590 else if (IsEqualIID(riid
, &IID_IRawElementProviderFragment
))
1591 *ppv
= &This
->IRawElementProviderFragment_iface
;
1592 else if (IsEqualIID(riid
, &IID_IRawElementProviderFragmentRoot
))
1593 *ppv
= &This
->IRawElementProviderFragmentRoot_iface
;
1594 else if (IsEqualIID(riid
, &IID_IRawElementProviderHwndOverride
))
1595 *ppv
= &This
->IRawElementProviderHwndOverride_iface
;
1596 else if (IsEqualIID(riid
, &IID_IValueProvider
))
1597 *ppv
= &This
->IValueProvider_iface
;
1598 else if (IsEqualIID(riid
, &IID_ILegacyIAccessibleProvider
))
1599 *ppv
= &This
->ILegacyIAccessibleProvider_iface
;
1601 return E_NOINTERFACE
;
1603 IRawElementProviderSimple_AddRef(iface
);
1607 ULONG WINAPI
ProviderSimple_AddRef(IRawElementProviderSimple
*iface
)
1609 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1610 return InterlockedIncrement(&This
->ref
);
1613 ULONG WINAPI
ProviderSimple_Release(IRawElementProviderSimple
*iface
)
1615 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1616 return InterlockedDecrement(&This
->ref
);
1619 HRESULT WINAPI
ProviderSimple_get_ProviderOptions(IRawElementProviderSimple
*iface
,
1620 enum ProviderOptions
*ret_val
)
1622 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1624 add_method_call(This
, PROV_GET_PROVIDER_OPTIONS
);
1625 if (This
->expected_tid
)
1626 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1627 This
->last_call_tid
= GetCurrentThreadId();
1630 if (This
->prov_opts
)
1632 *ret_val
= This
->prov_opts
;
1639 HRESULT WINAPI
ProviderSimple_GetPatternProvider(IRawElementProviderSimple
*iface
,
1640 PATTERNID pattern_id
, IUnknown
**ret_val
)
1642 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1644 add_method_call(This
, PROV_GET_PATTERN_PROV
);
1645 if (This
->expected_tid
)
1646 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1647 This
->last_call_tid
= GetCurrentThreadId();
1652 case UIA_ValuePatternId
:
1653 if (This
->value_pattern_data
.is_supported
)
1654 *ret_val
= (IUnknown
*)iface
;
1657 case UIA_LegacyIAccessiblePatternId
:
1658 if (This
->legacy_acc_pattern_data
.is_supported
)
1659 *ret_val
= (IUnknown
*)iface
;
1667 IUnknown_AddRef(*ret_val
);
1672 HRESULT WINAPI
ProviderSimple_GetPropertyValue(IRawElementProviderSimple
*iface
,
1673 PROPERTYID prop_id
, VARIANT
*ret_val
)
1675 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1677 add_method_call(This
, PROV_GET_PROPERTY_VALUE
);
1678 if (This
->expected_tid
)
1679 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1680 This
->last_call_tid
= GetCurrentThreadId();
1682 if (This
->prop_override
&& This
->prop_override_count
)
1686 for (i
= 0; i
< This
->prop_override_count
; i
++)
1688 if (This
->prop_override
[i
].prop_id
== prop_id
)
1690 *ret_val
= This
->prop_override
[i
].val
;
1691 if (V_VT(ret_val
) == VT_UNKNOWN
)
1692 IUnknown_AddRef(V_UNKNOWN(ret_val
));
1699 VariantInit(ret_val
);
1702 case UIA_NativeWindowHandlePropertyId
:
1703 if (This
->ret_invalid_prop_type
)
1705 V_VT(ret_val
) = VT_R8
;
1706 V_R8(ret_val
) = uia_r8_prop_val
;
1708 else if (!This
->ignore_hwnd_prop
)
1710 V_VT(ret_val
) = VT_I4
;
1711 V_I4(ret_val
) = HandleToULong(This
->hwnd
);
1715 case UIA_ProcessIdPropertyId
:
1716 case UIA_ControlTypePropertyId
:
1717 case UIA_CulturePropertyId
:
1718 case UIA_OrientationPropertyId
:
1719 case UIA_LiveSettingPropertyId
:
1720 case UIA_PositionInSetPropertyId
:
1721 case UIA_SizeOfSetPropertyId
:
1722 case UIA_LevelPropertyId
:
1723 case UIA_LandmarkTypePropertyId
:
1724 case UIA_FillColorPropertyId
:
1725 case UIA_FillTypePropertyId
:
1726 case UIA_VisualEffectsPropertyId
:
1727 case UIA_HeadingLevelPropertyId
:
1728 if (This
->ret_invalid_prop_type
)
1730 V_VT(ret_val
) = VT_R8
;
1731 V_R8(ret_val
) = uia_r8_prop_val
;
1735 V_VT(ret_val
) = VT_I4
;
1736 V_I4(ret_val
) = uia_i4_prop_val
;
1740 case UIA_RotationPropertyId
:
1741 if (This
->ret_invalid_prop_type
)
1743 V_VT(ret_val
) = VT_I4
;
1744 V_I4(ret_val
) = uia_i4_prop_val
;
1748 V_VT(ret_val
) = VT_R8
;
1749 V_R8(ret_val
) = uia_r8_prop_val
;
1753 case UIA_LocalizedControlTypePropertyId
:
1754 case UIA_NamePropertyId
:
1755 case UIA_AcceleratorKeyPropertyId
:
1756 case UIA_AccessKeyPropertyId
:
1757 case UIA_AutomationIdPropertyId
:
1758 case UIA_ClassNamePropertyId
:
1759 case UIA_HelpTextPropertyId
:
1760 case UIA_ItemTypePropertyId
:
1761 case UIA_FrameworkIdPropertyId
:
1762 case UIA_ItemStatusPropertyId
:
1763 case UIA_AriaRolePropertyId
:
1764 case UIA_AriaPropertiesPropertyId
:
1765 case UIA_LocalizedLandmarkTypePropertyId
:
1766 case UIA_FullDescriptionPropertyId
:
1767 if (This
->ret_invalid_prop_type
)
1769 V_VT(ret_val
) = VT_I4
;
1770 V_I4(ret_val
) = uia_i4_prop_val
;
1774 V_VT(ret_val
) = VT_BSTR
;
1775 V_BSTR(ret_val
) = SysAllocString(uia_bstr_prop_str
);
1779 case UIA_HasKeyboardFocusPropertyId
:
1780 case UIA_IsKeyboardFocusablePropertyId
:
1781 case UIA_IsEnabledPropertyId
:
1782 case UIA_IsControlElementPropertyId
:
1783 case UIA_IsContentElementPropertyId
:
1784 case UIA_IsPasswordPropertyId
:
1785 case UIA_IsOffscreenPropertyId
:
1786 case UIA_IsRequiredForFormPropertyId
:
1787 case UIA_IsDataValidForFormPropertyId
:
1788 case UIA_OptimizeForVisualContentPropertyId
:
1789 case UIA_IsPeripheralPropertyId
:
1790 case UIA_IsDialogPropertyId
:
1791 if (This
->ret_invalid_prop_type
)
1793 V_VT(ret_val
) = VT_R8
;
1794 V_R8(ret_val
) = uia_r8_prop_val
;
1798 V_VT(ret_val
) = VT_BOOL
;
1799 V_BOOL(ret_val
) = VARIANT_TRUE
;
1803 case UIA_AnnotationTypesPropertyId
:
1804 case UIA_OutlineColorPropertyId
:
1805 if (This
->ret_invalid_prop_type
)
1807 V_VT(ret_val
) = VT_ARRAY
| VT_R8
;
1808 V_ARRAY(ret_val
) = create_r8_safearray();
1812 V_VT(ret_val
) = VT_ARRAY
| VT_I4
;
1813 V_ARRAY(ret_val
) = create_i4_safearray();
1817 case UIA_OutlineThicknessPropertyId
:
1818 case UIA_SizePropertyId
:
1819 if (This
->ret_invalid_prop_type
)
1821 V_VT(ret_val
) = VT_ARRAY
| VT_I4
;
1822 V_ARRAY(ret_val
) = create_i4_safearray();
1826 V_VT(ret_val
) = VT_ARRAY
| VT_R8
;
1827 V_ARRAY(ret_val
) = create_r8_safearray();
1831 case UIA_LabeledByPropertyId
:
1832 if (This
->ret_invalid_prop_type
)
1834 V_VT(ret_val
) = VT_I4
;
1835 V_I4(ret_val
) = uia_i4_prop_val
;
1839 V_VT(ret_val
) = VT_UNKNOWN
;
1840 V_UNKNOWN(ret_val
) = (IUnknown
*)&Provider_child
.IRawElementProviderSimple_iface
;
1841 IUnknown_AddRef(V_UNKNOWN(ret_val
));
1845 case UIA_AnnotationObjectsPropertyId
:
1846 case UIA_DescribedByPropertyId
:
1847 case UIA_FlowsFromPropertyId
:
1848 case UIA_FlowsToPropertyId
:
1849 case UIA_ControllerForPropertyId
:
1850 if (This
->ret_invalid_prop_type
)
1852 V_VT(ret_val
) = VT_ARRAY
| VT_I4
;
1853 V_ARRAY(ret_val
) = create_i4_safearray();
1857 V_VT(ret_val
) = VT_UNKNOWN
| VT_ARRAY
;
1858 V_ARRAY(ret_val
) = create_unk_safearray();
1862 case UIA_ProviderDescriptionPropertyId
:
1864 WCHAR buf
[1024] = {};
1866 mbstowcs(buf
, This
->prov_name
, strlen(This
->prov_name
));
1867 V_VT(ret_val
) = VT_BSTR
;
1868 V_BSTR(ret_val
) = SysAllocString(buf
);
1879 HRESULT WINAPI
ProviderSimple_get_HostRawElementProvider(IRawElementProviderSimple
*iface
,
1880 IRawElementProviderSimple
**ret_val
)
1882 struct Provider
*This
= impl_from_ProviderSimple(iface
);
1884 add_method_call(This
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
);
1885 if (This
->expected_tid
)
1886 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1887 This
->last_call_tid
= GetCurrentThreadId();
1891 return UiaHostProviderFromHwnd(This
->hwnd
, ret_val
);
1896 IRawElementProviderSimpleVtbl ProviderSimpleVtbl
= {
1897 ProviderSimple_QueryInterface
,
1898 ProviderSimple_AddRef
,
1899 ProviderSimple_Release
,
1900 ProviderSimple_get_ProviderOptions
,
1901 ProviderSimple_GetPatternProvider
,
1902 ProviderSimple_GetPropertyValue
,
1903 ProviderSimple_get_HostRawElementProvider
,
1906 static inline struct Provider
*impl_from_ProviderFragment(IRawElementProviderFragment
*iface
)
1908 return CONTAINING_RECORD(iface
, struct Provider
, IRawElementProviderFragment_iface
);
1911 static HRESULT WINAPI
ProviderFragment_QueryInterface(IRawElementProviderFragment
*iface
, REFIID riid
,
1914 struct Provider
*Provider
= impl_from_ProviderFragment(iface
);
1915 return IRawElementProviderSimple_QueryInterface(&Provider
->IRawElementProviderSimple_iface
, riid
, ppv
);
1918 static ULONG WINAPI
ProviderFragment_AddRef(IRawElementProviderFragment
*iface
)
1920 struct Provider
*Provider
= impl_from_ProviderFragment(iface
);
1921 return IRawElementProviderSimple_AddRef(&Provider
->IRawElementProviderSimple_iface
);
1924 static ULONG WINAPI
ProviderFragment_Release(IRawElementProviderFragment
*iface
)
1926 struct Provider
*Provider
= impl_from_ProviderFragment(iface
);
1927 return IRawElementProviderSimple_Release(&Provider
->IRawElementProviderSimple_iface
);
1930 static HRESULT WINAPI
ProviderFragment_Navigate(IRawElementProviderFragment
*iface
,
1931 enum NavigateDirection direction
, IRawElementProviderFragment
**ret_val
)
1933 struct Provider
*This
= impl_from_ProviderFragment(iface
);
1935 add_method_call(This
, FRAG_NAVIGATE
);
1936 if (This
->expected_tid
)
1937 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1938 This
->last_call_tid
= GetCurrentThreadId();
1943 case NavigateDirection_Parent
:
1944 *ret_val
= This
->parent
;
1947 case NavigateDirection_NextSibling
:
1948 *ret_val
= This
->next_sibling
;
1951 case NavigateDirection_PreviousSibling
:
1952 *ret_val
= This
->prev_sibling
;
1955 case NavigateDirection_FirstChild
:
1956 *ret_val
= This
->first_child
;
1959 case NavigateDirection_LastChild
:
1960 *ret_val
= This
->last_child
;
1964 trace("Invalid navigate direction %d\n", direction
);
1969 IRawElementProviderFragment_AddRef(*ret_val
);
1974 static HRESULT WINAPI
ProviderFragment_GetRuntimeId(IRawElementProviderFragment
*iface
,
1975 SAFEARRAY
**ret_val
)
1977 struct Provider
*This
= impl_from_ProviderFragment(iface
);
1979 add_method_call(This
, FRAG_GET_RUNTIME_ID
);
1980 if (This
->expected_tid
)
1981 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
1982 This
->last_call_tid
= GetCurrentThreadId();
1985 if (This
->runtime_id
[0] || This
->runtime_id
[1])
1990 if (!(sa
= SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(This
->runtime_id
))))
1993 for (idx
= 0; idx
< ARRAY_SIZE(This
->runtime_id
); idx
++)
1994 SafeArrayPutElement(sa
, &idx
, (void *)&This
->runtime_id
[idx
]);
2002 static HRESULT WINAPI
ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment
*iface
,
2003 struct UiaRect
*ret_val
)
2005 struct Provider
*This
= impl_from_ProviderFragment(iface
);
2007 add_method_call(This
, FRAG_GET_BOUNDING_RECT
);
2008 if (This
->expected_tid
)
2009 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2010 This
->last_call_tid
= GetCurrentThreadId();
2012 *ret_val
= This
->bounds_rect
;
2016 static HRESULT WINAPI
ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment
*iface
,
2017 SAFEARRAY
**ret_val
)
2019 ok(0, "unexpected call\n");
2024 static HRESULT WINAPI
ProviderFragment_SetFocus(IRawElementProviderFragment
*iface
)
2026 ok(0, "unexpected call\n");
2030 static HRESULT WINAPI
ProviderFragment_get_FragmentRoot(IRawElementProviderFragment
*iface
,
2031 IRawElementProviderFragmentRoot
**ret_val
)
2033 struct Provider
*This
= impl_from_ProviderFragment(iface
);
2035 add_method_call(This
, FRAG_GET_FRAGMENT_ROOT
);
2036 if (This
->expected_tid
)
2037 ok(This
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2038 This
->last_call_tid
= GetCurrentThreadId();
2041 if (This
->frag_root
)
2043 *ret_val
= This
->frag_root
;
2044 IRawElementProviderFragmentRoot_AddRef(This
->frag_root
);
2050 static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl
= {
2051 ProviderFragment_QueryInterface
,
2052 ProviderFragment_AddRef
,
2053 ProviderFragment_Release
,
2054 ProviderFragment_Navigate
,
2055 ProviderFragment_GetRuntimeId
,
2056 ProviderFragment_get_BoundingRectangle
,
2057 ProviderFragment_GetEmbeddedFragmentRoots
,
2058 ProviderFragment_SetFocus
,
2059 ProviderFragment_get_FragmentRoot
,
2062 static inline struct Provider
*impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot
*iface
)
2064 return CONTAINING_RECORD(iface
, struct Provider
, IRawElementProviderFragmentRoot_iface
);
2067 static HRESULT WINAPI
ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot
*iface
, REFIID riid
,
2070 struct Provider
*Provider
= impl_from_ProviderFragmentRoot(iface
);
2071 return IRawElementProviderSimple_QueryInterface(&Provider
->IRawElementProviderSimple_iface
, riid
, ppv
);
2074 static ULONG WINAPI
ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot
*iface
)
2076 struct Provider
*Provider
= impl_from_ProviderFragmentRoot(iface
);
2077 return IRawElementProviderSimple_AddRef(&Provider
->IRawElementProviderSimple_iface
);
2080 static ULONG WINAPI
ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot
*iface
)
2082 struct Provider
*Provider
= impl_from_ProviderFragmentRoot(iface
);
2083 return IRawElementProviderSimple_Release(&Provider
->IRawElementProviderSimple_iface
);
2086 static HRESULT WINAPI
ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot
*iface
,
2087 double x
, double y
, IRawElementProviderFragment
**ret_val
)
2089 ok(0, "unexpected call\n");
2093 static HRESULT WINAPI
ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot
*iface
,
2094 IRawElementProviderFragment
**ret_val
)
2096 struct Provider
*Provider
= impl_from_ProviderFragmentRoot(iface
);
2098 add_method_call(Provider
, FRAG_ROOT_GET_FOCUS
);
2099 if (Provider
->expected_tid
)
2100 ok(Provider
->expected_tid
== GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2101 Provider
->last_call_tid
= GetCurrentThreadId();
2104 if (Provider
->focus_prov
)
2106 *ret_val
= Provider
->focus_prov
;
2107 IRawElementProviderFragment_AddRef(*ret_val
);
2113 static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl
= {
2114 ProviderFragmentRoot_QueryInterface
,
2115 ProviderFragmentRoot_AddRef
,
2116 ProviderFragmentRoot_Release
,
2117 ProviderFragmentRoot_ElementProviderFromPoint
,
2118 ProviderFragmentRoot_GetFocus
,
2121 static inline struct Provider
*impl_from_ProviderHwndOverride(IRawElementProviderHwndOverride
*iface
)
2123 return CONTAINING_RECORD(iface
, struct Provider
, IRawElementProviderHwndOverride_iface
);
2126 static HRESULT WINAPI
ProviderHwndOverride_QueryInterface(IRawElementProviderHwndOverride
*iface
, REFIID riid
,
2129 struct Provider
*Provider
= impl_from_ProviderHwndOverride(iface
);
2130 return IRawElementProviderSimple_QueryInterface(&Provider
->IRawElementProviderSimple_iface
, riid
, ppv
);
2133 static ULONG WINAPI
ProviderHwndOverride_AddRef(IRawElementProviderHwndOverride
*iface
)
2135 struct Provider
*Provider
= impl_from_ProviderHwndOverride(iface
);
2136 return IRawElementProviderSimple_AddRef(&Provider
->IRawElementProviderSimple_iface
);
2139 static ULONG WINAPI
ProviderHwndOverride_Release(IRawElementProviderHwndOverride
*iface
)
2141 struct Provider
*Provider
= impl_from_ProviderHwndOverride(iface
);
2142 return IRawElementProviderSimple_Release(&Provider
->IRawElementProviderSimple_iface
);
2145 static HRESULT WINAPI
ProviderHwndOverride_GetOverrideProviderForHwnd(IRawElementProviderHwndOverride
*iface
,
2146 HWND hwnd
, IRawElementProviderSimple
**ret_val
)
2148 struct Provider
*This
= impl_from_ProviderHwndOverride(iface
);
2150 add_method_call(This
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
);
2153 if (This
->override_hwnd
== hwnd
)
2155 return IRawElementProviderSimple_QueryInterface(&Provider_override
.IRawElementProviderSimple_iface
,
2156 &IID_IRawElementProviderSimple
, (void **)ret_val
);
2162 static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl
= {
2163 ProviderHwndOverride_QueryInterface
,
2164 ProviderHwndOverride_AddRef
,
2165 ProviderHwndOverride_Release
,
2166 ProviderHwndOverride_GetOverrideProviderForHwnd
,
2169 static inline struct Provider
*impl_from_ProviderValuePattern(IValueProvider
*iface
)
2171 return CONTAINING_RECORD(iface
, struct Provider
, IValueProvider_iface
);
2174 static HRESULT WINAPI
ProviderValuePattern_QueryInterface(IValueProvider
*iface
, REFIID riid
,
2177 struct Provider
*Provider
= impl_from_ProviderValuePattern(iface
);
2178 return IRawElementProviderSimple_QueryInterface(&Provider
->IRawElementProviderSimple_iface
, riid
, ppv
);
2181 static ULONG WINAPI
ProviderValuePattern_AddRef(IValueProvider
*iface
)
2183 struct Provider
*Provider
= impl_from_ProviderValuePattern(iface
);
2184 return IRawElementProviderSimple_AddRef(&Provider
->IRawElementProviderSimple_iface
);
2187 static ULONG WINAPI
ProviderValuePattern_Release(IValueProvider
*iface
)
2189 struct Provider
*Provider
= impl_from_ProviderValuePattern(iface
);
2190 return IRawElementProviderSimple_Release(&Provider
->IRawElementProviderSimple_iface
);
2193 static HRESULT WINAPI
ProviderValuePattern_SetValue(IValueProvider
*iface
, LPCWSTR val
)
2195 ok(0, "unexpected call\n");
2199 static HRESULT WINAPI
ProviderValuePattern_get_Value(IValueProvider
*iface
, BSTR
*ret_val
)
2201 ok(0, "unexpected call\n");
2205 static HRESULT WINAPI
ProviderValuePattern_get_IsReadOnly(IValueProvider
*iface
, BOOL
*ret_val
)
2207 struct Provider
*Provider
= impl_from_ProviderValuePattern(iface
);
2209 *ret_val
= Provider
->value_pattern_data
.is_read_only
;
2214 static const IValueProviderVtbl ProviderValuePatternVtbl
= {
2215 ProviderValuePattern_QueryInterface
,
2216 ProviderValuePattern_AddRef
,
2217 ProviderValuePattern_Release
,
2218 ProviderValuePattern_SetValue
,
2219 ProviderValuePattern_get_Value
,
2220 ProviderValuePattern_get_IsReadOnly
,
2223 static inline struct Provider
*impl_from_ProviderLegacyIAccessiblePattern(ILegacyIAccessibleProvider
*iface
)
2225 return CONTAINING_RECORD(iface
, struct Provider
, ILegacyIAccessibleProvider_iface
);
2228 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_QueryInterface(ILegacyIAccessibleProvider
*iface
, REFIID riid
,
2231 struct Provider
*Provider
= impl_from_ProviderLegacyIAccessiblePattern(iface
);
2232 return IRawElementProviderSimple_QueryInterface(&Provider
->IRawElementProviderSimple_iface
, riid
, ppv
);
2235 static ULONG WINAPI
ProviderLegacyIAccessiblePattern_AddRef(ILegacyIAccessibleProvider
*iface
)
2237 struct Provider
*Provider
= impl_from_ProviderLegacyIAccessiblePattern(iface
);
2238 return IRawElementProviderSimple_AddRef(&Provider
->IRawElementProviderSimple_iface
);
2241 static ULONG WINAPI
ProviderLegacyIAccessiblePattern_Release(ILegacyIAccessibleProvider
*iface
)
2243 struct Provider
*Provider
= impl_from_ProviderLegacyIAccessiblePattern(iface
);
2244 return IRawElementProviderSimple_Release(&Provider
->IRawElementProviderSimple_iface
);
2247 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_Select(ILegacyIAccessibleProvider
*iface
, LONG select_flags
)
2249 ok(0, "unexpected call\n");
2253 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider
*iface
)
2255 ok(0, "unexpected call\n");
2259 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider
*iface
, LPCWSTR val
)
2261 ok(0, "unexpected call\n");
2265 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider
*iface
,
2266 IAccessible
**out_acc
)
2268 ok(0, "unexpected call\n");
2272 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_ChildId(ILegacyIAccessibleProvider
*iface
, int *out_cid
)
2274 struct Provider
*Provider
= impl_from_ProviderLegacyIAccessiblePattern(iface
);
2276 *out_cid
= Provider
->legacy_acc_pattern_data
.child_id
;
2280 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider
*iface
, BSTR
*out_name
)
2282 ok(0, "unexpected call\n");
2286 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider
*iface
, BSTR
*out_value
)
2288 ok(0, "unexpected call\n");
2292 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider
*iface
,
2293 BSTR
*out_description
)
2295 ok(0, "unexpected call\n");
2299 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider
*iface
, DWORD
*out_role
)
2301 struct Provider
*Provider
= impl_from_ProviderLegacyIAccessiblePattern(iface
);
2303 *out_role
= Provider
->legacy_acc_pattern_data
.role
;
2307 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider
*iface
, DWORD
*out_state
)
2309 ok(0, "unexpected call\n");
2313 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider
*iface
, BSTR
*out_help
)
2315 ok(0, "unexpected call\n");
2319 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_KeyboardShortcut(ILegacyIAccessibleProvider
*iface
,
2320 BSTR
*out_kbd_shortcut
)
2322 ok(0, "unexpected call\n");
2326 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider
*iface
,
2327 SAFEARRAY
**out_selected
)
2329 ok(0, "unexpected call\n");
2333 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_DefaultAction(ILegacyIAccessibleProvider
*iface
,
2334 BSTR
*out_default_action
)
2336 ok(0, "unexpected call\n");
2340 static const ILegacyIAccessibleProviderVtbl ProviderLegacyIAccessiblePatternVtbl
= {
2341 ProviderLegacyIAccessiblePattern_QueryInterface
,
2342 ProviderLegacyIAccessiblePattern_AddRef
,
2343 ProviderLegacyIAccessiblePattern_Release
,
2344 ProviderLegacyIAccessiblePattern_Select
,
2345 ProviderLegacyIAccessiblePattern_DoDefaultAction
,
2346 ProviderLegacyIAccessiblePattern_SetValue
,
2347 ProviderLegacyIAccessiblePattern_GetIAccessible
,
2348 ProviderLegacyIAccessiblePattern_get_ChildId
,
2349 ProviderLegacyIAccessiblePattern_get_Name
,
2350 ProviderLegacyIAccessiblePattern_get_Value
,
2351 ProviderLegacyIAccessiblePattern_get_Description
,
2352 ProviderLegacyIAccessiblePattern_get_Role
,
2353 ProviderLegacyIAccessiblePattern_get_State
,
2354 ProviderLegacyIAccessiblePattern_get_Help
,
2355 ProviderLegacyIAccessiblePattern_get_KeyboardShortcut
,
2356 ProviderLegacyIAccessiblePattern_GetSelection
,
2357 ProviderLegacyIAccessiblePattern_get_DefaultAction
,
2360 static struct Provider Provider
=
2362 { &ProviderSimpleVtbl
},
2363 { &ProviderFragmentVtbl
},
2364 { &ProviderFragmentRootVtbl
},
2365 { &ProviderHwndOverrideVtbl
},
2366 { &ProviderValuePatternVtbl
},
2367 { &ProviderLegacyIAccessiblePatternVtbl
},
2372 &Provider_child
.IRawElementProviderFragment_iface
, &Provider_child2
.IRawElementProviderFragment_iface
,
2376 static struct Provider Provider2
=
2378 { &ProviderSimpleVtbl
},
2379 { &ProviderFragmentVtbl
},
2380 { &ProviderFragmentRootVtbl
},
2381 { &ProviderHwndOverrideVtbl
},
2382 { &ProviderValuePatternVtbl
},
2383 { &ProviderLegacyIAccessiblePatternVtbl
},
2392 static struct Provider Provider_child
=
2394 { &ProviderSimpleVtbl
},
2395 { &ProviderFragmentVtbl
},
2396 { &ProviderFragmentRootVtbl
},
2397 { &ProviderHwndOverrideVtbl
},
2398 { &ProviderValuePatternVtbl
},
2399 { &ProviderLegacyIAccessiblePatternVtbl
},
2402 &Provider
.IRawElementProviderFragment_iface
, &Provider
.IRawElementProviderFragmentRoot_iface
,
2403 NULL
, &Provider_child2
.IRawElementProviderFragment_iface
,
2405 ProviderOptions_ServerSideProvider
, 0, 0,
2408 static struct Provider Provider_child2
=
2410 { &ProviderSimpleVtbl
},
2411 { &ProviderFragmentVtbl
},
2412 { &ProviderFragmentRootVtbl
},
2413 { &ProviderHwndOverrideVtbl
},
2414 { &ProviderValuePatternVtbl
},
2415 { &ProviderLegacyIAccessiblePatternVtbl
},
2418 &Provider
.IRawElementProviderFragment_iface
, &Provider
.IRawElementProviderFragmentRoot_iface
,
2419 &Provider_child
.IRawElementProviderFragment_iface
, NULL
,
2421 ProviderOptions_ServerSideProvider
, 0, 0,
2424 static struct Provider Provider_hwnd
=
2426 { &ProviderSimpleVtbl
},
2427 { &ProviderFragmentVtbl
},
2428 { &ProviderFragmentRootVtbl
},
2429 { &ProviderHwndOverrideVtbl
},
2430 { &ProviderValuePatternVtbl
},
2431 { &ProviderLegacyIAccessiblePatternVtbl
},
2437 ProviderOptions_ClientSideProvider
, 0, 0,
2440 static struct Provider Provider_nc
=
2442 { &ProviderSimpleVtbl
},
2443 { &ProviderFragmentVtbl
},
2444 { &ProviderFragmentRootVtbl
},
2445 { &ProviderHwndOverrideVtbl
},
2446 { &ProviderValuePatternVtbl
},
2447 { &ProviderLegacyIAccessiblePatternVtbl
},
2453 ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
,
2457 static struct Provider Provider_proxy
=
2459 { &ProviderSimpleVtbl
},
2460 { &ProviderFragmentVtbl
},
2461 { &ProviderFragmentRootVtbl
},
2462 { &ProviderHwndOverrideVtbl
},
2463 { &ProviderValuePatternVtbl
},
2464 { &ProviderLegacyIAccessiblePatternVtbl
},
2470 ProviderOptions_ClientSideProvider
,
2474 static struct Provider Provider_proxy2
=
2476 { &ProviderSimpleVtbl
},
2477 { &ProviderFragmentVtbl
},
2478 { &ProviderFragmentRootVtbl
},
2479 { &ProviderHwndOverrideVtbl
},
2480 { &ProviderValuePatternVtbl
},
2481 { &ProviderLegacyIAccessiblePatternVtbl
},
2487 ProviderOptions_ClientSideProvider
,
2491 static struct Provider Provider_override
=
2493 { &ProviderSimpleVtbl
},
2494 { &ProviderFragmentVtbl
},
2495 { &ProviderFragmentRootVtbl
},
2496 { &ProviderHwndOverrideVtbl
},
2497 { &ProviderValuePatternVtbl
},
2498 { &ProviderLegacyIAccessiblePatternVtbl
},
2500 "Provider_override",
2504 ProviderOptions_ServerSideProvider
| ProviderOptions_OverrideProvider
,
2508 #define DEFINE_PROVIDER(name) \
2509 static struct Provider Provider_ ## name = \
2511 { &ProviderSimpleVtbl }, \
2512 { &ProviderFragmentVtbl }, \
2513 { &ProviderFragmentRootVtbl }, \
2514 { &ProviderHwndOverrideVtbl }, \
2515 { &ProviderValuePatternVtbl }, \
2516 { &ProviderLegacyIAccessiblePatternVtbl }, \
2518 "Provider_" # name "", \
2522 ProviderOptions_ServerSideProvider, 0, 0 \
2525 DEFINE_PROVIDER(hwnd_child
);
2526 DEFINE_PROVIDER(hwnd_child2
);
2527 DEFINE_PROVIDER(nc_child
);
2528 DEFINE_PROVIDER(nc_child2
);
2529 DEFINE_PROVIDER(child_child
);
2530 DEFINE_PROVIDER(child_child2
);
2531 DEFINE_PROVIDER(child2_child
);
2532 DEFINE_PROVIDER(child2_child_child
);
2533 DEFINE_PROVIDER(hwnd2
);
2534 DEFINE_PROVIDER(nc2
);
2535 DEFINE_PROVIDER(hwnd3
);
2536 DEFINE_PROVIDER(nc3
);
2538 static IAccessible
*acc_client
;
2539 static IRawElementProviderSimple
*prov_root
;
2540 static LRESULT WINAPI
test_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2545 if (lParam
== (DWORD
)OBJID_CLIENT
)
2547 CHECK_EXPECT(winproc_GETOBJECT_CLIENT
);
2549 return LresultFromObject(&IID_IAccessible
, wParam
, (IUnknown
*)acc_client
);
2553 else if (lParam
== UiaRootObjectId
)
2555 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot
);
2557 return UiaReturnRawElementProvider(hwnd
, wParam
, lParam
, prov_root
);
2568 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2571 static IRawElementProviderSimple
*child_win_prov_root
;
2572 static LRESULT WINAPI
child_test_wnd_proc(HWND hwnd
, UINT message
, WPARAM wParam
, LPARAM lParam
)
2577 if (lParam
== UiaRootObjectId
)
2579 CHECK_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
2580 if (child_win_prov_root
)
2581 return UiaReturnRawElementProvider(hwnd
, wParam
, lParam
, child_win_prov_root
);
2592 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
2595 static void test_UiaHostProviderFromHwnd(void)
2597 IRawElementProviderSimple
*p
, *p2
;
2598 enum ProviderOptions prov_opt
;
2606 cls
.lpfnWndProc
= test_wnd_proc
;
2609 cls
.hInstance
= GetModuleHandleA(NULL
);
2612 cls
.hbrBackground
= NULL
;
2613 cls
.lpszMenuName
= NULL
;
2614 cls
.lpszClassName
= "HostProviderFromHwnd class";
2616 RegisterClassA(&cls
);
2618 hwnd
= CreateWindowExA(0, "HostProviderFromHwnd class", "Test window 1",
2619 WS_CAPTION
| WS_SYSMENU
| WS_MINIMIZEBOX
| WS_MAXIMIZEBOX
| WS_VISIBLE
,
2620 0, 0, 100, 100, GetDesktopWindow(), NULL
, GetModuleHandleA(NULL
), NULL
);
2621 ok(hwnd
!= NULL
, "Failed to create a test window.\n");
2623 p
= (void *)0xdeadbeef;
2624 hr
= UiaHostProviderFromHwnd(NULL
, &p
);
2625 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2626 ok(p
== NULL
, "Unexpected instance.\n");
2628 hr
= UiaHostProviderFromHwnd(hwnd
, NULL
);
2629 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2632 hr
= UiaHostProviderFromHwnd(hwnd
, &p
);
2633 ok(hr
== S_OK
, "Failed to get host provider, hr %#lx.\n", hr
);
2636 hr
= UiaHostProviderFromHwnd(hwnd
, &p2
);
2637 ok(hr
== S_OK
, "Failed to get host provider, hr %#lx.\n", hr
);
2638 ok(p
!= p2
, "Unexpected instance.\n");
2639 IRawElementProviderSimple_Release(p2
);
2641 hr
= IRawElementProviderSimple_get_HostRawElementProvider(p
, &p2
);
2642 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2643 ok(p2
== NULL
, "Unexpected instance.\n");
2645 hr
= IRawElementProviderSimple_GetPropertyValue(p
, UIA_NativeWindowHandlePropertyId
, &v
);
2646 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2647 ok(V_VT(&v
) == VT_I4
, "V_VT(&v) = %d\n", V_VT(&v
));
2648 ok(V_I4(&v
) == HandleToUlong(hwnd
), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v
), HandleToUlong(hwnd
));
2650 hr
= IRawElementProviderSimple_GetPropertyValue(p
, UIA_ProviderDescriptionPropertyId
, &v
);
2651 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2652 ok(V_VT(&v
) == VT_BSTR
, "V_VT(&v) = %d\n", V_VT(&v
));
2655 /* No patterns are implemented on the HWND Host provider. */
2656 for (i
= UIA_InvokePatternId
; i
< (UIA_CustomNavigationPatternId
+ 1); i
++)
2660 unk
= (void *)0xdeadbeef;
2661 hr
= IRawElementProviderSimple_GetPatternProvider(p
, i
, &unk
);
2662 ok(hr
== S_OK
, "Unexpected hr %#lx, %d.\n", hr
, i
);
2663 ok(!unk
, "Pattern %d returned %p\n", i
, unk
);
2666 hr
= IRawElementProviderSimple_get_ProviderOptions(p
, &prov_opt
);
2667 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2668 ok((prov_opt
== ProviderOptions_ServerSideProvider
) ||
2669 broken(prov_opt
== ProviderOptions_ClientSideProvider
), /* Windows < 10 1507 */
2670 "Unexpected provider options %#x\n", prov_opt
);
2672 /* Test behavior post Window destruction. */
2673 DestroyWindow(hwnd
);
2675 hr
= IRawElementProviderSimple_GetPropertyValue(p
, UIA_NativeWindowHandlePropertyId
, &v
);
2676 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2677 ok(V_VT(&v
) == VT_I4
, "V_VT(&v) = %d\n", V_VT(&v
));
2678 ok(V_I4(&v
) == HandleToUlong(hwnd
), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v
), HandleToUlong(hwnd
));
2680 hr
= IRawElementProviderSimple_GetPropertyValue(p
, UIA_ProviderDescriptionPropertyId
, &v
);
2681 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2682 ok(V_VT(&v
) == VT_BSTR
, "V_VT(&v) = %d\n", V_VT(&v
));
2685 hr
= IRawElementProviderSimple_get_ProviderOptions(p
, &prov_opt
);
2686 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2687 ok((prov_opt
== ProviderOptions_ServerSideProvider
) ||
2688 broken(prov_opt
== ProviderOptions_ClientSideProvider
), /* Windows < 10 1507 */
2689 "Unexpected provider options %#x\n", prov_opt
);
2691 IRawElementProviderSimple_Release(p
);
2693 UnregisterClassA("HostProviderFromHwnd class", NULL
);
2696 static DWORD WINAPI
uia_reserved_val_iface_marshal_thread(LPVOID param
)
2698 IStream
**stream
= param
;
2699 IUnknown
*unk_ns
, *unk_ns2
, *unk_ma
, *unk_ma2
;
2702 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2704 hr
= CoGetInterfaceAndReleaseStream(stream
[0], &IID_IUnknown
, (void **)&unk_ns
);
2705 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2707 hr
= CoGetInterfaceAndReleaseStream(stream
[1], &IID_IUnknown
, (void **)&unk_ma
);
2708 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2710 hr
= UiaGetReservedNotSupportedValue(&unk_ns2
);
2711 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2713 hr
= UiaGetReservedMixedAttributeValue(&unk_ma2
);
2714 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2716 ok(unk_ns2
== unk_ns
, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2
, unk_ns
);
2717 ok(unk_ma2
== unk_ma
, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2
, unk_ma
);
2724 static void test_uia_reserved_value_ifaces(void)
2726 IUnknown
*unk_ns
, *unk_ns2
, *unk_ma
, *unk_ma2
;
2733 /* ReservedNotSupportedValue. */
2734 hr
= UiaGetReservedNotSupportedValue(NULL
);
2735 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2737 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
2738 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2739 ok(unk_ns
!= NULL
, "UiaGetReservedNotSupportedValue returned NULL interface.\n");
2741 refcnt
= IUnknown_AddRef(unk_ns
);
2742 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2744 refcnt
= IUnknown_AddRef(unk_ns
);
2745 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2747 refcnt
= IUnknown_Release(unk_ns
);
2748 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2750 hr
= UiaGetReservedNotSupportedValue(&unk_ns2
);
2751 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2752 ok(unk_ns2
!= NULL
, "UiaGetReservedNotSupportedValue returned NULL interface.");
2753 ok(unk_ns2
== unk_ns
, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2
, unk_ns
);
2756 hr
= IUnknown_QueryInterface(unk_ns
, &IID_IMarshal
, (void **)&marshal
);
2757 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2758 ok(marshal
!= NULL
, "Failed to get IMarshal interface.\n");
2760 refcnt
= IMarshal_AddRef(marshal
);
2761 ok(refcnt
== 2, "Expected refcnt %d, got %ld\n", 2, refcnt
);
2763 refcnt
= IMarshal_Release(marshal
);
2764 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2766 refcnt
= IMarshal_Release(marshal
);
2767 ok(refcnt
== 0, "Expected refcnt %d, got %ld\n", 0, refcnt
);
2769 /* ReservedMixedAttributeValue. */
2770 hr
= UiaGetReservedMixedAttributeValue(NULL
);
2771 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
2773 hr
= UiaGetReservedMixedAttributeValue(&unk_ma
);
2774 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2775 ok(unk_ma
!= NULL
, "UiaGetReservedMixedAttributeValue returned NULL interface.");
2777 refcnt
= IUnknown_AddRef(unk_ma
);
2778 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2780 refcnt
= IUnknown_AddRef(unk_ma
);
2781 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2783 refcnt
= IUnknown_Release(unk_ma
);
2784 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2786 hr
= UiaGetReservedMixedAttributeValue(&unk_ma2
);
2787 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2788 ok(unk_ma2
!= NULL
, "UiaGetReservedMixedAttributeValue returned NULL interface.");
2789 ok(unk_ma2
== unk_ma
, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2
, unk_ma
);
2792 hr
= IUnknown_QueryInterface(unk_ma
, &IID_IMarshal
, (void **)&marshal
);
2793 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2794 ok(marshal
!= NULL
, "Failed to get IMarshal interface.\n");
2796 refcnt
= IMarshal_AddRef(marshal
);
2797 ok(refcnt
== 2, "Expected refcnt %d, got %ld\n", 2, refcnt
);
2799 refcnt
= IMarshal_Release(marshal
);
2800 ok(refcnt
== 1, "Expected refcnt %d, got %ld\n", 1, refcnt
);
2802 refcnt
= IMarshal_Release(marshal
);
2803 ok(refcnt
== 0, "Expected refcnt %d, got %ld\n", 0, refcnt
);
2805 /* Test cross-thread marshaling behavior. */
2806 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
2808 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, unk_ns
, &stream
[0]);
2809 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2810 hr
= CoMarshalInterThreadInterfaceInStream(&IID_IUnknown
, unk_ma
, &stream
[1]);
2811 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2813 thread
= CreateThread(NULL
, 0, uia_reserved_val_iface_marshal_thread
, (void *)stream
, 0, NULL
);
2814 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
) != WAIT_OBJECT_0
)
2817 while(PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
2819 TranslateMessage(&msg
);
2820 DispatchMessageW(&msg
);
2823 CloseHandle(thread
);
2828 struct msaa_role_uia_type
{
2830 INT uia_control_type
;
2833 static const struct msaa_role_uia_type msaa_role_uia_types
[] = {
2834 { ROLE_SYSTEM_TITLEBAR
, UIA_TitleBarControlTypeId
},
2835 { ROLE_SYSTEM_MENUBAR
, UIA_MenuBarControlTypeId
},
2836 { ROLE_SYSTEM_SCROLLBAR
, UIA_ScrollBarControlTypeId
},
2837 { ROLE_SYSTEM_GRIP
, UIA_ThumbControlTypeId
},
2838 { ROLE_SYSTEM_WINDOW
, UIA_WindowControlTypeId
},
2839 { ROLE_SYSTEM_MENUPOPUP
, UIA_MenuControlTypeId
},
2840 { ROLE_SYSTEM_MENUITEM
, UIA_MenuItemControlTypeId
},
2841 { ROLE_SYSTEM_TOOLTIP
, UIA_ToolTipControlTypeId
},
2842 { ROLE_SYSTEM_APPLICATION
, UIA_WindowControlTypeId
},
2843 { ROLE_SYSTEM_DOCUMENT
, UIA_DocumentControlTypeId
},
2844 { ROLE_SYSTEM_PANE
, UIA_PaneControlTypeId
},
2845 { ROLE_SYSTEM_GROUPING
, UIA_GroupControlTypeId
},
2846 { ROLE_SYSTEM_SEPARATOR
, UIA_SeparatorControlTypeId
},
2847 { ROLE_SYSTEM_TOOLBAR
, UIA_ToolBarControlTypeId
},
2848 { ROLE_SYSTEM_STATUSBAR
, UIA_StatusBarControlTypeId
},
2849 { ROLE_SYSTEM_TABLE
, UIA_TableControlTypeId
},
2850 { ROLE_SYSTEM_COLUMNHEADER
, UIA_HeaderControlTypeId
},
2851 { ROLE_SYSTEM_ROWHEADER
, UIA_HeaderControlTypeId
},
2852 { ROLE_SYSTEM_CELL
, UIA_DataItemControlTypeId
},
2853 { ROLE_SYSTEM_LINK
, UIA_HyperlinkControlTypeId
},
2854 { ROLE_SYSTEM_LIST
, UIA_ListControlTypeId
},
2855 { ROLE_SYSTEM_LISTITEM
, UIA_ListItemControlTypeId
},
2856 { ROLE_SYSTEM_OUTLINE
, UIA_TreeControlTypeId
},
2857 { ROLE_SYSTEM_OUTLINEITEM
, UIA_TreeItemControlTypeId
},
2858 { ROLE_SYSTEM_PAGETAB
, UIA_TabItemControlTypeId
},
2859 { ROLE_SYSTEM_INDICATOR
, UIA_ThumbControlTypeId
},
2860 { ROLE_SYSTEM_GRAPHIC
, UIA_ImageControlTypeId
},
2861 { ROLE_SYSTEM_STATICTEXT
, UIA_TextControlTypeId
},
2862 { ROLE_SYSTEM_TEXT
, UIA_EditControlTypeId
},
2863 { ROLE_SYSTEM_PUSHBUTTON
, UIA_ButtonControlTypeId
},
2864 { ROLE_SYSTEM_CHECKBUTTON
, UIA_CheckBoxControlTypeId
},
2865 { ROLE_SYSTEM_RADIOBUTTON
, UIA_RadioButtonControlTypeId
},
2866 { ROLE_SYSTEM_COMBOBOX
, UIA_ComboBoxControlTypeId
},
2867 { ROLE_SYSTEM_PROGRESSBAR
, UIA_ProgressBarControlTypeId
},
2868 { ROLE_SYSTEM_SLIDER
, UIA_SliderControlTypeId
},
2869 { ROLE_SYSTEM_SPINBUTTON
, UIA_SpinnerControlTypeId
},
2870 { ROLE_SYSTEM_BUTTONDROPDOWN
, UIA_SplitButtonControlTypeId
},
2871 { ROLE_SYSTEM_BUTTONMENU
, UIA_MenuItemControlTypeId
},
2872 { ROLE_SYSTEM_BUTTONDROPDOWNGRID
, UIA_ButtonControlTypeId
},
2873 { ROLE_SYSTEM_PAGETABLIST
, UIA_TabControlTypeId
},
2874 { ROLE_SYSTEM_SPLITBUTTON
, UIA_SplitButtonControlTypeId
},
2875 /* These accessible roles have no equivalent in UI Automation. */
2876 { ROLE_SYSTEM_SOUND
, 0 },
2877 { ROLE_SYSTEM_CURSOR
, 0 },
2878 { ROLE_SYSTEM_CARET
, 0 },
2879 { ROLE_SYSTEM_ALERT
, 0 },
2880 { ROLE_SYSTEM_CLIENT
, 0 },
2881 { ROLE_SYSTEM_CHART
, 0 },
2882 { ROLE_SYSTEM_DIALOG
, 0 },
2883 { ROLE_SYSTEM_BORDER
, 0 },
2884 { ROLE_SYSTEM_COLUMN
, 0 },
2885 { ROLE_SYSTEM_ROW
, 0 },
2886 { ROLE_SYSTEM_HELPBALLOON
, 0 },
2887 { ROLE_SYSTEM_CHARACTER
, 0 },
2888 { ROLE_SYSTEM_PROPERTYPAGE
, 0 },
2889 { ROLE_SYSTEM_DROPLIST
, 0 },
2890 { ROLE_SYSTEM_DIAL
, 0 },
2891 { ROLE_SYSTEM_HOTKEYFIELD
, 0 },
2892 { ROLE_SYSTEM_DIAGRAM
, 0 },
2893 { ROLE_SYSTEM_ANIMATION
, 0 },
2894 { ROLE_SYSTEM_EQUATION
, 0 },
2895 { ROLE_SYSTEM_WHITESPACE
, 0 },
2896 { ROLE_SYSTEM_IPADDRESS
, 0 },
2897 { ROLE_SYSTEM_OUTLINEBUTTON
, 0 },
2900 struct msaa_state_uia_prop
{
2905 static const struct msaa_state_uia_prop msaa_state_uia_props
[] = {
2906 { STATE_SYSTEM_FOCUSED
, UIA_HasKeyboardFocusPropertyId
},
2907 { STATE_SYSTEM_FOCUSABLE
, UIA_IsKeyboardFocusablePropertyId
},
2908 { ~STATE_SYSTEM_UNAVAILABLE
, UIA_IsEnabledPropertyId
},
2909 { STATE_SYSTEM_PROTECTED
, UIA_IsPasswordPropertyId
},
2912 static void set_accessible_props(struct Accessible
*acc
, INT role
, INT state
,
2913 LONG child_count
, LPCWSTR name
, LONG left
, LONG top
, LONG width
, LONG height
)
2918 acc
->child_count
= child_count
;
2923 acc
->height
= height
;
2926 static void set_accessible_ia2_props(struct Accessible
*acc
, BOOL enable_ia2
, LONG unique_id
)
2928 acc
->enable_ia2
= enable_ia2
;
2929 acc
->unique_id
= unique_id
;
2932 static void test_uia_prov_from_acc_ia2(void)
2934 IRawElementProviderSimple
*elprov
, *elprov2
;
2937 /* Only one exposes an IA2 interface, no match. */
2938 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, 0, 0, L
"acc_name", 0, 0, 0, 0);
2939 set_accessible_ia2_props(&Accessible
, TRUE
, 0);
2940 set_accessible_props(&Accessible2
, ROLE_SYSTEM_TEXT
, 0, 0, L
"acc_name", 0, 0, 0, 0);
2941 set_accessible_ia2_props(&Accessible2
, FALSE
, 0);
2943 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
2944 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2945 if (Accessible
.ref
!= 3)
2947 IRawElementProviderSimple_Release(elprov
);
2948 win_skip("UiaProviderFromIAccessible has no IAccessible2 support, skipping tests.\n");
2952 acc_client
= &Accessible2
.IAccessible_iface
;
2953 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
2954 /* The four below are only called on Win10v1909. */
2955 SET_EXPECT(Accessible_get_accRole
);
2956 SET_EXPECT(Accessible2_get_accRole
);
2957 SET_EXPECT(Accessible2_QI_IAccIdentity
);
2958 SET_EXPECT(Accessible2_get_accParent
);
2959 elprov2
= (void *)0xdeadbeef;
2960 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
2961 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2962 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
2963 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
2964 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
2967 * Win10v1909 has IAccessible2 support, but it's not used for checking if
2968 * two IAccessible interfaces match. Skip the comparison tests for this
2971 if (called_Accessible_get_accRole
)
2973 IRawElementProviderSimple_Release(elprov
);
2974 CHECK_CALLED(Accessible_get_accRole
);
2975 CHECK_CALLED(Accessible2_get_accRole
);
2976 CHECK_CALLED(Accessible2_QI_IAccIdentity
);
2977 CHECK_CALLED(Accessible2_get_accParent
);
2978 win_skip("Win10v1909 doesn't support IAccessible2 interface comparsion, skipping tests.\n");
2981 called_Accessible_get_accRole
= expect_Accessible_get_accRole
= 0;
2982 called_Accessible2_get_accRole
= expect_Accessible2_get_accRole
= 0;
2983 called_Accessible2_QI_IAccIdentity
= expect_Accessible2_QI_IAccIdentity
= 0;
2984 called_Accessible2_get_accParent
= expect_Accessible2_get_accParent
= 0;
2986 Accessible
.role
= Accessible2
.role
= 0;
2987 elprov2
= (void *)0xdeadbeef;
2989 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
2990 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
2991 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
2993 IRawElementProviderSimple_Release(elprov
);
2994 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
2997 * If &Accessible returns a failure code on get_uniqueID, &Accessible2's
2998 * uniqueID is not checked.
3000 set_accessible_ia2_props(&Accessible
, TRUE
, 0);
3001 set_accessible_ia2_props(&Accessible2
, TRUE
, 0);
3002 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3003 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3004 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3006 acc_client
= &Accessible2
.IAccessible_iface
;
3007 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3008 SET_EXPECT(Accessible_get_accRole
);
3009 SET_EXPECT(Accessible_get_accState
);
3010 SET_EXPECT(Accessible_get_accChildCount
);
3011 SET_EXPECT(Accessible_accLocation
);
3012 SET_EXPECT(Accessible_get_accName
);
3013 SET_EXPECT(Accessible_get_uniqueID
);
3014 SET_EXPECT(Accessible2_get_accChildCount
);
3015 SET_EXPECT(Accessible2_get_accName
);
3016 SET_EXPECT(Accessible2_QI_IAccIdentity
);
3017 SET_EXPECT(Accessible2_get_accParent
);
3018 elprov2
= (void *)0xdeadbeef;
3019 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3020 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3021 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
3022 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
3023 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
3024 CHECK_CALLED(Accessible_get_accRole
);
3025 CHECK_CALLED(Accessible_get_accState
);
3026 CHECK_CALLED(Accessible_get_accChildCount
);
3027 CHECK_CALLED(Accessible_accLocation
);
3028 CHECK_CALLED(Accessible_get_accName
);
3029 CHECK_CALLED(Accessible_get_uniqueID
);
3030 CHECK_CALLED(Accessible2_get_accChildCount
);
3031 CHECK_CALLED(Accessible2_get_accName
);
3032 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
3033 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
3034 IRawElementProviderSimple_Release(elprov2
);
3036 elprov2
= (void *)0xdeadbeef;
3038 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3039 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3040 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
3041 IRawElementProviderSimple_Release(elprov2
);
3043 IRawElementProviderSimple_Release(elprov
);
3044 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3046 /* Unique ID matches. */
3047 set_accessible_ia2_props(&Accessible
, TRUE
, 1);
3048 set_accessible_ia2_props(&Accessible2
, TRUE
, 1);
3049 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3050 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3051 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3053 acc_client
= &Accessible2
.IAccessible_iface
;
3054 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3055 SET_EXPECT(Accessible_get_uniqueID
);
3056 SET_EXPECT(Accessible2_get_uniqueID
);
3057 elprov2
= (void *)0xdeadbeef;
3058 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3059 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3060 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
3061 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
3062 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
3063 CHECK_CALLED(Accessible_get_uniqueID
);
3064 CHECK_CALLED(Accessible2_get_uniqueID
);
3065 IRawElementProviderSimple_Release(elprov2
);
3067 elprov2
= (void *)0xdeadbeef;
3069 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3070 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3071 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
3072 IRawElementProviderSimple_Release(elprov2
);
3074 IRawElementProviderSimple_Release(elprov
);
3075 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3077 /* Unique ID mismatch. */
3078 set_accessible_ia2_props(&Accessible
, TRUE
, 1);
3079 set_accessible_ia2_props(&Accessible2
, TRUE
, 2);
3080 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3081 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3082 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3084 acc_client
= &Accessible2
.IAccessible_iface
;
3085 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3086 SET_EXPECT(Accessible_get_uniqueID
);
3087 SET_EXPECT(Accessible2_get_uniqueID
);
3088 elprov2
= (void *)0xdeadbeef;
3089 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3090 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3091 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
3092 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
3093 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
3094 CHECK_CALLED(Accessible_get_uniqueID
);
3095 CHECK_CALLED(Accessible2_get_uniqueID
);
3097 elprov2
= (void *)0xdeadbeef;
3099 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3100 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3101 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
3103 IRawElementProviderSimple_Release(elprov
);
3104 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3106 set_accessible_props(&Accessible
, 0, 0, 0, NULL
, 0, 0, 0, 0);
3107 set_accessible_ia2_props(&Accessible
, FALSE
, 0);
3108 set_accessible_props(&Accessible2
, 0, 0, 0, NULL
, 0, 0, 0, 0);
3109 set_accessible_ia2_props(&Accessible2
, FALSE
, 0);
3112 #define check_fragment_acc( fragment, acc, cid) \
3113 check_fragment_acc_( (fragment), (acc), (cid), __LINE__)
3114 static void check_fragment_acc_(IRawElementProviderFragment
*elfrag
, IAccessible
*acc
,
3117 ILegacyIAccessibleProvider
*accprov
;
3118 IAccessible
*accessible
;
3122 hr
= IRawElementProviderFragment_QueryInterface(elfrag
, &IID_ILegacyIAccessibleProvider
, (void **)&accprov
);
3123 ok_(__FILE__
, line
) (hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3124 ok_(__FILE__
, line
) (!!accprov
, "accprov == NULL\n");
3126 hr
= ILegacyIAccessibleProvider_GetIAccessible(accprov
, &accessible
);
3127 ok_(__FILE__
, line
) (hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3128 ok_(__FILE__
, line
) (accessible
== acc
, "accessible != acc\n");
3129 IAccessible_Release(accessible
);
3131 hr
= ILegacyIAccessibleProvider_get_ChildId(accprov
, &child_id
);
3132 ok_(__FILE__
, line
) (hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3133 ok_(__FILE__
, line
) (child_id
== cid
, "child_id != cid\n");
3135 ILegacyIAccessibleProvider_Release(accprov
);
3138 static void test_uia_prov_from_acc_navigation(void)
3140 IRawElementProviderFragment
*elfrag
, *elfrag2
, *elfrag3
;
3141 IRawElementProviderSimple
*elprov
, *elprov2
;
3145 * Full IAccessible parent, with 4 children:
3146 * childid 1 is a simple element, with STATE_SYSTEM_INVISIBLE.
3147 * childid 2 is Accessible_child.
3148 * childid 3 is a simple element with STATE_SYSTEM_NORMAL.
3149 * childid 4 is Accessible_child2.
3151 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3152 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3153 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3155 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragment
, (void **)&elfrag
);
3156 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3157 ok(!!elfrag
, "elfrag == NULL\n");
3160 * First time doing NavigateDirection_Parent will result in the same root
3161 * accessible check as get_HostRawElementProvider. If this IAccessible is
3162 * the root for its associated HWND, NavigateDirection_Parent and
3163 * NavigateDirection_Next/PreviousSibling will do nothing, as UI Automation
3164 * provides non-client area providers for the root IAccessible's parent
3167 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 4,
3168 L
"acc_name", 0, 0, 50, 50);
3169 set_accessible_props(&Accessible2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 4,
3170 L
"acc_name", 0, 0, 50, 50);
3171 acc_client
= &Accessible2
.IAccessible_iface
;
3172 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3173 SET_EXPECT(Accessible_get_accRole
);
3174 SET_EXPECT(Accessible_get_accState
);
3175 SET_EXPECT(Accessible_get_accChildCount
);
3176 SET_EXPECT(Accessible_accLocation
);
3177 SET_EXPECT(Accessible_get_accName
);
3178 SET_EXPECT(Accessible2_get_accRole
);
3179 SET_EXPECT(Accessible2_get_accState
);
3180 SET_EXPECT(Accessible2_get_accChildCount
);
3181 SET_EXPECT(Accessible2_accLocation
);
3182 SET_EXPECT(Accessible2_get_accName
);
3183 SET_EXPECT(Accessible2_QI_IAccIdentity
);
3184 SET_EXPECT(Accessible2_get_accParent
);
3185 elfrag2
= (void *)0xdeadbeef;
3186 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_Parent
, &elfrag2
);
3187 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3188 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3189 ok(!elfrag2
, "elfrag2 != NULL\n");
3190 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
3191 CHECK_CALLED(Accessible_get_accRole
);
3192 CHECK_CALLED(Accessible_get_accState
);
3193 CHECK_CALLED(Accessible_get_accChildCount
);
3194 CHECK_CALLED(Accessible_accLocation
);
3195 CHECK_CALLED(Accessible_get_accName
);
3196 CHECK_CALLED(Accessible2_get_accRole
);
3197 CHECK_CALLED(Accessible2_get_accState
);
3198 CHECK_CALLED(Accessible2_get_accChildCount
);
3199 CHECK_CALLED(Accessible2_accLocation
);
3200 CHECK_CALLED(Accessible2_get_accName
);
3201 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
3202 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
3205 /* No check against root IAccessible, since it was done previously. */
3206 elprov2
= (void *)0xdeadbeef;
3207 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3208 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3209 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
3210 IRawElementProviderSimple_Release(elprov2
);
3213 elfrag2
= (void *)0xdeadbeef;
3214 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_Parent
, &elfrag2
);
3215 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3216 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3217 ok(!elfrag2
, "elfrag2 != NULL\n");
3219 elfrag2
= (void *)0xdeadbeef;
3220 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_NextSibling
, &elfrag2
);
3221 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3222 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3223 ok(!elfrag2
, "elfrag2 != NULL\n");
3225 elfrag2
= (void *)0xdeadbeef;
3226 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_PreviousSibling
, &elfrag2
);
3227 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3228 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3229 ok(!elfrag2
, "elfrag2 != NULL\n");
3232 * Retrieve childid 2 (Accessible_child) as first child. childid 1 is skipped due to
3233 * having a state of STATE_SYSTEM_INVISIBLE.
3235 set_accessible_props(&Accessible_child
, 0, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
3236 set_accessible_props(&Accessible_child2
, 0, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
3237 SET_EXPECT_MULTI(Accessible_get_accChildCount
, 3);
3238 SET_EXPECT_MULTI(Accessible_get_accChild
, 2);
3239 SET_EXPECT(Accessible_get_accState
);
3240 SET_EXPECT(Accessible_child_get_accState
);
3241 SET_EXPECT(Accessible_child_accNavigate
);
3242 SET_EXPECT(Accessible_child_get_accParent
);
3243 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_FirstChild
, &elfrag2
);
3244 ok(Accessible_child
.ref
== 2, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3245 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3246 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3247 ok(!!elfrag2
, "elfrag2 == NULL\n");
3248 CHECK_CALLED_MULTI(Accessible_get_accChildCount
, 3);
3249 CHECK_CALLED_MULTI(Accessible_get_accChild
, 2);
3250 CHECK_CALLED(Accessible_child_get_accState
);
3251 CHECK_CALLED(Accessible_child_accNavigate
);
3252 CHECK_CALLED(Accessible_child_get_accParent
);
3254 check_fragment_acc(elfrag2
, &Accessible_child
.IAccessible_iface
, CHILDID_SELF
);
3255 SET_EXPECT(Accessible_get_accChildCount
);
3256 SET_EXPECT(Accessible_get_accChild
);
3257 SET_EXPECT(Accessible_get_accState
);
3258 hr
= IRawElementProviderFragment_Navigate(elfrag2
, NavigateDirection_NextSibling
, &elfrag3
);
3259 ok(Accessible
.ref
== 5, "Unexpected refcnt %ld\n", Accessible
.ref
);
3260 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3261 ok(!!elfrag3
, "elfrag2 == NULL\n");
3262 CHECK_CALLED(Accessible_get_accChildCount
);
3263 CHECK_CALLED(Accessible_get_accChild
);
3264 CHECK_CALLED(Accessible_get_accState
);
3265 check_fragment_acc(elfrag3
, &Accessible
.IAccessible_iface
, 3);
3267 IRawElementProviderFragment_Release(elfrag3
);
3268 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3269 IRawElementProviderFragment_Release(elfrag2
);
3270 ok(Accessible_child
.ref
== 1, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3271 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3273 /* Retrieve childid 3 as first child now that Accessible_child is invisible. */
3274 set_accessible_props(&Accessible_child
, 0, STATE_SYSTEM_INVISIBLE
, 0, NULL
, 0, 0, 0, 0);
3275 SET_EXPECT_MULTI(Accessible_get_accChildCount
, 4);
3276 SET_EXPECT_MULTI(Accessible_get_accChild
, 3);
3277 SET_EXPECT_MULTI(Accessible_get_accState
, 2);
3278 SET_EXPECT(Accessible_child_get_accState
);
3279 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_FirstChild
, &elfrag2
);
3280 ok(Accessible
.ref
== 4, "Unexpected refcnt %ld\n", Accessible
.ref
);
3281 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3282 ok(!!elfrag2
, "elfrag2 == NULL\n");
3283 CHECK_CALLED_MULTI(Accessible_get_accChildCount
, 4);
3284 CHECK_CALLED_MULTI(Accessible_get_accChild
, 3);
3285 CHECK_CALLED_MULTI(Accessible_get_accState
, 2);
3286 CHECK_CALLED(Accessible_child_get_accState
);
3287 check_fragment_acc(elfrag2
, &Accessible
.IAccessible_iface
, 3);
3288 IRawElementProviderFragment_Release(elfrag2
);
3289 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3291 /* Retrieve childid 4 (Accessible_child2) as last child. */
3292 set_accessible_props(&Accessible_child2
, 0, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
3293 SET_EXPECT_MULTI(Accessible_get_accChildCount
, 2);
3294 SET_EXPECT(Accessible_get_accChild
);
3295 SET_EXPECT(Accessible_child2_get_accState
);
3296 SET_EXPECT(Accessible_child2_accNavigate
);
3297 SET_EXPECT(Accessible_child2_get_accParent
);
3298 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_LastChild
, &elfrag2
);
3299 ok(Accessible_child2
.ref
== 2, "Unexpected refcnt %ld\n", Accessible_child2
.ref
);
3300 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3301 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3302 ok(!!elfrag2
, "elfrag2 == NULL\n");
3303 CHECK_CALLED_MULTI(Accessible_get_accChildCount
, 2);
3304 CHECK_CALLED(Accessible_get_accChild
);
3305 CHECK_CALLED(Accessible_child2_get_accState
);
3306 CHECK_CALLED(Accessible_child2_accNavigate
);
3307 CHECK_CALLED(Accessible_child2_get_accParent
);
3309 check_fragment_acc(elfrag2
, &Accessible_child2
.IAccessible_iface
, CHILDID_SELF
);
3310 SET_EXPECT(Accessible_get_accChildCount
);
3311 SET_EXPECT(Accessible_get_accChild
);
3312 SET_EXPECT(Accessible_get_accState
);
3313 hr
= IRawElementProviderFragment_Navigate(elfrag2
, NavigateDirection_PreviousSibling
, &elfrag3
);
3314 ok(Accessible
.ref
== 5, "Unexpected refcnt %ld\n", Accessible
.ref
);
3315 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3316 ok(!!elfrag3
, "elfrag2 == NULL\n");
3317 CHECK_CALLED(Accessible_get_accChildCount
);
3318 CHECK_CALLED(Accessible_get_accChild
);
3319 CHECK_CALLED(Accessible_get_accState
);
3320 check_fragment_acc(elfrag3
, &Accessible
.IAccessible_iface
, 3);
3322 IRawElementProviderFragment_Release(elfrag3
);
3323 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3324 IRawElementProviderFragment_Release(elfrag2
);
3325 ok(Accessible_child2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible_child2
.ref
);
3326 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3328 /* Retrieve childid 3 as last child, now that Accessible_child2 is STATE_SYSTEM_INVISIBLE. */
3329 set_accessible_props(&Accessible_child2
, 0, STATE_SYSTEM_INVISIBLE
, 0, NULL
, 0, 0, 0, 0);
3330 SET_EXPECT_MULTI(Accessible_get_accChildCount
, 3);
3331 SET_EXPECT_MULTI(Accessible_get_accChild
, 2);
3332 SET_EXPECT(Accessible_get_accState
);
3333 SET_EXPECT(Accessible_child2_get_accState
);
3334 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_LastChild
, &elfrag2
);
3335 ok(Accessible
.ref
== 4, "Unexpected refcnt %ld\n", Accessible
.ref
);
3336 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3337 ok(!!elfrag2
, "elfrag2 == NULL\n");
3338 CHECK_CALLED_MULTI(Accessible_get_accChildCount
, 3);
3339 CHECK_CALLED_MULTI(Accessible_get_accChild
, 2);
3340 CHECK_CALLED(Accessible_get_accState
);
3341 CHECK_CALLED(Accessible_child2_get_accState
);
3342 check_fragment_acc(elfrag2
, &Accessible
.IAccessible_iface
, 3);
3343 IRawElementProviderFragment_Release(elfrag2
);
3344 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3346 IRawElementProviderFragment_Release(elfrag
);
3347 IRawElementProviderSimple_Release(elprov
);
3348 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3351 * Full IAccessible child tests.
3353 SET_EXPECT(Accessible_child_accNavigate
);
3354 SET_EXPECT(Accessible_child_get_accParent
);
3355 hr
= pUiaProviderFromIAccessible(&Accessible_child
.IAccessible_iface
, 0, UIA_PFIA_DEFAULT
, &elprov
);
3356 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3357 CHECK_CALLED(Accessible_child_accNavigate
);
3358 CHECK_CALLED(Accessible_child_get_accParent
);
3359 ok(Accessible_child
.ref
== 2, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3361 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragment
, (void **)&elfrag
);
3362 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3363 ok(!!elfrag
, "elfrag == NULL\n");
3366 * After determining this isn't the root IAccessible, get_accParent will
3367 * be used to get the parent.
3369 set_accessible_props(&Accessible2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
3370 set_accessible_props(&Accessible_child
, ROLE_SYSTEM_CLIENT
, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
3371 acc_client
= &Accessible2
.IAccessible_iface
;
3372 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3373 SET_EXPECT(Accessible_child_get_accRole
);
3374 SET_EXPECT(Accessible_child_get_accParent
);
3375 SET_EXPECT(Accessible2_get_accRole
);
3376 SET_EXPECT(Accessible2_QI_IAccIdentity
);
3377 SET_EXPECT(Accessible2_get_accParent
);
3378 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_Parent
, &elfrag2
);
3379 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3380 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3381 ok(!!elfrag2
, "elfrag2 == NULL\n");
3382 CHECK_CALLED(Accessible_child_get_accParent
);
3383 CHECK_CALLED(Accessible_child_get_accRole
);
3384 CHECK_CALLED(Accessible2_get_accRole
);
3385 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
3386 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
3387 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
3388 check_fragment_acc(elfrag2
, &Accessible
.IAccessible_iface
, CHILDID_SELF
);
3389 IRawElementProviderFragment_Release(elfrag2
);
3390 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3393 /* Second call only does get_accParent, no root check. */
3394 SET_EXPECT(Accessible_child_get_accParent
);
3395 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_Parent
, &elfrag2
);
3396 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3397 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3398 ok(!!elfrag2
, "elfrag2 == NULL\n");
3399 CHECK_CALLED(Accessible_child_get_accParent
);
3400 check_fragment_acc(elfrag2
, &Accessible
.IAccessible_iface
, CHILDID_SELF
);
3401 IRawElementProviderFragment_Release(elfrag2
);
3402 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3404 /* ChildCount of 0, do nothing for First/Last child.*/
3405 SET_EXPECT(Accessible_child_get_accChildCount
);
3406 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_FirstChild
, &elfrag2
);
3407 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3408 ok(!elfrag2
, "elfrag2 != NULL\n");
3409 CHECK_CALLED(Accessible_child_get_accChildCount
);
3411 SET_EXPECT(Accessible_child_get_accChildCount
);
3412 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_LastChild
, &elfrag2
);
3413 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3414 ok(!elfrag2
, "elfrag2 != NULL\n");
3415 CHECK_CALLED(Accessible_child_get_accChildCount
);
3418 * In the case of sibling navigation on an IAccessible that wasn't
3419 * received through previous navigation from a parent (i.e, from
3420 * NavigateDirection_First/LastChild), we have to figure out which
3421 * IAccessible child we represent by comparing against all children of our
3422 * IAccessible parent. If we find more than one IAccessible that matches,
3423 * or none at all that do, navigation will fail.
3425 set_accessible_props(&Accessible_child
, ROLE_SYSTEM_CLIENT
, STATE_SYSTEM_FOCUSABLE
, 1,
3426 L
"acc_child", 0, 0, 50, 50);
3427 set_accessible_props(&Accessible_child2
, ROLE_SYSTEM_CLIENT
, STATE_SYSTEM_FOCUSABLE
, 1,
3428 L
"acc_child", 0, 0, 50, 50);
3429 SET_EXPECT_MULTI(Accessible_get_accChildCount
, 5);
3430 SET_EXPECT_MULTI(Accessible_get_accChild
, 4);
3431 SET_EXPECT(Accessible_child_get_accParent
);
3432 SET_EXPECT(Accessible_child_get_accRole
);
3433 SET_EXPECT(Accessible_child_get_accState
);
3434 SET_EXPECT(Accessible_child_get_accChildCount
);
3435 SET_EXPECT(Accessible_child_accLocation
);
3436 SET_EXPECT(Accessible_child_get_accName
);
3437 SET_EXPECT(Accessible_child2_get_accRole
);
3438 SET_EXPECT(Accessible_child2_get_accState
);
3439 SET_EXPECT(Accessible_child2_get_accChildCount
);
3440 SET_EXPECT(Accessible_child2_accLocation
);
3441 SET_EXPECT(Accessible_child2_get_accName
);
3442 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_NextSibling
, &elfrag2
);
3443 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3444 ok(!elfrag2
, "elfrag2 != NULL\n");
3445 CHECK_CALLED_MULTI(Accessible_get_accChildCount
, 5);
3446 CHECK_CALLED_MULTI(Accessible_get_accChild
, 4);
3447 CHECK_CALLED(Accessible_child_get_accParent
);
3448 CHECK_CALLED(Accessible_child_get_accRole
);
3449 CHECK_CALLED(Accessible_child_get_accState
);
3450 CHECK_CALLED(Accessible_child_get_accChildCount
);
3451 CHECK_CALLED(Accessible_child_accLocation
);
3452 CHECK_CALLED(Accessible_child_get_accName
);
3453 CHECK_CALLED(Accessible_child2_get_accRole
);
3454 CHECK_CALLED(Accessible_child2_get_accState
);
3455 CHECK_CALLED(Accessible_child2_get_accChildCount
);
3456 CHECK_CALLED(Accessible_child2_accLocation
);
3457 CHECK_CALLED(Accessible_child2_get_accName
);
3459 /* Now they have a role mismatch, we can determine our position. */
3460 set_accessible_props(&Accessible_child2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1,
3461 L
"acc_child", 0, 0, 50, 50);
3462 SET_EXPECT_MULTI(Accessible_get_accChildCount
, 6);
3463 SET_EXPECT_MULTI(Accessible_get_accChild
, 5);
3464 /* Check ChildID 1 for STATE_SYSTEM_INVISIBLE. */
3465 SET_EXPECT(Accessible_get_accState
);
3466 SET_EXPECT(Accessible_child_get_accParent
);
3467 SET_EXPECT(Accessible_child_get_accRole
);
3468 SET_EXPECT(Accessible_child2_get_accRole
);
3469 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_PreviousSibling
, &elfrag2
);
3471 * Even though we didn't get a new fragment, now that we know our
3472 * position, a reference is added to the parent IAccessible.
3474 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3475 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3476 ok(!elfrag2
, "elfrag2 != NULL\n");
3477 CHECK_CALLED_MULTI(Accessible_get_accChildCount
, 6);
3478 CHECK_CALLED_MULTI(Accessible_get_accChild
, 5);
3479 CHECK_CALLED(Accessible_get_accState
);
3480 CHECK_CALLED(Accessible_child_get_accParent
);
3481 CHECK_CALLED(Accessible_child_get_accRole
);
3482 CHECK_CALLED(Accessible_child2_get_accRole
);
3484 /* Now that we know our position, no extra nav work. */
3485 SET_EXPECT(Accessible_get_accChildCount
);
3486 SET_EXPECT(Accessible_get_accChild
);
3487 SET_EXPECT(Accessible_get_accState
);
3488 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_NextSibling
, &elfrag2
);
3489 ok(Accessible
.ref
== 4, "Unexpected refcnt %ld\n", Accessible
.ref
);
3490 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3491 ok(!!elfrag2
, "elfrag2 == NULL\n");
3492 CHECK_CALLED(Accessible_get_accChildCount
);
3493 CHECK_CALLED(Accessible_get_accChild
);
3494 CHECK_CALLED(Accessible_get_accState
);
3497 check_fragment_acc(elfrag2
, &Accessible
.IAccessible_iface
, 3);
3498 IRawElementProviderFragment_Release(elfrag2
);
3499 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3502 IRawElementProviderFragment_Release(elfrag
);
3503 IRawElementProviderSimple_Release(elprov
);
3504 ok(Accessible_child
.ref
== 1, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3505 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3508 * Simple element child tests.
3510 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, 1, UIA_PFIA_DEFAULT
, &elprov
);
3511 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3512 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3514 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragment
, (void **)&elfrag
);
3515 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3516 ok(!!elfrag
, "elfrag == NULL\n");
3519 * Simple child elements don't check the root IAccessible, because they
3520 * can't be the root IAccessible.
3522 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_Parent
, &elfrag2
);
3523 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3524 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3525 ok(!!elfrag2
, "elfrag2 == NULL\n");
3526 check_fragment_acc(elfrag2
, &Accessible
.IAccessible_iface
, CHILDID_SELF
);
3527 IRawElementProviderFragment_Release(elfrag2
);
3528 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3531 * Test NavigateDirection_First/LastChild on simple child element. Does
3532 * nothing, as simple children cannot have children.
3534 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_FirstChild
, &elfrag2
);
3535 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3536 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3537 ok(!elfrag2
, "elfrag2 != NULL\n");
3539 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_LastChild
, &elfrag2
);
3540 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3541 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3542 ok(!elfrag2
, "elfrag2 != NULL\n");
3545 * NavigateDirection_Next/PreviousSibling behaves normally, no IAccessible
3548 SET_EXPECT(Accessible_get_accChildCount
);
3549 SET_EXPECT(Accessible_get_accChild
);
3550 SET_EXPECT(Accessible_child_get_accState
);
3551 SET_EXPECT(Accessible_child_accNavigate
);
3552 SET_EXPECT(Accessible_child_get_accParent
);
3553 hr
= IRawElementProviderFragment_Navigate(elfrag
, NavigateDirection_NextSibling
, &elfrag2
);
3554 ok(Accessible_child
.ref
== 2, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3555 ok(Accessible
.ref
== 4, "Unexpected refcnt %ld\n", Accessible
.ref
);
3556 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3557 ok(!!elfrag2
, "elfrag2 == NULL\n");
3558 CHECK_CALLED(Accessible_get_accChildCount
);
3559 CHECK_CALLED(Accessible_get_accChild
);
3560 CHECK_CALLED(Accessible_child_get_accState
);
3561 CHECK_CALLED(Accessible_child_accNavigate
);
3562 CHECK_CALLED(Accessible_child_get_accParent
);
3563 check_fragment_acc(elfrag2
, &Accessible_child
.IAccessible_iface
, CHILDID_SELF
);
3565 IRawElementProviderFragment_Release(elfrag2
);
3566 ok(Accessible_child
.ref
== 1, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3567 ok(Accessible
.ref
== 3, "Unexpected refcnt %ld\n", Accessible
.ref
);
3568 IRawElementProviderFragment_Release(elfrag
);
3569 IRawElementProviderSimple_Release(elprov
);
3570 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3572 set_accessible_props(&Accessible
, 0, 0, 0, NULL
, 0, 0, 0, 0);
3573 set_accessible_props(&Accessible2
, 0, 0, 0, NULL
, 0, 0, 0, 0);
3574 set_accessible_props(&Accessible_child
, 0, 0, 0, NULL
, 0, 0, 0, 0);
3575 set_accessible_props(&Accessible_child2
, 0, 0, 0, NULL
, 0, 0, 0, 0);
3578 static void test_uia_prov_from_acc_properties(void)
3580 IRawElementProviderSimple
*elprov
;
3581 RECT rect
[2] = { 0 };
3586 /* MSAA role to UIA control type test. */
3588 for (i
= 0; i
< ARRAY_SIZE(msaa_role_uia_types
); i
++)
3590 const struct msaa_role_uia_type
*role
= &msaa_role_uia_types
[i
];
3591 ILegacyIAccessibleProvider
*accprov
;
3596 * Roles get cached once a valid one is mapped, so create a new
3597 * element for each role.
3599 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3600 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3601 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3603 Accessible
.role
= role
->acc_role
;
3604 SET_EXPECT(Accessible_get_accRole
);
3606 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_ControlTypePropertyId
, &v
);
3607 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3608 if (role
->uia_control_type
)
3609 ok(check_variant_i4(&v
, role
->uia_control_type
), "MSAA role %d: V_I4(&v) = %ld\n", role
->acc_role
, V_I4(&v
));
3611 ok(V_VT(&v
) == VT_EMPTY
, "MSAA role %d: V_VT(&v) = %d\n", role
->acc_role
, V_VT(&v
));
3612 CHECK_CALLED(Accessible_get_accRole
);
3614 if (!role
->uia_control_type
)
3615 SET_EXPECT(Accessible_get_accRole
);
3617 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_ControlTypePropertyId
, &v
);
3618 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3619 if (role
->uia_control_type
)
3620 ok(check_variant_i4(&v
, role
->uia_control_type
), "MSAA role %d: V_I4(&v) = %ld\n", role
->acc_role
, V_I4(&v
));
3622 ok(V_VT(&v
) == VT_EMPTY
, "MSAA role %d: V_VT(&v) = %d\n", role
->acc_role
, V_VT(&v
));
3623 if (!role
->uia_control_type
)
3624 CHECK_CALLED(Accessible_get_accRole
);
3626 hr
= IRawElementProviderSimple_GetPatternProvider(elprov
, UIA_LegacyIAccessiblePatternId
, &unk
);
3627 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3628 ok(!!unk
, "unk == NULL\n");
3630 hr
= IUnknown_QueryInterface(unk
, &IID_ILegacyIAccessibleProvider
, (void **)&accprov
);
3631 IUnknown_Release(unk
);
3632 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3633 ok(!!accprov
, "accprov == NULL\n");
3635 SET_EXPECT(Accessible_get_accRole
);
3636 hr
= ILegacyIAccessibleProvider_get_Role(accprov
, &role_val
);
3637 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3638 ok(role_val
== Accessible
.role
, "role_val != Accessible.role\n");
3639 CHECK_CALLED(Accessible_get_accRole
);
3641 ILegacyIAccessibleProvider_Release(accprov
);
3642 IRawElementProviderSimple_Release(elprov
);
3643 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3646 /* ROLE_SYSTEM_CLOCK has no mapping in Windows < 10 1809. */
3647 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3648 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3649 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3651 Accessible
.role
= ROLE_SYSTEM_CLOCK
;
3652 SET_EXPECT(Accessible_get_accRole
);
3654 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_ControlTypePropertyId
, &v
);
3655 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3656 ok(check_variant_i4(&v
, UIA_ButtonControlTypeId
) || broken(V_VT(&v
) == VT_EMPTY
), /* Windows < 10 1809 */
3657 "MSAA role %d: V_I4(&v) = %ld\n", Accessible
.role
, V_I4(&v
));
3658 CHECK_CALLED(Accessible_get_accRole
);
3660 if (V_VT(&v
) == VT_EMPTY
)
3661 SET_EXPECT(Accessible_get_accRole
);
3663 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_ControlTypePropertyId
, &v
);
3664 ok(check_variant_i4(&v
, UIA_ButtonControlTypeId
) || broken(V_VT(&v
) == VT_EMPTY
), /* Windows < 10 1809 */
3665 "MSAA role %d: V_I4(&v) = %ld\n", Accessible
.role
, V_I4(&v
));
3666 if (V_VT(&v
) == VT_EMPTY
)
3667 CHECK_CALLED(Accessible_get_accRole
);
3669 Accessible
.role
= 0;
3670 IRawElementProviderSimple_Release(elprov
);
3671 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3673 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3674 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3675 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3677 /* UIA PropertyId's that correspond directly to individual MSAA state flags. */
3678 for (i
= 0; i
< ARRAY_SIZE(msaa_state_uia_props
); i
++)
3680 const struct msaa_state_uia_prop
*state
= &msaa_state_uia_props
[i
];
3682 for (x
= 0; x
< 2; x
++)
3684 Accessible
.state
= x
? state
->acc_state
: ~state
->acc_state
;
3685 SET_EXPECT(Accessible_get_accState
);
3686 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, state
->prop_id
, &v
);
3687 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3688 ok(check_variant_bool(&v
, x
), "V_BOOL(&v) = %#x\n", V_BOOL(&v
));
3689 CHECK_CALLED(Accessible_get_accState
);
3692 Accessible
.state
= 0;
3695 * UIA_IsOffscreenPropertyId relies upon either STATE_SYSTEM_OFFSCREEN
3696 * being set, or accLocation returning a location that is within the
3697 * client area bounding box of the HWND it is contained within.
3699 set_accessible_props(&Accessible
, 0, STATE_SYSTEM_OFFSCREEN
, 0, L
"Accessible", 0, 0, 0, 0);
3700 SET_EXPECT(Accessible_get_accState
);
3701 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_IsOffscreenPropertyId
, &v
);
3702 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3703 ok(V_VT(&v
) == VT_BOOL
, "V_VT(&v) = %d\n", V_VT(&v
));
3704 ok(check_variant_bool(&v
, TRUE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
3705 CHECK_CALLED(Accessible_get_accState
);
3707 /* accLocation fails, will return FALSE. */
3708 set_accessible_props(&Accessible
, 0, ~STATE_SYSTEM_OFFSCREEN
, 0, L
"Accessible", 0, 0, 0, 0);
3709 SET_EXPECT(Accessible_get_accState
);
3710 SET_EXPECT(Accessible_accLocation
);
3711 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_IsOffscreenPropertyId
, &v
);
3712 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3713 ok(V_VT(&v
) == VT_BOOL
, "V_VT(&v) = %d\n", V_VT(&v
));
3714 ok(check_variant_bool(&v
, FALSE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
3715 CHECK_CALLED(Accessible_get_accState
);
3716 CHECK_CALLED(Accessible_accLocation
);
3718 /* Window is visible, Accessible is within its bounds. */
3719 ShowWindow(Accessible
.ow_hwnd
, SW_SHOW
);
3720 ok(GetClientRect(Accessible
.ow_hwnd
, &rect
[0]), "GetClientRect returned FALSE\n");
3721 MapWindowPoints(Accessible
.ow_hwnd
, NULL
, (POINT
*)&rect
[0], 2);
3723 set_accessible_props(&Accessible
, 0, ~STATE_SYSTEM_OFFSCREEN
, 0, L
"Accessible", rect
[0].left
, rect
[0].top
,
3724 (rect
[0].right
- rect
[0].left
), (rect
[0].bottom
- rect
[0].top
));
3725 SET_EXPECT(Accessible_get_accState
);
3726 SET_EXPECT(Accessible_accLocation
);
3727 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_IsOffscreenPropertyId
, &v
);
3728 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3729 ok(V_VT(&v
) == VT_BOOL
, "Unexpected VT %d\n", V_VT(&v
));
3730 ok(check_variant_bool(&v
, FALSE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
3731 CHECK_CALLED(Accessible_get_accState
);
3732 CHECK_CALLED(Accessible_accLocation
);
3735 * Window is invisible, Accessible is within its bounds. Window visibility
3736 * doesn't effect whether or not an IAccessible is considered offscreen.
3738 ShowWindow(Accessible
.ow_hwnd
, SW_HIDE
);
3739 set_accessible_props(&Accessible
, 0, ~STATE_SYSTEM_OFFSCREEN
, 0, L
"Accessible", rect
[0].left
, rect
[0].top
,
3740 (rect
[0].right
- rect
[0].left
), (rect
[0].bottom
- rect
[0].top
));
3741 SET_EXPECT(Accessible_get_accState
);
3742 SET_EXPECT(Accessible_accLocation
);
3743 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_IsOffscreenPropertyId
, &v
);
3744 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3745 ok(V_VT(&v
) == VT_BOOL
, "Unexpected VT %d\n", V_VT(&v
));
3746 ok(check_variant_bool(&v
, FALSE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
3747 CHECK_CALLED(Accessible_get_accState
);
3748 CHECK_CALLED(Accessible_accLocation
);
3750 /* Accessible now outside of its window's bounds. */
3751 set_accessible_props(&Accessible
, 0, ~STATE_SYSTEM_OFFSCREEN
, 0, L
"Accessible", rect
[0].right
, rect
[0].bottom
,
3753 SET_EXPECT(Accessible_get_accState
);
3754 SET_EXPECT(Accessible_accLocation
);
3755 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_IsOffscreenPropertyId
, &v
);
3756 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3757 ok(V_VT(&v
) == VT_BOOL
, "V_VT(&v) = %d\n", V_VT(&v
));
3758 ok(check_variant_bool(&v
, TRUE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
3759 CHECK_CALLED(Accessible_get_accState
);
3760 CHECK_CALLED(Accessible_accLocation
);
3762 /* Accessible within window bounds, but not client area bounds. */
3763 ok(GetWindowRect(Accessible
.ow_hwnd
, &rect
[1]), "GetWindowRect returned FALSE\n");
3764 set_accessible_props(&Accessible
, 0, ~STATE_SYSTEM_OFFSCREEN
, 0, L
"Accessible", rect
[1].left
, rect
[1].top
,
3765 (rect
[0].left
- rect
[1].left
) - 1, (rect
[0].top
- rect
[1].top
) - 1);
3767 SET_EXPECT(Accessible_get_accState
);
3768 SET_EXPECT(Accessible_accLocation
);
3769 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_IsOffscreenPropertyId
, &v
);
3770 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3771 ok(V_VT(&v
) == VT_BOOL
, "V_VT(&v) = %d\n", V_VT(&v
));
3772 ok(check_variant_bool(&v
, TRUE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
3773 CHECK_CALLED(Accessible_get_accState
);
3774 CHECK_CALLED(Accessible_accLocation
);
3776 IRawElementProviderSimple_Release(elprov
);
3777 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3779 /* UIA_NamePropertyId tests. */
3780 set_accessible_props(&Accessible
, 0, 0, 0, L
"Accessible", 0, 0, 0, 0);
3781 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3782 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3783 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3785 SET_EXPECT(Accessible_get_accName
);
3787 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_NamePropertyId
, &v
);
3788 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3789 ok(V_VT(&v
) == VT_BSTR
, "Unexpected VT %d\n", V_VT(&v
));
3790 ok(!lstrcmpW(V_BSTR(&v
), Accessible
.name
), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v
)));
3792 CHECK_CALLED(Accessible_get_accName
);
3794 /* Name is not cached. */
3795 set_accessible_props(&Accessible
, 0, 0, 0, L
"Accessible2", 0, 0, 0, 0);
3796 SET_EXPECT(Accessible_get_accName
);
3797 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_NamePropertyId
, &v
);
3798 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3799 ok(V_VT(&v
) == VT_BSTR
, "Unexpected VT %d\n", V_VT(&v
));
3800 ok(!lstrcmpW(V_BSTR(&v
), Accessible
.name
), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v
)));
3802 CHECK_CALLED(Accessible_get_accName
);
3804 IRawElementProviderSimple_Release(elprov
);
3805 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3808 static void test_UiaProviderFromIAccessible(void)
3810 ILegacyIAccessibleProvider
*accprov
;
3811 IRawElementProviderSimple
*elprov
, *elprov2
;
3812 IRawElementProviderFragment
*elfrag
;
3813 enum ProviderOptions prov_opt
;
3814 struct UiaRect rect
;
3823 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
3825 cls
.lpfnWndProc
= test_wnd_proc
;
3828 cls
.hInstance
= GetModuleHandleA(NULL
);
3831 cls
.hbrBackground
= NULL
;
3832 cls
.lpszMenuName
= NULL
;
3833 cls
.lpszClassName
= "UiaProviderFromIAccessible class";
3835 RegisterClassA(&cls
);
3837 hwnd
= CreateWindowA("UiaProviderFromIAccessible class", "Test window", WS_OVERLAPPEDWINDOW
,
3838 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
3840 hr
= pUiaProviderFromIAccessible(NULL
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3841 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3843 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, NULL
);
3844 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
3847 * UiaProviderFromIAccessible will not wrap an MSAA proxy, this is
3848 * detected by checking for the 'IIS_IsOleaccProxy' service from the
3849 * IServiceProvider interface.
3851 hr
= CreateStdAccessibleObject(hwnd
, OBJID_CLIENT
, &IID_IAccessible
, (void**)&acc
);
3852 ok(hr
== S_OK
, "got %#lx\n", hr
);
3853 ok(!!acc
, "acc == NULL\n");
3855 hr
= pUiaProviderFromIAccessible(acc
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3856 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
3857 IAccessible_Release(acc
);
3859 /* Don't return an HWND from accNavigate or OleWindow. */
3860 SET_EXPECT(Accessible_accNavigate
);
3861 SET_EXPECT(Accessible_get_accParent
);
3862 Accessible
.acc_hwnd
= NULL
;
3863 Accessible
.ow_hwnd
= NULL
;
3864 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3865 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
3866 CHECK_CALLED(Accessible_accNavigate
);
3867 CHECK_CALLED(Accessible_get_accParent
);
3869 /* Return an HWND from accNavigate, not OleWindow. */
3870 SET_EXPECT(Accessible_accNavigate
);
3871 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3872 acc_client
= &Accessible
.IAccessible_iface
;
3873 Accessible
.acc_hwnd
= hwnd
;
3874 Accessible
.ow_hwnd
= NULL
;
3875 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3876 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3877 CHECK_CALLED(Accessible_accNavigate
);
3878 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3879 IRawElementProviderSimple_Release(elprov
);
3880 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3883 /* Skip tests on Win10v1507. */
3884 if (called_winproc_GETOBJECT_CLIENT
)
3886 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
3889 expect_winproc_GETOBJECT_CLIENT
= FALSE
;
3891 /* Return an HWND from parent IAccessible's IOleWindow interface. */
3892 SET_EXPECT(Accessible_child_accNavigate
);
3893 SET_EXPECT(Accessible_child_get_accParent
);
3894 Accessible
.acc_hwnd
= NULL
;
3895 Accessible
.ow_hwnd
= hwnd
;
3896 hr
= pUiaProviderFromIAccessible(&Accessible_child
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3897 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3898 CHECK_CALLED(Accessible_child_accNavigate
);
3899 CHECK_CALLED(Accessible_child_get_accParent
);
3900 ok(Accessible_child
.ref
== 2, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3901 IRawElementProviderSimple_Release(elprov
);
3902 ok(Accessible_child
.ref
== 1, "Unexpected refcnt %ld\n", Accessible_child
.ref
);
3904 /* Return an HWND from OleWindow, not accNavigate. */
3905 Accessible
.acc_hwnd
= NULL
;
3906 Accessible
.ow_hwnd
= hwnd
;
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 hr
= IRawElementProviderSimple_get_ProviderOptions(elprov
, &prov_opt
);
3912 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3913 ok((prov_opt
== (ProviderOptions_ServerSideProvider
| ProviderOptions_UseComThreading
)) ||
3914 broken(prov_opt
== ProviderOptions_ClientSideProvider
), /* Windows < 10 1507 */
3915 "Unexpected provider options %#x\n", prov_opt
);
3917 hr
= IRawElementProviderSimple_GetPropertyValue(elprov
, UIA_ProviderDescriptionPropertyId
, &v
);
3918 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3919 ok(V_VT(&v
) == VT_BSTR
, "V_VT(&v) = %d\n", V_VT(&v
));
3922 hr
= IRawElementProviderSimple_GetPatternProvider(elprov
, UIA_LegacyIAccessiblePatternId
, &unk
);
3923 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3924 ok(!!unk
, "unk == NULL\n");
3925 ok(iface_cmp((IUnknown
*)elprov
, unk
), "unk != elprov\n");
3927 hr
= IUnknown_QueryInterface(unk
, &IID_ILegacyIAccessibleProvider
, (void **)&accprov
);
3928 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3929 ok(!!accprov
, "accprov == NULL\n");
3931 hr
= ILegacyIAccessibleProvider_get_ChildId(accprov
, &cid
);
3932 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3933 ok(cid
== CHILDID_SELF
, "cid != CHILDID_SELF\n");
3935 hr
= ILegacyIAccessibleProvider_GetIAccessible(accprov
, &acc
);
3936 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3937 ok(acc
== &Accessible
.IAccessible_iface
, "acc != &Accessible.IAccessible_iface\n");
3938 IAccessible_Release(acc
);
3939 IUnknown_Release(unk
);
3940 ILegacyIAccessibleProvider_Release(accprov
);
3942 IRawElementProviderSimple_Release(elprov
);
3943 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3945 /* ChildID other than CHILDID_SELF. */
3946 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, 1, UIA_PFIA_DEFAULT
, &elprov
);
3947 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3948 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3951 * Simple child element (IAccessible without CHILDID_SELF) cannot be root
3952 * IAccessible. No checks against the root HWND IAccessible will be done.
3954 elprov2
= (void *)0xdeadbeef;
3955 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
3956 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3957 ok(!elprov2
, "elprov != NULL\n");
3959 hr
= IRawElementProviderSimple_GetPatternProvider(elprov
, UIA_LegacyIAccessiblePatternId
, &unk
);
3960 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3961 ok(!!unk
, "unk == NULL\n");
3962 ok(iface_cmp((IUnknown
*)elprov
, unk
), "unk != elprov\n");
3964 hr
= IUnknown_QueryInterface(unk
, &IID_ILegacyIAccessibleProvider
, (void **)&accprov
);
3965 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3966 ok(!!accprov
, "accprov == NULL\n");
3968 hr
= ILegacyIAccessibleProvider_get_ChildId(accprov
, &cid
);
3969 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3970 ok(cid
== 1, "cid != CHILDID_SELF\n");
3972 hr
= ILegacyIAccessibleProvider_GetIAccessible(accprov
, &acc
);
3973 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3974 ok(acc
== &Accessible
.IAccessible_iface
, "acc != &Accessible.IAccessible_iface\n");
3975 IAccessible_Release(acc
);
3976 IUnknown_Release(unk
);
3977 ILegacyIAccessibleProvider_Release(accprov
);
3979 IRawElementProviderSimple_Release(elprov
);
3980 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
3983 * &Accessible.IAccessible_iface will be compared against the default
3984 * client accessible object. Since we have all properties set to 0,
3985 * we return failure HRESULTs and all properties will get queried but not
3988 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
3989 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
3990 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
3992 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
3993 SET_EXPECT(Accessible_get_accRole
);
3994 SET_EXPECT(Accessible_get_accState
);
3995 SET_EXPECT(Accessible_get_accChildCount
);
3996 SET_EXPECT(Accessible_accLocation
);
3997 SET_EXPECT(Accessible_get_accName
);
3998 elprov2
= (void *)0xdeadbeef;
3999 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4000 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4001 ok(!elprov2
, "elprov != NULL\n");
4002 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4003 CHECK_CALLED(Accessible_get_accRole
);
4004 CHECK_CALLED(Accessible_get_accState
);
4005 CHECK_CALLED(Accessible_get_accChildCount
);
4006 CHECK_CALLED(Accessible_accLocation
);
4007 CHECK_CALLED(Accessible_get_accName
);
4009 /* Second call won't send WM_GETOBJECT. */
4010 elprov2
= (void *)0xdeadbeef;
4011 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4012 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4013 ok(!elprov2
, "elprov != NULL\n");
4015 IRawElementProviderSimple_Release(elprov
);
4016 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4019 * Return &Accessible.IAccessible_iface in response to OBJID_CLIENT,
4020 * interface pointers will be compared, no method calls to check property
4023 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4024 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4025 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4027 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4028 elprov2
= (void *)0xdeadbeef;
4029 acc_client
= &Accessible
.IAccessible_iface
;
4030 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4031 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4032 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4033 IRawElementProviderSimple_Release(elprov2
);
4034 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4036 /* Second call, no checks. */
4037 elprov2
= (void *)0xdeadbeef;
4039 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4040 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4041 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4042 IRawElementProviderSimple_Release(elprov2
);
4044 IRawElementProviderSimple_Release(elprov
);
4045 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4048 * Return &Accessible2.IAccessible_iface in response to OBJID_CLIENT,
4049 * interface pointers won't match, so properties will be compared.
4051 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4052 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4053 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4055 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1,
4056 L
"acc_name", 0, 0, 50, 50);
4057 set_accessible_props(&Accessible2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1,
4058 L
"acc_name", 0, 0, 50, 50);
4060 acc_client
= &Accessible2
.IAccessible_iface
;
4061 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4062 SET_EXPECT(Accessible_get_accRole
);
4063 SET_EXPECT(Accessible_get_accState
);
4064 SET_EXPECT(Accessible_get_accChildCount
);
4065 SET_EXPECT(Accessible_accLocation
);
4066 SET_EXPECT(Accessible_get_accName
);
4067 SET_EXPECT(Accessible2_get_accRole
);
4068 SET_EXPECT(Accessible2_get_accState
);
4069 SET_EXPECT(Accessible2_get_accChildCount
);
4070 SET_EXPECT(Accessible2_accLocation
);
4071 SET_EXPECT(Accessible2_get_accName
);
4073 * The IAccessible returned by WM_GETOBJECT will be checked for an
4074 * IAccIdentity interface to see if Dynamic Annotation properties should
4075 * be queried. If not present on the current IAccessible, it will check
4076 * the parent IAccessible for one.
4078 SET_EXPECT(Accessible2_QI_IAccIdentity
);
4079 SET_EXPECT(Accessible2_get_accParent
);
4080 elprov2
= (void *)0xdeadbeef;
4081 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4082 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4083 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4084 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
4085 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4086 CHECK_CALLED(Accessible_get_accRole
);
4087 CHECK_CALLED(Accessible_get_accState
);
4088 CHECK_CALLED(Accessible_get_accChildCount
);
4089 CHECK_CALLED(Accessible_accLocation
);
4090 CHECK_CALLED(Accessible_get_accName
);
4091 CHECK_CALLED(Accessible2_get_accRole
);
4092 CHECK_CALLED(Accessible2_get_accState
);
4093 CHECK_CALLED(Accessible2_get_accChildCount
);
4094 CHECK_CALLED(Accessible2_accLocation
);
4095 CHECK_CALLED(Accessible2_get_accName
);
4096 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
4097 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
4098 IRawElementProviderSimple_Release(elprov2
);
4100 elprov2
= (void *)0xdeadbeef;
4102 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4103 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4104 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4105 IRawElementProviderSimple_Release(elprov2
);
4107 IRawElementProviderSimple_Release(elprov
);
4108 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4111 * If a failure HRESULT is returned from the IRawElementProviderSimple
4112 * IAccessible, the corresponding AOFW IAccessible method isn't called.
4113 * An exception is get_accChildCount, which is always called, but only
4114 * checked if the HRESULT return value is not a failure. If Role/State/Name
4115 * are not queried, no IAccIdentity check is done.
4117 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4118 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4119 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4121 set_accessible_props(&Accessible
, 0, 0, 0, NULL
, 0, 0, 0, 0);
4122 set_accessible_props(&Accessible2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1,
4123 L
"acc_name", 0, 0, 50, 50);
4125 acc_client
= &Accessible2
.IAccessible_iface
;
4126 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4127 SET_EXPECT(Accessible_get_accRole
);
4128 SET_EXPECT(Accessible_get_accState
);
4129 SET_EXPECT(Accessible_get_accChildCount
);
4130 SET_EXPECT(Accessible2_get_accChildCount
);
4131 SET_EXPECT(Accessible_accLocation
);
4132 SET_EXPECT(Accessible_get_accName
);
4133 elprov2
= (void *)0xdeadbeef;
4134 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4135 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4136 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
4137 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4138 CHECK_CALLED(Accessible_get_accRole
);
4139 CHECK_CALLED(Accessible_get_accState
);
4140 CHECK_CALLED(Accessible_get_accChildCount
);
4141 CHECK_CALLED(Accessible2_get_accChildCount
);
4142 CHECK_CALLED(Accessible_accLocation
);
4143 CHECK_CALLED(Accessible_get_accName
);
4146 elprov2
= (void *)0xdeadbeef;
4147 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4148 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4149 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
4151 IRawElementProviderSimple_Release(elprov
);
4152 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4155 * Properties are checked in a sequence of accRole, accState,
4156 * accChildCount, accLocation, and finally accName. If a mismatch is found
4157 * early in the sequence, the rest aren't checked.
4159 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4160 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4161 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4163 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
4164 set_accessible_props(&Accessible2
, ROLE_SYSTEM_CLIENT
, STATE_SYSTEM_FOCUSABLE
, 0, NULL
, 0, 0, 0, 0);
4166 acc_client
= &Accessible2
.IAccessible_iface
;
4167 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4168 SET_EXPECT(Accessible_get_accRole
);
4169 SET_EXPECT(Accessible2_get_accRole
);
4170 SET_EXPECT(Accessible2_QI_IAccIdentity
);
4171 SET_EXPECT(Accessible2_get_accParent
);
4172 elprov2
= (void *)0xdeadbeef;
4173 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4174 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4175 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
4176 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4177 CHECK_CALLED(Accessible_get_accRole
);
4178 CHECK_CALLED(Accessible2_get_accRole
);
4179 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
4180 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
4182 elprov2
= (void *)0xdeadbeef;
4184 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4185 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4186 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
4188 IRawElementProviderSimple_Release(elprov
);
4189 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4191 /* 4/5 properties match, considered a match. */
4192 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4193 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4194 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4196 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1, NULL
, 0, 0, 50, 50);
4197 set_accessible_props(&Accessible2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1, NULL
, 0, 0, 50, 50);
4199 acc_client
= &Accessible2
.IAccessible_iface
;
4200 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4201 SET_EXPECT(Accessible_get_accRole
);
4202 SET_EXPECT(Accessible_get_accState
);
4203 SET_EXPECT(Accessible_get_accChildCount
);
4204 SET_EXPECT(Accessible_accLocation
);
4205 SET_EXPECT(Accessible_get_accName
);
4206 SET_EXPECT(Accessible2_get_accRole
);
4207 SET_EXPECT(Accessible2_get_accState
);
4208 SET_EXPECT(Accessible2_get_accChildCount
);
4209 SET_EXPECT(Accessible2_accLocation
);
4210 SET_EXPECT(Accessible2_QI_IAccIdentity
);
4211 SET_EXPECT(Accessible2_get_accParent
);
4212 elprov2
= (void *)0xdeadbeef;
4213 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4214 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4215 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4216 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
4217 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4218 CHECK_CALLED(Accessible_get_accRole
);
4219 CHECK_CALLED(Accessible_get_accState
);
4220 CHECK_CALLED(Accessible_get_accChildCount
);
4221 CHECK_CALLED(Accessible_accLocation
);
4222 CHECK_CALLED(Accessible_get_accName
);
4223 CHECK_CALLED(Accessible2_get_accRole
);
4224 CHECK_CALLED(Accessible2_get_accState
);
4225 CHECK_CALLED(Accessible2_get_accChildCount
);
4226 CHECK_CALLED(Accessible2_accLocation
);
4227 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
4228 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
4229 IRawElementProviderSimple_Release(elprov2
);
4231 elprov2
= (void *)0xdeadbeef;
4233 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4234 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4235 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4236 IRawElementProviderSimple_Release(elprov2
);
4238 IRawElementProviderSimple_Release(elprov
);
4239 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4241 /* 3/5 properties match, not considered a match. */
4242 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4243 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4244 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4246 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1, NULL
, 0, 0, 0, 0);
4247 set_accessible_props(&Accessible2
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 1, NULL
, 0, 0, 0, 0);
4249 acc_client
= &Accessible2
.IAccessible_iface
;
4250 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4251 SET_EXPECT(Accessible_get_accRole
);
4252 SET_EXPECT(Accessible_get_accState
);
4253 SET_EXPECT(Accessible_get_accChildCount
);
4254 SET_EXPECT(Accessible_accLocation
);
4255 SET_EXPECT(Accessible_get_accName
);
4256 SET_EXPECT(Accessible2_get_accRole
);
4257 SET_EXPECT(Accessible2_get_accState
);
4258 SET_EXPECT(Accessible2_get_accChildCount
);
4259 SET_EXPECT(Accessible2_QI_IAccIdentity
);
4260 SET_EXPECT(Accessible2_get_accParent
);
4261 elprov2
= (void *)0xdeadbeef;
4262 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4263 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4264 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
4265 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4266 CHECK_CALLED(Accessible_get_accRole
);
4267 CHECK_CALLED(Accessible_get_accState
);
4268 CHECK_CALLED(Accessible_get_accChildCount
);
4269 CHECK_CALLED(Accessible_accLocation
);
4270 CHECK_CALLED(Accessible_get_accName
);
4271 CHECK_CALLED(Accessible2_get_accRole
);
4272 CHECK_CALLED(Accessible2_get_accState
);
4273 CHECK_CALLED(Accessible2_get_accChildCount
);
4274 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
4275 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
4277 elprov2
= (void *)0xdeadbeef;
4279 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4280 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4281 ok(!elprov2
, "elprov != NULL, elprov %p\n", elprov2
);
4283 IRawElementProviderSimple_Release(elprov
);
4284 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4286 /* Only name matches, considered a match. */
4287 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4288 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4289 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4291 set_accessible_props(&Accessible
, 0, 0, 0, L
"acc_name", 0, 0, 0, 0);
4292 set_accessible_props(&Accessible2
, 0, 0, 0, L
"acc_name", 0, 0, 0, 0);
4294 acc_client
= &Accessible2
.IAccessible_iface
;
4295 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4296 SET_EXPECT(Accessible_get_accRole
);
4297 SET_EXPECT(Accessible_get_accState
);
4298 SET_EXPECT(Accessible_get_accChildCount
);
4299 SET_EXPECT(Accessible_accLocation
);
4300 SET_EXPECT(Accessible_get_accName
);
4301 SET_EXPECT(Accessible2_get_accChildCount
);
4302 SET_EXPECT(Accessible2_get_accName
);
4303 SET_EXPECT(Accessible2_QI_IAccIdentity
);
4304 SET_EXPECT(Accessible2_get_accParent
);
4305 elprov2
= (void *)0xdeadbeef;
4306 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4307 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4308 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4309 ok(Accessible2
.ref
== 1, "Unexpected refcnt %ld\n", Accessible2
.ref
);
4310 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4311 CHECK_CALLED(Accessible_get_accRole
);
4312 CHECK_CALLED(Accessible_get_accState
);
4313 CHECK_CALLED(Accessible_get_accChildCount
);
4314 CHECK_CALLED(Accessible_accLocation
);
4315 CHECK_CALLED(Accessible_get_accName
);
4316 CHECK_CALLED(Accessible2_get_accChildCount
);
4317 CHECK_CALLED(Accessible2_get_accName
);
4318 todo_wine
CHECK_CALLED(Accessible2_QI_IAccIdentity
);
4319 todo_wine
CHECK_CALLED(Accessible2_get_accParent
);
4320 IRawElementProviderSimple_Release(elprov2
);
4322 elprov2
= (void *)0xdeadbeef;
4324 hr
= IRawElementProviderSimple_get_HostRawElementProvider(elprov
, &elprov2
);
4325 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4326 ok(!!elprov2
, "elprov == NULL, elprov %p\n", elprov2
);
4327 IRawElementProviderSimple_Release(elprov2
);
4329 IRawElementProviderSimple_Release(elprov
);
4330 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4333 * Test IRawElementProviderFragment_get_BoundingRectangle.
4335 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_FOCUSABLE
, 0, L
"acc_name", 25, 25, 50, 50);
4336 /* Test the case where Accessible is not the root for its HWND. */
4338 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4339 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4340 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4342 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragment
, (void **)&elfrag
);
4343 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4344 ok(!!elfrag
, "elfrag == NULL\n");
4346 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4347 SET_EXPECT(Accessible_get_accRole
);
4348 SET_EXPECT(Accessible_get_accState
);
4349 SET_EXPECT(Accessible_accLocation
);
4350 hr
= IRawElementProviderFragment_get_BoundingRectangle(elfrag
, &rect
);
4351 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4352 ok(rect
.left
== (double)Accessible
.left
, "Unexpected left value %f\n", rect
.left
);
4353 ok(rect
.top
== (double)Accessible
.top
, "Unexpected top value %f\n", rect
.top
);
4354 ok(rect
.width
== (double)Accessible
.width
, "Unexpected width value %f\n", rect
.width
);
4355 ok(rect
.height
== (double)Accessible
.height
, "Unexpected height value %f\n", rect
.height
);
4356 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4357 CHECK_CALLED(Accessible_get_accRole
);
4358 CHECK_CALLED(Accessible_get_accState
);
4359 CHECK_CALLED(Accessible_accLocation
);
4361 /* If Accessible has STATE_SYSTEM_OFFSCREEN, it will return an empty rect. */
4362 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, STATE_SYSTEM_OFFSCREEN
, 0, L
"acc_name", 0, 0, 50, 50);
4363 SET_EXPECT(Accessible_get_accState
);
4364 hr
= IRawElementProviderFragment_get_BoundingRectangle(elfrag
, &rect
);
4365 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4366 ok(rect
.left
== 0.0, "Unexpected left value %f\n", rect
.left
);
4367 ok(rect
.top
== 0.0, "Unexpected top value %f\n", rect
.top
);
4368 ok(rect
.width
== 0.0, "Unexpected width value %f\n", rect
.width
);
4369 ok(rect
.height
== 0.0, "Unexpected height value %f\n", rect
.height
);
4370 CHECK_CALLED(Accessible_get_accState
);
4372 IRawElementProviderFragment_Release(elfrag
);
4373 IRawElementProviderSimple_Release(elprov
);
4374 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4376 /* Test case where accessible is the root accessible. */
4377 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, 0, 0, L
"acc_name", 0, 0, 0, 0);
4378 acc_client
= &Accessible
.IAccessible_iface
;
4379 hr
= pUiaProviderFromIAccessible(&Accessible
.IAccessible_iface
, CHILDID_SELF
, UIA_PFIA_DEFAULT
, &elprov
);
4380 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4381 ok(Accessible
.ref
== 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
4383 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragment
, (void **)&elfrag
);
4384 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4385 ok(!!elfrag
, "elfrag == NULL\n");
4387 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
4388 hr
= IRawElementProviderFragment_get_BoundingRectangle(elfrag
, &rect
);
4389 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4390 ok(rect
.left
== 0.0, "Unexpected left value %f\n", rect
.left
);
4391 ok(rect
.top
== 0.0, "Unexpected top value %f\n", rect
.top
);
4392 ok(rect
.width
== 0.0, "Unexpected width value %f\n", rect
.width
);
4393 ok(rect
.height
== 0.0, "Unexpected height value %f\n", rect
.height
);
4394 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
4396 /* Second call does nothing. */
4397 hr
= IRawElementProviderFragment_get_BoundingRectangle(elfrag
, &rect
);
4398 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4399 ok(rect
.left
== 0.0, "Unexpected left value %f\n", rect
.left
);
4400 ok(rect
.top
== 0.0, "Unexpected top value %f\n", rect
.top
);
4401 ok(rect
.width
== 0.0, "Unexpected width value %f\n", rect
.width
);
4402 ok(rect
.height
== 0.0, "Unexpected height value %f\n", rect
.height
);
4404 IRawElementProviderFragment_Release(elfrag
);
4405 IRawElementProviderSimple_Release(elprov
);
4406 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
4409 test_uia_prov_from_acc_properties();
4410 test_uia_prov_from_acc_navigation();
4411 test_uia_prov_from_acc_ia2();
4414 DestroyWindow(hwnd
);
4415 UnregisterClassA("pUiaProviderFromIAccessible class", NULL
);
4416 Accessible
.acc_hwnd
= NULL
;
4417 Accessible
.ow_hwnd
= NULL
;
4420 struct uia_lookup_id
{
4425 static const struct uia_lookup_id uia_property_lookup_ids
[] = {
4426 { &RuntimeId_Property_GUID
, UIA_RuntimeIdPropertyId
},
4427 { &BoundingRectangle_Property_GUID
, UIA_BoundingRectanglePropertyId
},
4428 { &ProcessId_Property_GUID
, UIA_ProcessIdPropertyId
},
4429 { &ControlType_Property_GUID
, UIA_ControlTypePropertyId
},
4430 { &LocalizedControlType_Property_GUID
, UIA_LocalizedControlTypePropertyId
},
4431 { &Name_Property_GUID
, UIA_NamePropertyId
},
4432 { &AcceleratorKey_Property_GUID
, UIA_AcceleratorKeyPropertyId
},
4433 { &AccessKey_Property_GUID
, UIA_AccessKeyPropertyId
},
4434 { &HasKeyboardFocus_Property_GUID
, UIA_HasKeyboardFocusPropertyId
},
4435 { &IsKeyboardFocusable_Property_GUID
, UIA_IsKeyboardFocusablePropertyId
},
4436 { &IsEnabled_Property_GUID
, UIA_IsEnabledPropertyId
},
4437 { &AutomationId_Property_GUID
, UIA_AutomationIdPropertyId
},
4438 { &ClassName_Property_GUID
, UIA_ClassNamePropertyId
},
4439 { &HelpText_Property_GUID
, UIA_HelpTextPropertyId
},
4440 { &ClickablePoint_Property_GUID
, UIA_ClickablePointPropertyId
},
4441 { &Culture_Property_GUID
, UIA_CulturePropertyId
},
4442 { &IsControlElement_Property_GUID
, UIA_IsControlElementPropertyId
},
4443 { &IsContentElement_Property_GUID
, UIA_IsContentElementPropertyId
},
4444 { &LabeledBy_Property_GUID
, UIA_LabeledByPropertyId
},
4445 { &IsPassword_Property_GUID
, UIA_IsPasswordPropertyId
},
4446 { &NewNativeWindowHandle_Property_GUID
, UIA_NativeWindowHandlePropertyId
},
4447 { &ItemType_Property_GUID
, UIA_ItemTypePropertyId
},
4448 { &IsOffscreen_Property_GUID
, UIA_IsOffscreenPropertyId
},
4449 { &Orientation_Property_GUID
, UIA_OrientationPropertyId
},
4450 { &FrameworkId_Property_GUID
, UIA_FrameworkIdPropertyId
},
4451 { &IsRequiredForForm_Property_GUID
, UIA_IsRequiredForFormPropertyId
},
4452 { &ItemStatus_Property_GUID
, UIA_ItemStatusPropertyId
},
4453 { &IsDockPatternAvailable_Property_GUID
, UIA_IsDockPatternAvailablePropertyId
},
4454 { &IsExpandCollapsePatternAvailable_Property_GUID
, UIA_IsExpandCollapsePatternAvailablePropertyId
},
4455 { &IsGridItemPatternAvailable_Property_GUID
, UIA_IsGridItemPatternAvailablePropertyId
},
4456 { &IsGridPatternAvailable_Property_GUID
, UIA_IsGridPatternAvailablePropertyId
},
4457 { &IsInvokePatternAvailable_Property_GUID
, UIA_IsInvokePatternAvailablePropertyId
},
4458 { &IsMultipleViewPatternAvailable_Property_GUID
, UIA_IsMultipleViewPatternAvailablePropertyId
},
4459 { &IsRangeValuePatternAvailable_Property_GUID
, UIA_IsRangeValuePatternAvailablePropertyId
},
4460 { &IsScrollPatternAvailable_Property_GUID
, UIA_IsScrollPatternAvailablePropertyId
},
4461 { &IsScrollItemPatternAvailable_Property_GUID
, UIA_IsScrollItemPatternAvailablePropertyId
},
4462 { &IsSelectionItemPatternAvailable_Property_GUID
, UIA_IsSelectionItemPatternAvailablePropertyId
},
4463 { &IsSelectionPatternAvailable_Property_GUID
, UIA_IsSelectionPatternAvailablePropertyId
},
4464 { &IsTablePatternAvailable_Property_GUID
, UIA_IsTablePatternAvailablePropertyId
},
4465 { &IsTableItemPatternAvailable_Property_GUID
, UIA_IsTableItemPatternAvailablePropertyId
},
4466 { &IsTextPatternAvailable_Property_GUID
, UIA_IsTextPatternAvailablePropertyId
},
4467 { &IsTogglePatternAvailable_Property_GUID
, UIA_IsTogglePatternAvailablePropertyId
},
4468 { &IsTransformPatternAvailable_Property_GUID
, UIA_IsTransformPatternAvailablePropertyId
},
4469 { &IsValuePatternAvailable_Property_GUID
, UIA_IsValuePatternAvailablePropertyId
},
4470 { &IsWindowPatternAvailable_Property_GUID
, UIA_IsWindowPatternAvailablePropertyId
},
4471 { &Value_Value_Property_GUID
, UIA_ValueValuePropertyId
},
4472 { &Value_IsReadOnly_Property_GUID
, UIA_ValueIsReadOnlyPropertyId
},
4473 { &RangeValue_Value_Property_GUID
, UIA_RangeValueValuePropertyId
},
4474 { &RangeValue_IsReadOnly_Property_GUID
, UIA_RangeValueIsReadOnlyPropertyId
},
4475 { &RangeValue_Minimum_Property_GUID
, UIA_RangeValueMinimumPropertyId
},
4476 { &RangeValue_Maximum_Property_GUID
, UIA_RangeValueMaximumPropertyId
},
4477 { &RangeValue_LargeChange_Property_GUID
, UIA_RangeValueLargeChangePropertyId
},
4478 { &RangeValue_SmallChange_Property_GUID
, UIA_RangeValueSmallChangePropertyId
},
4479 { &Scroll_HorizontalScrollPercent_Property_GUID
, UIA_ScrollHorizontalScrollPercentPropertyId
},
4480 { &Scroll_HorizontalViewSize_Property_GUID
, UIA_ScrollHorizontalViewSizePropertyId
},
4481 { &Scroll_VerticalScrollPercent_Property_GUID
, UIA_ScrollVerticalScrollPercentPropertyId
},
4482 { &Scroll_VerticalViewSize_Property_GUID
, UIA_ScrollVerticalViewSizePropertyId
},
4483 { &Scroll_HorizontallyScrollable_Property_GUID
, UIA_ScrollHorizontallyScrollablePropertyId
},
4484 { &Scroll_VerticallyScrollable_Property_GUID
, UIA_ScrollVerticallyScrollablePropertyId
},
4485 { &Selection_Selection_Property_GUID
, UIA_SelectionSelectionPropertyId
},
4486 { &Selection_CanSelectMultiple_Property_GUID
, UIA_SelectionCanSelectMultiplePropertyId
},
4487 { &Selection_IsSelectionRequired_Property_GUID
, UIA_SelectionIsSelectionRequiredPropertyId
},
4488 { &Grid_RowCount_Property_GUID
, UIA_GridRowCountPropertyId
},
4489 { &Grid_ColumnCount_Property_GUID
, UIA_GridColumnCountPropertyId
},
4490 { &GridItem_Row_Property_GUID
, UIA_GridItemRowPropertyId
},
4491 { &GridItem_Column_Property_GUID
, UIA_GridItemColumnPropertyId
},
4492 { &GridItem_RowSpan_Property_GUID
, UIA_GridItemRowSpanPropertyId
},
4493 { &GridItem_ColumnSpan_Property_GUID
, UIA_GridItemColumnSpanPropertyId
},
4494 { &GridItem_Parent_Property_GUID
, UIA_GridItemContainingGridPropertyId
},
4495 { &Dock_DockPosition_Property_GUID
, UIA_DockDockPositionPropertyId
},
4496 { &ExpandCollapse_ExpandCollapseState_Property_GUID
, UIA_ExpandCollapseExpandCollapseStatePropertyId
},
4497 { &MultipleView_CurrentView_Property_GUID
, UIA_MultipleViewCurrentViewPropertyId
},
4498 { &MultipleView_SupportedViews_Property_GUID
, UIA_MultipleViewSupportedViewsPropertyId
},
4499 { &Window_CanMaximize_Property_GUID
, UIA_WindowCanMaximizePropertyId
},
4500 { &Window_CanMinimize_Property_GUID
, UIA_WindowCanMinimizePropertyId
},
4501 { &Window_WindowVisualState_Property_GUID
, UIA_WindowWindowVisualStatePropertyId
},
4502 { &Window_WindowInteractionState_Property_GUID
, UIA_WindowWindowInteractionStatePropertyId
},
4503 { &Window_IsModal_Property_GUID
, UIA_WindowIsModalPropertyId
},
4504 { &Window_IsTopmost_Property_GUID
, UIA_WindowIsTopmostPropertyId
},
4505 { &SelectionItem_IsSelected_Property_GUID
, UIA_SelectionItemIsSelectedPropertyId
},
4506 { &SelectionItem_SelectionContainer_Property_GUID
, UIA_SelectionItemSelectionContainerPropertyId
},
4507 { &Table_RowHeaders_Property_GUID
, UIA_TableRowHeadersPropertyId
},
4508 { &Table_ColumnHeaders_Property_GUID
, UIA_TableColumnHeadersPropertyId
},
4509 { &Table_RowOrColumnMajor_Property_GUID
, UIA_TableRowOrColumnMajorPropertyId
},
4510 { &TableItem_RowHeaderItems_Property_GUID
, UIA_TableItemRowHeaderItemsPropertyId
},
4511 { &TableItem_ColumnHeaderItems_Property_GUID
, UIA_TableItemColumnHeaderItemsPropertyId
},
4512 { &Toggle_ToggleState_Property_GUID
, UIA_ToggleToggleStatePropertyId
},
4513 { &Transform_CanMove_Property_GUID
, UIA_TransformCanMovePropertyId
},
4514 { &Transform_CanResize_Property_GUID
, UIA_TransformCanResizePropertyId
},
4515 { &Transform_CanRotate_Property_GUID
, UIA_TransformCanRotatePropertyId
},
4516 { &IsLegacyIAccessiblePatternAvailable_Property_GUID
, UIA_IsLegacyIAccessiblePatternAvailablePropertyId
},
4517 { &LegacyIAccessible_ChildId_Property_GUID
, UIA_LegacyIAccessibleChildIdPropertyId
},
4518 { &LegacyIAccessible_Name_Property_GUID
, UIA_LegacyIAccessibleNamePropertyId
},
4519 { &LegacyIAccessible_Value_Property_GUID
, UIA_LegacyIAccessibleValuePropertyId
},
4520 { &LegacyIAccessible_Description_Property_GUID
, UIA_LegacyIAccessibleDescriptionPropertyId
},
4521 { &LegacyIAccessible_Role_Property_GUID
, UIA_LegacyIAccessibleRolePropertyId
},
4522 { &LegacyIAccessible_State_Property_GUID
, UIA_LegacyIAccessibleStatePropertyId
},
4523 { &LegacyIAccessible_Help_Property_GUID
, UIA_LegacyIAccessibleHelpPropertyId
},
4524 { &LegacyIAccessible_KeyboardShortcut_Property_GUID
, UIA_LegacyIAccessibleKeyboardShortcutPropertyId
},
4525 { &LegacyIAccessible_Selection_Property_GUID
, UIA_LegacyIAccessibleSelectionPropertyId
},
4526 { &LegacyIAccessible_DefaultAction_Property_GUID
, UIA_LegacyIAccessibleDefaultActionPropertyId
},
4527 { &AriaRole_Property_GUID
, UIA_AriaRolePropertyId
},
4528 { &AriaProperties_Property_GUID
, UIA_AriaPropertiesPropertyId
},
4529 { &IsDataValidForForm_Property_GUID
, UIA_IsDataValidForFormPropertyId
},
4530 { &ControllerFor_Property_GUID
, UIA_ControllerForPropertyId
},
4531 { &DescribedBy_Property_GUID
, UIA_DescribedByPropertyId
},
4532 { &FlowsTo_Property_GUID
, UIA_FlowsToPropertyId
},
4533 { &ProviderDescription_Property_GUID
, UIA_ProviderDescriptionPropertyId
},
4534 { &IsItemContainerPatternAvailable_Property_GUID
, UIA_IsItemContainerPatternAvailablePropertyId
},
4535 { &IsVirtualizedItemPatternAvailable_Property_GUID
, UIA_IsVirtualizedItemPatternAvailablePropertyId
},
4536 { &IsSynchronizedInputPatternAvailable_Property_GUID
, UIA_IsSynchronizedInputPatternAvailablePropertyId
},
4537 /* Implemented on Win8+ */
4538 { &OptimizeForVisualContent_Property_GUID
, UIA_OptimizeForVisualContentPropertyId
},
4539 { &IsObjectModelPatternAvailable_Property_GUID
, UIA_IsObjectModelPatternAvailablePropertyId
},
4540 { &Annotation_AnnotationTypeId_Property_GUID
, UIA_AnnotationAnnotationTypeIdPropertyId
},
4541 { &Annotation_AnnotationTypeName_Property_GUID
, UIA_AnnotationAnnotationTypeNamePropertyId
},
4542 { &Annotation_Author_Property_GUID
, UIA_AnnotationAuthorPropertyId
},
4543 { &Annotation_DateTime_Property_GUID
, UIA_AnnotationDateTimePropertyId
},
4544 { &Annotation_Target_Property_GUID
, UIA_AnnotationTargetPropertyId
},
4545 { &IsAnnotationPatternAvailable_Property_GUID
, UIA_IsAnnotationPatternAvailablePropertyId
},
4546 { &IsTextPattern2Available_Property_GUID
, UIA_IsTextPattern2AvailablePropertyId
},
4547 { &Styles_StyleId_Property_GUID
, UIA_StylesStyleIdPropertyId
},
4548 { &Styles_StyleName_Property_GUID
, UIA_StylesStyleNamePropertyId
},
4549 { &Styles_FillColor_Property_GUID
, UIA_StylesFillColorPropertyId
},
4550 { &Styles_FillPatternStyle_Property_GUID
, UIA_StylesFillPatternStylePropertyId
},
4551 { &Styles_Shape_Property_GUID
, UIA_StylesShapePropertyId
},
4552 { &Styles_FillPatternColor_Property_GUID
, UIA_StylesFillPatternColorPropertyId
},
4553 { &Styles_ExtendedProperties_Property_GUID
, UIA_StylesExtendedPropertiesPropertyId
},
4554 { &IsStylesPatternAvailable_Property_GUID
, UIA_IsStylesPatternAvailablePropertyId
},
4555 { &IsSpreadsheetPatternAvailable_Property_GUID
, UIA_IsSpreadsheetPatternAvailablePropertyId
},
4556 { &SpreadsheetItem_Formula_Property_GUID
, UIA_SpreadsheetItemFormulaPropertyId
},
4557 { &SpreadsheetItem_AnnotationObjects_Property_GUID
, UIA_SpreadsheetItemAnnotationObjectsPropertyId
},
4558 { &SpreadsheetItem_AnnotationTypes_Property_GUID
, UIA_SpreadsheetItemAnnotationTypesPropertyId
},
4559 { &IsSpreadsheetItemPatternAvailable_Property_GUID
, UIA_IsSpreadsheetItemPatternAvailablePropertyId
},
4560 { &Transform2_CanZoom_Property_GUID
, UIA_Transform2CanZoomPropertyId
},
4561 { &IsTransformPattern2Available_Property_GUID
, UIA_IsTransformPattern2AvailablePropertyId
},
4562 { &LiveSetting_Property_GUID
, UIA_LiveSettingPropertyId
},
4563 { &IsTextChildPatternAvailable_Property_GUID
, UIA_IsTextChildPatternAvailablePropertyId
},
4564 { &IsDragPatternAvailable_Property_GUID
, UIA_IsDragPatternAvailablePropertyId
},
4565 { &Drag_IsGrabbed_Property_GUID
, UIA_DragIsGrabbedPropertyId
},
4566 { &Drag_DropEffect_Property_GUID
, UIA_DragDropEffectPropertyId
},
4567 { &Drag_DropEffects_Property_GUID
, UIA_DragDropEffectsPropertyId
},
4568 { &IsDropTargetPatternAvailable_Property_GUID
, UIA_IsDropTargetPatternAvailablePropertyId
},
4569 { &DropTarget_DropTargetEffect_Property_GUID
, UIA_DropTargetDropTargetEffectPropertyId
},
4570 { &DropTarget_DropTargetEffects_Property_GUID
, UIA_DropTargetDropTargetEffectsPropertyId
},
4571 { &Drag_GrabbedItems_Property_GUID
, UIA_DragGrabbedItemsPropertyId
},
4572 { &Transform2_ZoomLevel_Property_GUID
, UIA_Transform2ZoomLevelPropertyId
},
4573 { &Transform2_ZoomMinimum_Property_GUID
, UIA_Transform2ZoomMinimumPropertyId
},
4574 { &Transform2_ZoomMaximum_Property_GUID
, UIA_Transform2ZoomMaximumPropertyId
},
4575 { &FlowsFrom_Property_GUID
, UIA_FlowsFromPropertyId
},
4576 { &IsTextEditPatternAvailable_Property_GUID
, UIA_IsTextEditPatternAvailablePropertyId
},
4577 { &IsPeripheral_Property_GUID
, UIA_IsPeripheralPropertyId
},
4578 /* Implemented on Win10v1507+. */
4579 { &IsCustomNavigationPatternAvailable_Property_GUID
, UIA_IsCustomNavigationPatternAvailablePropertyId
},
4580 { &PositionInSet_Property_GUID
, UIA_PositionInSetPropertyId
},
4581 { &SizeOfSet_Property_GUID
, UIA_SizeOfSetPropertyId
},
4582 { &Level_Property_GUID
, UIA_LevelPropertyId
},
4583 { &AnnotationTypes_Property_GUID
, UIA_AnnotationTypesPropertyId
},
4584 { &AnnotationObjects_Property_GUID
, UIA_AnnotationObjectsPropertyId
},
4585 /* Implemented on Win10v1809+. */
4586 { &LandmarkType_Property_GUID
, UIA_LandmarkTypePropertyId
},
4587 { &LocalizedLandmarkType_Property_GUID
, UIA_LocalizedLandmarkTypePropertyId
},
4588 { &FullDescription_Property_GUID
, UIA_FullDescriptionPropertyId
},
4589 { &FillColor_Property_GUID
, UIA_FillColorPropertyId
},
4590 { &OutlineColor_Property_GUID
, UIA_OutlineColorPropertyId
},
4591 { &FillType_Property_GUID
, UIA_FillTypePropertyId
},
4592 { &VisualEffects_Property_GUID
, UIA_VisualEffectsPropertyId
},
4593 { &OutlineThickness_Property_GUID
, UIA_OutlineThicknessPropertyId
},
4594 { &CenterPoint_Property_GUID
, UIA_CenterPointPropertyId
},
4595 { &Rotation_Property_GUID
, UIA_RotationPropertyId
},
4596 { &Size_Property_GUID
, UIA_SizePropertyId
},
4597 { &IsSelectionPattern2Available_Property_GUID
, UIA_IsSelectionPattern2AvailablePropertyId
},
4598 { &Selection2_FirstSelectedItem_Property_GUID
, UIA_Selection2FirstSelectedItemPropertyId
},
4599 { &Selection2_LastSelectedItem_Property_GUID
, UIA_Selection2LastSelectedItemPropertyId
},
4600 { &Selection2_CurrentSelectedItem_Property_GUID
, UIA_Selection2CurrentSelectedItemPropertyId
},
4601 { &Selection2_ItemCount_Property_GUID
, UIA_Selection2ItemCountPropertyId
},
4602 { &HeadingLevel_Property_GUID
, UIA_HeadingLevelPropertyId
},
4603 { &IsDialog_Property_GUID
, UIA_IsDialogPropertyId
},
4606 static const struct uia_lookup_id uia_event_lookup_ids
[] = {
4607 { &ToolTipOpened_Event_GUID
, UIA_ToolTipOpenedEventId
},
4608 { &ToolTipClosed_Event_GUID
, UIA_ToolTipClosedEventId
},
4609 { &StructureChanged_Event_GUID
, UIA_StructureChangedEventId
},
4610 { &MenuOpened_Event_GUID
, UIA_MenuOpenedEventId
},
4611 { &AutomationPropertyChanged_Event_GUID
, UIA_AutomationPropertyChangedEventId
},
4612 { &AutomationFocusChanged_Event_GUID
, UIA_AutomationFocusChangedEventId
},
4613 { &AsyncContentLoaded_Event_GUID
, UIA_AsyncContentLoadedEventId
},
4614 { &MenuClosed_Event_GUID
, UIA_MenuClosedEventId
},
4615 { &LayoutInvalidated_Event_GUID
, UIA_LayoutInvalidatedEventId
},
4616 { &Invoke_Invoked_Event_GUID
, UIA_Invoke_InvokedEventId
},
4617 { &SelectionItem_ElementAddedToSelectionEvent_Event_GUID
, UIA_SelectionItem_ElementAddedToSelectionEventId
},
4618 { &SelectionItem_ElementRemovedFromSelectionEvent_Event_GUID
, UIA_SelectionItem_ElementRemovedFromSelectionEventId
},
4619 { &SelectionItem_ElementSelectedEvent_Event_GUID
, UIA_SelectionItem_ElementSelectedEventId
},
4620 { &Selection_InvalidatedEvent_Event_GUID
, UIA_Selection_InvalidatedEventId
},
4621 { &Text_TextSelectionChangedEvent_Event_GUID
, UIA_Text_TextSelectionChangedEventId
},
4622 { &Text_TextChangedEvent_Event_GUID
, UIA_Text_TextChangedEventId
},
4623 { &Window_WindowOpened_Event_GUID
, UIA_Window_WindowOpenedEventId
},
4624 { &Window_WindowClosed_Event_GUID
, UIA_Window_WindowClosedEventId
},
4625 { &MenuModeStart_Event_GUID
, UIA_MenuModeStartEventId
},
4626 { &MenuModeEnd_Event_GUID
, UIA_MenuModeEndEventId
},
4627 { &InputReachedTarget_Event_GUID
, UIA_InputReachedTargetEventId
},
4628 { &InputReachedOtherElement_Event_GUID
, UIA_InputReachedOtherElementEventId
},
4629 { &InputDiscarded_Event_GUID
, UIA_InputDiscardedEventId
},
4630 /* Implemented on Win8+ */
4631 { &SystemAlert_Event_GUID
, UIA_SystemAlertEventId
},
4632 { &LiveRegionChanged_Event_GUID
, UIA_LiveRegionChangedEventId
},
4633 { &HostedFragmentRootsInvalidated_Event_GUID
, UIA_HostedFragmentRootsInvalidatedEventId
},
4634 { &Drag_DragStart_Event_GUID
, UIA_Drag_DragStartEventId
},
4635 { &Drag_DragCancel_Event_GUID
, UIA_Drag_DragCancelEventId
},
4636 { &Drag_DragComplete_Event_GUID
, UIA_Drag_DragCompleteEventId
},
4637 { &DropTarget_DragEnter_Event_GUID
, UIA_DropTarget_DragEnterEventId
},
4638 { &DropTarget_DragLeave_Event_GUID
, UIA_DropTarget_DragLeaveEventId
},
4639 { &DropTarget_Dropped_Event_GUID
, UIA_DropTarget_DroppedEventId
},
4640 { &TextEdit_TextChanged_Event_GUID
, UIA_TextEdit_TextChangedEventId
},
4641 { &TextEdit_ConversionTargetChanged_Event_GUID
, UIA_TextEdit_ConversionTargetChangedEventId
},
4642 /* Implemented on Win10v1809+. */
4643 { &Changes_Event_GUID
, UIA_ChangesEventId
},
4644 { &Notification_Event_GUID
, UIA_NotificationEventId
},
4647 static const struct uia_lookup_id uia_pattern_lookup_ids
[] = {
4648 { &Invoke_Pattern_GUID
, UIA_InvokePatternId
},
4649 { &Selection_Pattern_GUID
, UIA_SelectionPatternId
},
4650 { &Value_Pattern_GUID
, UIA_ValuePatternId
},
4651 { &RangeValue_Pattern_GUID
, UIA_RangeValuePatternId
},
4652 { &Scroll_Pattern_GUID
, UIA_ScrollPatternId
},
4653 { &ExpandCollapse_Pattern_GUID
, UIA_ExpandCollapsePatternId
},
4654 { &Grid_Pattern_GUID
, UIA_GridPatternId
},
4655 { &GridItem_Pattern_GUID
, UIA_GridItemPatternId
},
4656 { &MultipleView_Pattern_GUID
, UIA_MultipleViewPatternId
},
4657 { &Window_Pattern_GUID
, UIA_WindowPatternId
},
4658 { &SelectionItem_Pattern_GUID
, UIA_SelectionItemPatternId
},
4659 { &Dock_Pattern_GUID
, UIA_DockPatternId
},
4660 { &Table_Pattern_GUID
, UIA_TablePatternId
},
4661 { &TableItem_Pattern_GUID
, UIA_TableItemPatternId
},
4662 { &Text_Pattern_GUID
, UIA_TextPatternId
},
4663 { &Toggle_Pattern_GUID
, UIA_TogglePatternId
},
4664 { &Transform_Pattern_GUID
, UIA_TransformPatternId
},
4665 { &ScrollItem_Pattern_GUID
, UIA_ScrollItemPatternId
},
4666 { &LegacyIAccessible_Pattern_GUID
, UIA_LegacyIAccessiblePatternId
},
4667 { &ItemContainer_Pattern_GUID
, UIA_ItemContainerPatternId
},
4668 { &VirtualizedItem_Pattern_GUID
, UIA_VirtualizedItemPatternId
},
4669 { &SynchronizedInput_Pattern_GUID
, UIA_SynchronizedInputPatternId
},
4670 /* Implemented on Win8+ */
4671 { &ObjectModel_Pattern_GUID
, UIA_ObjectModelPatternId
},
4672 { &Annotation_Pattern_GUID
, UIA_AnnotationPatternId
},
4673 { &Text_Pattern2_GUID
, UIA_TextPattern2Id
},
4674 { &Styles_Pattern_GUID
, UIA_StylesPatternId
},
4675 { &Spreadsheet_Pattern_GUID
, UIA_SpreadsheetPatternId
},
4676 { &SpreadsheetItem_Pattern_GUID
, UIA_SpreadsheetItemPatternId
},
4677 { &Tranform_Pattern2_GUID
, UIA_TransformPattern2Id
},
4678 { &TextChild_Pattern_GUID
, UIA_TextChildPatternId
},
4679 { &Drag_Pattern_GUID
, UIA_DragPatternId
},
4680 { &DropTarget_Pattern_GUID
, UIA_DropTargetPatternId
},
4681 { &TextEdit_Pattern_GUID
, UIA_TextEditPatternId
},
4682 /* Implemented on Win10+. */
4683 { &CustomNavigation_Pattern_GUID
, UIA_CustomNavigationPatternId
},
4686 static const struct uia_lookup_id uia_control_type_lookup_ids
[] = {
4687 { &Button_Control_GUID
, UIA_ButtonControlTypeId
},
4688 { &Calendar_Control_GUID
, UIA_CalendarControlTypeId
},
4689 { &CheckBox_Control_GUID
, UIA_CheckBoxControlTypeId
},
4690 { &ComboBox_Control_GUID
, UIA_ComboBoxControlTypeId
},
4691 { &Edit_Control_GUID
, UIA_EditControlTypeId
},
4692 { &Hyperlink_Control_GUID
, UIA_HyperlinkControlTypeId
},
4693 { &Image_Control_GUID
, UIA_ImageControlTypeId
},
4694 { &ListItem_Control_GUID
, UIA_ListItemControlTypeId
},
4695 { &List_Control_GUID
, UIA_ListControlTypeId
},
4696 { &Menu_Control_GUID
, UIA_MenuControlTypeId
},
4697 { &MenuBar_Control_GUID
, UIA_MenuBarControlTypeId
},
4698 { &MenuItem_Control_GUID
, UIA_MenuItemControlTypeId
},
4699 { &ProgressBar_Control_GUID
, UIA_ProgressBarControlTypeId
},
4700 { &RadioButton_Control_GUID
, UIA_RadioButtonControlTypeId
},
4701 { &ScrollBar_Control_GUID
, UIA_ScrollBarControlTypeId
},
4702 { &Slider_Control_GUID
, UIA_SliderControlTypeId
},
4703 { &Spinner_Control_GUID
, UIA_SpinnerControlTypeId
},
4704 { &StatusBar_Control_GUID
, UIA_StatusBarControlTypeId
},
4705 { &Tab_Control_GUID
, UIA_TabControlTypeId
},
4706 { &TabItem_Control_GUID
, UIA_TabItemControlTypeId
},
4707 { &Text_Control_GUID
, UIA_TextControlTypeId
},
4708 { &ToolBar_Control_GUID
, UIA_ToolBarControlTypeId
},
4709 { &ToolTip_Control_GUID
, UIA_ToolTipControlTypeId
},
4710 { &Tree_Control_GUID
, UIA_TreeControlTypeId
},
4711 { &TreeItem_Control_GUID
, UIA_TreeItemControlTypeId
},
4712 { &Custom_Control_GUID
, UIA_CustomControlTypeId
},
4713 { &Group_Control_GUID
, UIA_GroupControlTypeId
},
4714 { &Thumb_Control_GUID
, UIA_ThumbControlTypeId
},
4715 { &DataGrid_Control_GUID
, UIA_DataGridControlTypeId
},
4716 { &DataItem_Control_GUID
, UIA_DataItemControlTypeId
},
4717 { &Document_Control_GUID
, UIA_DocumentControlTypeId
},
4718 { &SplitButton_Control_GUID
, UIA_SplitButtonControlTypeId
},
4719 { &Window_Control_GUID
, UIA_WindowControlTypeId
},
4720 { &Pane_Control_GUID
, UIA_PaneControlTypeId
},
4721 { &Header_Control_GUID
, UIA_HeaderControlTypeId
},
4722 { &HeaderItem_Control_GUID
, UIA_HeaderItemControlTypeId
},
4723 { &Table_Control_GUID
, UIA_TableControlTypeId
},
4724 { &TitleBar_Control_GUID
, UIA_TitleBarControlTypeId
},
4725 { &Separator_Control_GUID
, UIA_SeparatorControlTypeId
},
4726 /* Implemented on Win8+ */
4727 { &SemanticZoom_Control_GUID
, UIA_SemanticZoomControlTypeId
},
4728 { &AppBar_Control_GUID
, UIA_AppBarControlTypeId
},
4731 static void test_UiaLookupId(void)
4733 static const struct {
4734 const char *id_type_name
;
4736 const struct uia_lookup_id
*ids
;
4740 { "property", AutomationIdentifierType_Property
, uia_property_lookup_ids
, ARRAY_SIZE(uia_property_lookup_ids
) },
4741 { "event", AutomationIdentifierType_Event
, uia_event_lookup_ids
, ARRAY_SIZE(uia_event_lookup_ids
) },
4742 { "pattern", AutomationIdentifierType_Pattern
, uia_pattern_lookup_ids
, ARRAY_SIZE(uia_pattern_lookup_ids
) },
4743 { "control_type", AutomationIdentifierType_ControlType
, uia_control_type_lookup_ids
, ARRAY_SIZE(uia_control_type_lookup_ids
) },
4747 for (i
= 0; i
< ARRAY_SIZE(tests
); i
++)
4749 for (y
= 0; y
< tests
[i
].ids_count
; y
++)
4751 int id
= UiaLookupId(tests
[i
].id_type
, tests
[i
].ids
[y
].guid
);
4755 win_skip("No %s id for GUID %s, skipping further tests.\n", tests
[i
].id_type_name
, debugstr_guid(tests
[i
].ids
[y
].guid
));
4759 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
);
4764 static const struct prov_method_sequence node_from_prov1
[] = {
4765 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
4769 static const struct prov_method_sequence node_from_prov2
[] = {
4770 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
4771 /* Win10v1507 and below call this. */
4772 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4773 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4774 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
4775 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4776 /* Only called on Windows versions past Win10v1507. */
4777 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4778 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4782 static const struct prov_method_sequence node_from_prov3
[] = {
4783 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
4784 /* Win10v1507 and below call this. */
4785 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4786 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4787 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
4788 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4789 /* Only called on Windows versions past Win10v1507. */
4790 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4791 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4795 static const struct prov_method_sequence node_from_prov4
[] = {
4796 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
4797 /* Win10v1507 and below call this. */
4798 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4799 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4800 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4801 /* Only called on Windows versions past Win10v1507. */
4802 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4803 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4807 static const struct prov_method_sequence node_from_prov5
[] = {
4808 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
4809 /* Win10v1507 and below call this. */
4810 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4811 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4812 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4813 /* Win10v1507 and below call this. */
4814 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4815 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4816 { &Provider2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4817 /* These three are only done on Win10v1507 and below. */
4818 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4819 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4820 { &Provider2
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
4821 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4822 /* This is only done on Win10v1507. */
4823 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4824 /* Only called on Windows versions past Win10v1507. */
4825 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4826 /* Win10v1507 and below call this. */
4827 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_ProviderDescriptionPropertyId */
4828 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4832 static const struct prov_method_sequence node_from_prov6
[] = {
4833 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
4834 /* Win10v1507 and below call this. */
4835 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4836 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4837 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4838 /* Win10v1507 and below call this. */
4839 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4840 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4841 { &Provider2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4842 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4843 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4844 /* Only called on Windows versions past Win10v1507. */
4845 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
4846 { &Provider2
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
4847 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4848 /* This is only done on Win10v1507. */
4849 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4850 /* Only called on Windows versions past Win10v1507. */
4851 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4852 { &Provider2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4853 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4857 static const struct prov_method_sequence node_from_prov7
[] = {
4858 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
4859 /* Win10v1507 and below call this. */
4860 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4861 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4862 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4863 /* Win10v1507 and below call this. */
4864 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4865 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4866 { &Provider2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4867 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4868 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
},
4869 /* Only called on Windows versions past Win10v1507. */
4870 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
4871 { &Provider2
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
4872 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4873 /* This is only done on Win10v1507. */
4874 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4875 /* Only called on Windows versions past Win10v1507. */
4876 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4877 { &Provider2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4878 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
4882 static const struct prov_method_sequence node_from_prov8
[] = {
4883 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
4884 /* Win10v1507 and below call this. */
4885 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
4886 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
4887 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
4888 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
4889 /* Only called on Windows versions past Win10v1507. */
4890 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
4894 static void check_uia_prop_val(PROPERTYID prop_id
, enum UIAutomationType type
, VARIANT
*v
, BOOL from_com
);
4895 static DWORD WINAPI
uia_node_from_provider_test_com_thread(LPVOID param
)
4897 HUIANODE node
= param
;
4902 * Since this is a node representing an IRawElementProviderSimple with
4903 * ProviderOptions_UseComThreading set, it is only usable in threads that
4904 * have initialized COM.
4906 hr
= UiaGetPropertyValue(node
, UIA_ProcessIdPropertyId
, &v
);
4907 ok(hr
== CO_E_NOTINITIALIZED
, "Unexpected hr %#lx\n", hr
);
4909 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4911 hr
= UiaGetPropertyValue(node
, UIA_ProcessIdPropertyId
, &v
);
4912 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
4913 check_uia_prop_val(UIA_ProcessIdPropertyId
, UIAutomationType_Int
, &v
, FALSE
);
4916 * When retrieving a UIAutomationType_Element property, if UseComThreading
4917 * is set, we'll get an HUIANODE that will make calls inside of the
4918 * apartment of the node it is retrieved from. I.e, if we received a node
4919 * with UseComThreading set from another node with UseComThreading set
4920 * inside of an STA, the returned node will have all of its methods called
4921 * from the STA thread.
4923 Provider_child
.prov_opts
= ProviderOptions_UseComThreading
| ProviderOptions_ServerSideProvider
;
4924 Provider_child
.expected_tid
= Provider
.expected_tid
;
4925 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
4926 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
4927 check_uia_prop_val(UIA_LabeledByPropertyId
, UIAutomationType_Element
, &v
, FALSE
);
4929 /* Unset ProviderOptions_UseComThreading. */
4930 Provider_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
4931 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
4932 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
4935 * ProviderOptions_UseComThreading not set, GetPropertyValue will be
4936 * called on the current thread.
4938 Provider_child
.expected_tid
= GetCurrentThreadId();
4939 check_uia_prop_val(UIA_LabeledByPropertyId
, UIAutomationType_Element
, &v
, FALSE
);
4946 static void test_uia_node_from_prov_com_threading(void)
4952 /* Test ProviderOptions_UseComThreading. */
4953 Provider
.hwnd
= NULL
;
4955 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
| ProviderOptions_UseComThreading
;
4956 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
4957 ok_method_sequence(node_from_prov8
, "node_from_prov8");
4960 * On Windows versions prior to Windows 10, UiaNodeFromProvider ignores the
4961 * ProviderOptions_UseComThreading flag.
4965 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
4966 UiaNodeRelease(node
);
4969 ok(hr
== CO_E_NOTINITIALIZED
, "Unexpected hr %#lx.\n", hr
);
4971 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
4972 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
4973 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
4974 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
4975 ok_method_sequence(node_from_prov8
, "node_from_prov8");
4977 Provider
.expected_tid
= GetCurrentThreadId();
4978 thread
= CreateThread(NULL
, 0, uia_node_from_provider_test_com_thread
, (void *)node
, 0, NULL
);
4979 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
) != WAIT_OBJECT_0
)
4982 while(PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
4984 TranslateMessage(&msg
);
4985 DispatchMessageW(&msg
);
4988 CloseHandle(thread
);
4990 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
4991 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
4992 Provider_child
.expected_tid
= Provider
.expected_tid
= 0;
4996 static void test_UiaNodeFromProvider(void)
5006 cls
.lpfnWndProc
= test_wnd_proc
;
5009 cls
.hInstance
= GetModuleHandleA(NULL
);
5012 cls
.hbrBackground
= NULL
;
5013 cls
.lpszMenuName
= NULL
;
5014 cls
.lpszClassName
= "UiaNodeFromProvider class";
5016 RegisterClassA(&cls
);
5018 hwnd
= CreateWindowA("UiaNodeFromProvider class", "Test window", WS_OVERLAPPEDWINDOW
,
5019 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
5021 /* Run these tests early, we end up in an implicit MTA later. */
5022 test_uia_node_from_prov_com_threading();
5024 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
5026 hr
= UiaNodeFromProvider(NULL
, &node
);
5027 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5029 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, NULL
);
5030 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
5032 /* Must have a successful call to get_ProviderOptions. */
5033 Provider
.prov_opts
= 0;
5034 node
= (void *)0xdeadbeef;
5035 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
5036 ok(hr
== E_NOTIMPL
, "Unexpected hr %#lx.\n", hr
);
5037 ok(!node
, "node != NULL\n");
5038 ok_method_sequence(node_from_prov1
, "node_from_prov1");
5040 /* No HWND exposed through Provider. */
5041 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
5042 node
= (void *)0xdeadbeef;
5043 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
5044 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
5046 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5047 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5048 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
5049 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
5052 ok_method_sequence(node_from_prov2
, "node_from_prov2");
5054 /* HUIANODE represents a COM interface. */
5055 ref
= IUnknown_AddRef((IUnknown
*)node
);
5056 ok(ref
== 2, "Unexpected refcnt %ld\n", ref
);
5058 ref
= IUnknown_AddRef((IUnknown
*)node
);
5059 ok(ref
== 3, "Unexpected refcnt %ld\n", ref
);
5061 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5063 ref
= IUnknown_Release((IUnknown
*)node
);
5064 ok(ref
== 1, "Unexpected refcnt %ld\n", ref
);
5066 ref
= IUnknown_Release((IUnknown
*)node
);
5067 ok(ref
== 0, "Unexpected refcnt %ld\n", ref
);
5068 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
5071 * No HWND exposed through Provider_child, but it returns a parent from
5072 * NavigateDirection_Parent. Behavior doesn't change.
5074 Provider_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
5075 node
= (void *)0xdeadbeef;
5076 hr
= UiaNodeFromProvider(&Provider_child
.IRawElementProviderSimple_iface
, &node
);
5077 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5079 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5080 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5081 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
5082 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
5085 ok_method_sequence(node_from_prov3
, "node_from_prov3");
5086 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5087 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5089 /* HWND exposed, but Provider2 not returned from WM_GETOBJECT. */
5090 Provider
.hwnd
= hwnd
;
5092 node
= (void *)0xdeadbeef;
5093 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
5094 /* Win10v1507 and below send this, Windows 7 sends it twice. */
5095 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT
, 2);
5096 Provider
.ignore_hwnd_prop
= TRUE
;
5097 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
5098 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5099 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
5100 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
5101 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
5103 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5104 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5105 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
5106 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
5107 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
5108 check_node_provider_desc_todo(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
5111 Provider
.ignore_hwnd_prop
= FALSE
;
5112 ok_method_sequence(node_from_prov4
, "node_from_prov4");
5114 ok(!!node
, "node == NULL\n");
5115 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5116 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
5119 * Provider is our main provider, since Provider2 is also a main, it won't
5122 Provider
.hwnd
= Provider2
.hwnd
= hwnd
;
5123 Provider
.prov_opts
= Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
5124 Provider
.ignore_hwnd_prop
= Provider2
.ignore_hwnd_prop
= TRUE
;
5125 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
5126 node
= (void *)0xdeadbeef;
5127 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
5128 /* Windows 7 sends this. */
5129 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
5130 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
5131 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5132 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
5133 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
5135 /* Win10v1507 and below hold a reference to the root provider for the HWND */
5136 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
5137 ok(!!node
, "node == NULL\n");
5139 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5140 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5141 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
5142 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
5143 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
5144 check_node_provider_desc_todo(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
5147 Provider
.ignore_hwnd_prop
= Provider2
.ignore_hwnd_prop
= FALSE
;
5148 ok_method_sequence(node_from_prov5
, "node_from_prov5");
5150 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5151 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
5152 ok(Provider2
.ref
== 1, "Unexpected refcnt %ld\n", Provider2
.ref
);
5155 * Provider is classified as an Hwnd provider, Provider2 will become our
5156 * Main provider since we don't have one already.
5158 Provider
.prov_opts
= ProviderOptions_ClientSideProvider
;
5159 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
5160 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
5161 node
= (void *)0xdeadbeef;
5162 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
5163 /* Windows 7 sends this. */
5164 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
5165 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
5166 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5167 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
5168 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
5170 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5171 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5172 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
5173 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider2", TRUE
);
5174 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
5175 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider", FALSE
);
5178 ok_method_sequence(node_from_prov6
, "node_from_prov6");
5180 ok(Provider2
.ref
== 2, "Unexpected refcnt %ld\n", Provider2
.ref
);
5181 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
5183 ok(!!node
, "node == NULL\n");
5184 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5185 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
5186 ok(Provider2
.ref
== 1, "Unexpected refcnt %ld\n", Provider2
.ref
);
5188 /* Provider_child has a parent, so it will be "(parent link)". */
5189 Provider_child
.prov_opts
= ProviderOptions_ClientSideProvider
;
5190 Provider_child
.hwnd
= hwnd
;
5191 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
5192 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
5193 node
= (void *)0xdeadbeef;
5194 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
5195 /* Windows 7 sends this. */
5196 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
5197 hr
= UiaNodeFromProvider(&Provider_child
.IRawElementProviderSimple_iface
, &node
);
5198 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5199 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
5200 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
5202 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5203 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5204 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
5205 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider2", FALSE
);
5206 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
5207 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_child", TRUE
);
5210 ok_method_sequence(node_from_prov7
, "node_from_prov7");
5212 ok(Provider2
.ref
== 2, "Unexpected refcnt %ld\n", Provider2
.ref
);
5213 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
5215 ok(!!node
, "node == NULL\n");
5216 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5217 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
5218 ok(Provider2
.ref
== 1, "Unexpected refcnt %ld\n", Provider2
.ref
);
5221 DestroyWindow(hwnd
);
5222 UnregisterClassA("UiaNodeFromProvider class", NULL
);
5226 /* Sequence for types other than UIAutomationType_Element. */
5227 static const struct prov_method_sequence get_prop_seq
[] = {
5228 { &Provider
, PROV_GET_PROPERTY_VALUE
},
5232 /* Sequence for getting a property that returns an invalid type. */
5233 static const struct prov_method_sequence get_prop_invalid_type_seq
[] = {
5234 { &Provider
, PROV_GET_PROPERTY_VALUE
},
5235 /* Windows 7 calls this. */
5236 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
5240 /* UIAutomationType_Element sequence. */
5241 static const struct prov_method_sequence get_elem_prop_seq
[] = {
5242 { &Provider
, PROV_GET_PROPERTY_VALUE
},
5243 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
5244 /* Win10v1507 and below call this. */
5245 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5246 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
5247 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
5248 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
5249 /* Only called on Windows versions past Win10v1507. */
5250 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
5251 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
},
5255 /* UIAutomationType_ElementArray sequence. */
5256 static const struct prov_method_sequence get_elem_arr_prop_seq
[] = {
5257 { &Provider
, PROV_GET_PROPERTY_VALUE
},
5258 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
5259 /* Win10v1507 and below call this. */
5260 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5261 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
5262 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
5263 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
5264 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
5265 { &Provider_child2
, PROV_GET_PROVIDER_OPTIONS
},
5266 /* Win10v1507 and below call this. */
5267 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5268 { &Provider_child2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
5269 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
5270 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
5271 { &Provider_child2
, PROV_GET_PROVIDER_OPTIONS
},
5272 { &Provider_child
, PROV_GET_PROPERTY_VALUE
},
5273 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
},
5277 static const struct prov_method_sequence get_pattern_prop_seq
[] = {
5278 { &Provider
, PROV_GET_PATTERN_PROV
},
5282 static const struct prov_method_sequence get_pattern_prop_seq2
[] = {
5283 { &Provider
, PROV_GET_PATTERN_PROV
},
5284 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_TODO
},
5288 static const struct prov_method_sequence get_bounding_rect_seq
[] = {
5289 NODE_CREATE_SEQ(&Provider_child
),
5290 { &Provider_child
, FRAG_GET_BOUNDING_RECT
},
5292 * Win10v21H2+ and above call these, attempting to get the fragment root's
5293 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
5295 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5296 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
5297 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5298 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5302 static const struct prov_method_sequence get_bounding_rect_seq2
[] = {
5303 { &Provider
, PROV_GET_PROPERTY_VALUE
},
5304 NODE_CREATE_SEQ(&Provider_child
),
5305 { &Provider_child
, FRAG_GET_BOUNDING_RECT
},
5307 * Win10v21H2+ and above call these, attempting to get the fragment root's
5308 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
5310 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5311 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
5312 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5313 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5317 static const struct prov_method_sequence get_bounding_rect_seq3
[] = {
5318 { &Provider_child
, FRAG_GET_BOUNDING_RECT
},
5320 * Win10v21H2+ and above call these, attempting to get the fragment root's
5321 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
5323 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5324 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
5325 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5326 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5330 static const struct prov_method_sequence get_empty_bounding_rect_seq
[] = {
5331 { &Provider_child
, FRAG_GET_BOUNDING_RECT
},
5335 static void set_uia_rect(struct UiaRect
*rect
, double left
, double top
, double width
, double height
)
5339 rect
->width
= width
;
5340 rect
->height
= height
;
5343 #define check_uia_rect_val( v, rect ) \
5344 check_uia_rect_val_( (v), (rect), __FILE__, __LINE__)
5345 static void check_uia_rect_val_(VARIANT
*v
, struct UiaRect
*rect
, const char *file
, int line
)
5347 LONG lbound
, ubound
, elems
, idx
;
5354 ok_(file
, line
)(V_VT(v
) == (VT_R8
| VT_ARRAY
), "Unexpected rect VT hr %d.\n", V_VT(v
));
5355 if (V_VT(v
) != (VT_R8
| VT_ARRAY
))
5359 hr
= SafeArrayGetVartype(sa
, &vt
);
5360 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5361 ok_(file
, line
)(vt
== VT_R8
, "Unexpected vt %d\n", vt
);
5363 dims
= SafeArrayGetDim(sa
);
5364 ok_(file
, line
)(dims
== 1, "Unexpected dims %d\n", dims
);
5366 lbound
= ubound
= elems
= 0;
5367 hr
= SafeArrayGetLBound(sa
, 1, &lbound
);
5368 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr
);
5369 ok_(file
, line
)(lbound
== 0, "Unexpected lbound %ld\n", lbound
);
5371 hr
= SafeArrayGetUBound(sa
, 1, &ubound
);
5372 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr
);
5373 ok_(file
, line
)(ubound
== 3, "Unexpected ubound %ld\n", ubound
);
5375 elems
= (ubound
- lbound
) + 1;
5376 ok_(file
, line
)(elems
== 4, "Unexpected rect elems %ld\n", elems
);
5378 for (idx
= 0; idx
< ARRAY_SIZE(tmp
); idx
++)
5380 hr
= SafeArrayGetElement(sa
, &idx
, &tmp
[idx
]);
5381 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetElement at idx %ld.\n", hr
, idx
);
5384 ok_(file
, line
)(tmp
[0] == rect
->left
, "Unexpected left value %f, expected %f\n", tmp
[0], rect
->left
);
5385 ok_(file
, line
)(tmp
[1] == rect
->top
, "Unexpected top value %f, expected %f\n", tmp
[1], rect
->top
);
5386 ok_(file
, line
)(tmp
[2] == rect
->width
, "Unexpected width value %f, expected %f\n", tmp
[2], rect
->width
);
5387 ok_(file
, line
)(tmp
[3] == rect
->height
, "Unexpected height value %f, expected %f\n", tmp
[3], rect
->height
);
5390 #define check_uia_rect_rect_val( rect, uia_rect ) \
5391 check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__)
5392 static void check_uia_rect_rect_val_(RECT
*rect
, struct UiaRect
*uia_rect
, const char *file
, int line
)
5394 ok_(file
, line
)(rect
->left
== (LONG
)uia_rect
->left
, "Unexpected left value %ld, expected %ld\n", rect
->left
, (LONG
)uia_rect
->left
);
5395 ok_(file
, line
)(rect
->top
== (LONG
)uia_rect
->top
, "Unexpected top value %ld, expected %ld\n", rect
->top
, (LONG
)uia_rect
->top
);
5396 ok_(file
, line
)(rect
->right
== (LONG
)(uia_rect
->left
+ uia_rect
->width
), "Unexpected right value %ld, expected %ld\n", rect
->right
,
5397 (LONG
)(uia_rect
->left
+ uia_rect
->width
));
5398 ok_(file
, line
)(rect
->bottom
== (LONG
)(uia_rect
->top
+ uia_rect
->height
), "Unexpected bottom value %ld, expected %ld\n", rect
->bottom
,
5399 (LONG
)(uia_rect
->top
+ uia_rect
->height
));
5402 static void check_uia_prop_val(PROPERTYID prop_id
, enum UIAutomationType type
, VARIANT
*v
, BOOL from_com
)
5408 case UIAutomationType_String
:
5409 ok(V_VT(v
) == VT_BSTR
, "Unexpected VT %d\n", V_VT(v
));
5410 ok(!lstrcmpW(V_BSTR(v
), uia_bstr_prop_str
), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(v
)));
5411 ok_method_sequence(get_prop_seq
, NULL
);
5414 case UIAutomationType_Bool
:
5415 ok(V_VT(v
) == VT_BOOL
, "Unexpected VT %d\n", V_VT(v
));
5417 /* UIA_IsKeyboardFocusablePropertyId is broken on Win8 and Win10v1507. */
5418 if (prop_id
== UIA_IsKeyboardFocusablePropertyId
)
5419 ok(check_variant_bool(v
, TRUE
) || broken(check_variant_bool(v
, FALSE
)),
5420 "Unexpected BOOL %#x\n", V_BOOL(v
));
5422 ok(check_variant_bool(v
, TRUE
), "Unexpected BOOL %#x\n", V_BOOL(v
));
5423 ok_method_sequence(get_prop_seq
, NULL
);
5426 case UIAutomationType_Int
:
5427 ok(V_VT(v
) == VT_I4
, "Unexpected VT %d\n", V_VT(v
));
5429 if (prop_id
== UIA_NativeWindowHandlePropertyId
)
5430 ok(ULongToHandle(V_I4(v
)) == Provider
.hwnd
, "Unexpected I4 %#lx\n", V_I4(v
));
5432 ok(V_I4(v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(v
));
5433 ok_method_sequence(get_prop_seq
, NULL
);
5436 case UIAutomationType_IntArray
:
5437 ok(V_VT(v
) == (VT_ARRAY
| VT_I4
), "Unexpected VT %d\n", V_VT(v
));
5439 for (idx
= 0; idx
< ARRAY_SIZE(uia_i4_arr_prop_val
); idx
++)
5443 SafeArrayGetElement(V_ARRAY(v
), &idx
, &val
);
5444 ok(val
== uia_i4_arr_prop_val
[idx
], "Unexpected I4 %#lx at idx %ld\n", val
, idx
);
5446 ok_method_sequence(get_prop_seq
, NULL
);
5449 case UIAutomationType_Double
:
5450 ok(V_VT(v
) == VT_R8
, "Unexpected VT %d\n", V_VT(v
));
5451 ok(V_R8(v
) == uia_r8_prop_val
, "Unexpected R8 %lf\n", V_R8(v
));
5452 ok_method_sequence(get_prop_seq
, NULL
);
5455 case UIAutomationType_DoubleArray
:
5456 ok(V_VT(v
) == (VT_ARRAY
| VT_R8
), "Unexpected VT %d\n", V_VT(v
));
5457 for (idx
= 0; idx
< ARRAY_SIZE(uia_r8_arr_prop_val
); idx
++)
5461 SafeArrayGetElement(V_ARRAY(v
), &idx
, &val
);
5462 ok(val
== uia_r8_arr_prop_val
[idx
], "Unexpected R8 %lf at idx %ld\n", val
, idx
);
5464 ok_method_sequence(get_prop_seq
, NULL
);
5467 case UIAutomationType_Element
:
5475 IUIAutomationElement
*elem
;
5477 ok(V_VT(v
) == VT_UNKNOWN
, "Unexpected VT %d\n", V_VT(v
));
5478 hr
= IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IUIAutomationElement
, (void **)&elem
);
5480 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5481 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5483 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(elem
, UIA_ControlTypePropertyId
, TRUE
, &v1
);
5484 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5485 IUIAutomationElement_Release(elem
);
5490 ok(V_VT(v
) == VT_I8
, "Unexpected VT %d\n", V_VT(v
));
5491 tmp_node
= (HUIANODE
)V_I8(v
);
5493 ok(V_VT(v
) == VT_I4
, "Unexpected VT %d\n", V_VT(v
));
5494 tmp_node
= (HUIANODE
)V_I4(v
);
5496 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5498 hr
= UiaGetPropertyValue(tmp_node
, UIA_ControlTypePropertyId
, &v1
);
5499 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5500 ok(UiaNodeRelease(tmp_node
), "Failed to release node\n");
5503 ok(V_VT(&v1
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v1
));
5504 ok(V_I4(&v1
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v1
));
5505 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5507 ok_method_sequence(get_elem_prop_seq
, NULL
);
5511 case UIAutomationType_ElementArray
:
5512 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5513 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
5516 IUIAutomationElementArray
*elem_arr
= NULL
;
5520 ok(V_VT(v
) == VT_UNKNOWN
, "Unexpected VT %d\n", V_VT(v
));
5521 hr
= IUnknown_QueryInterface(V_UNKNOWN(v
), &IID_IUIAutomationElementArray
, (void **)&elem_arr
);
5522 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5523 ok(!!elem_arr
, "elem_arr == NULL\n");
5530 hr
= IUIAutomationElementArray_get_Length(elem_arr
, &len
);
5531 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5532 ok(len
== ARRAY_SIZE(uia_unk_arr_prop_val
), "Unexpected length %d\n", len
);
5534 for (idx
= 0; idx
< ARRAY_SIZE(uia_unk_arr_prop_val
); idx
++)
5536 IUIAutomationElement
*tmp_elem
= NULL
;
5539 hr
= IUIAutomationElementArray_GetElement(elem_arr
, idx
, &tmp_elem
);
5540 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5541 ok(!!tmp_elem
, "tmp_elem == NULL\n");
5543 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(tmp_elem
, UIA_ControlTypePropertyId
, TRUE
, &v1
);
5544 ok(hr
== S_OK
, "elem[%ld] Unexpected hr %#lx\n", idx
, hr
);
5545 ok(V_VT(&v1
) == VT_I4
, "elem[%ld] Unexpected VT %d\n", idx
, V_VT(&v1
));
5546 ok(V_I4(&v1
) == uia_i4_prop_val
, "elem[%ld] Unexpected I4 %#lx\n", idx
, V_I4(&v1
));
5548 IUIAutomationElement_Release(tmp_elem
);
5552 IUIAutomationElementArray_Release(elem_arr
);
5556 ok(V_VT(v
) == (VT_ARRAY
| VT_UNKNOWN
), "Unexpected VT %d\n", V_VT(v
));
5557 if (V_VT(v
) != (VT_ARRAY
| VT_UNKNOWN
))
5560 for (idx
= 0; idx
< ARRAY_SIZE(uia_unk_arr_prop_val
); idx
++)
5566 SafeArrayGetElement(V_ARRAY(v
), &idx
, &tmp_node
);
5568 hr
= UiaGetPropertyValue(tmp_node
, UIA_ControlTypePropertyId
, &v1
);
5569 ok(hr
== S_OK
, "node[%ld] Unexpected hr %#lx\n", idx
, hr
);
5570 ok(V_VT(&v1
) == VT_I4
, "node[%ld] Unexpected VT %d\n", idx
, V_VT(&v1
));
5571 ok(V_I4(&v1
) == uia_i4_prop_val
, "node[%ld] Unexpected I4 %#lx\n", idx
, V_I4(&v1
));
5573 ok(UiaNodeRelease(tmp_node
), "Failed to release node[%ld]\n", idx
);
5579 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5580 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
5581 ok_method_sequence(get_elem_arr_prop_seq
, NULL
);
5592 struct uia_element_property
{
5593 const GUID
*prop_guid
;
5594 enum UIAutomationType type
;
5598 static const struct uia_element_property element_properties
[] = {
5599 { &ProcessId_Property_GUID
, UIAutomationType_Int
, TRUE
},
5600 { &ControlType_Property_GUID
, UIAutomationType_Int
},
5601 { &LocalizedControlType_Property_GUID
, UIAutomationType_String
, TRUE
},
5602 { &Name_Property_GUID
, UIAutomationType_String
},
5603 { &AcceleratorKey_Property_GUID
, UIAutomationType_String
},
5604 { &AccessKey_Property_GUID
, UIAutomationType_String
},
5605 { &HasKeyboardFocus_Property_GUID
, UIAutomationType_Bool
},
5606 { &IsKeyboardFocusable_Property_GUID
, UIAutomationType_Bool
},
5607 { &IsEnabled_Property_GUID
, UIAutomationType_Bool
},
5608 { &AutomationId_Property_GUID
, UIAutomationType_String
},
5609 { &ClassName_Property_GUID
, UIAutomationType_String
},
5610 { &HelpText_Property_GUID
, UIAutomationType_String
},
5611 { &Culture_Property_GUID
, UIAutomationType_Int
},
5612 { &IsControlElement_Property_GUID
, UIAutomationType_Bool
},
5613 { &IsContentElement_Property_GUID
, UIAutomationType_Bool
},
5614 { &LabeledBy_Property_GUID
, UIAutomationType_Element
},
5615 { &IsPassword_Property_GUID
, UIAutomationType_Bool
},
5616 { &NewNativeWindowHandle_Property_GUID
, UIAutomationType_Int
},
5617 { &ItemType_Property_GUID
, UIAutomationType_String
},
5618 { &IsOffscreen_Property_GUID
, UIAutomationType_Bool
},
5619 { &Orientation_Property_GUID
, UIAutomationType_Int
},
5620 { &FrameworkId_Property_GUID
, UIAutomationType_String
},
5621 { &IsRequiredForForm_Property_GUID
, UIAutomationType_Bool
},
5622 { &ItemStatus_Property_GUID
, UIAutomationType_String
},
5623 { &AriaRole_Property_GUID
, UIAutomationType_String
},
5624 { &AriaProperties_Property_GUID
, UIAutomationType_String
},
5625 { &IsDataValidForForm_Property_GUID
, UIAutomationType_Bool
},
5626 { &ControllerFor_Property_GUID
, UIAutomationType_ElementArray
},
5627 { &DescribedBy_Property_GUID
, UIAutomationType_ElementArray
},
5628 { &FlowsTo_Property_GUID
, UIAutomationType_ElementArray
},
5629 /* Implemented on Win8+ */
5630 { &OptimizeForVisualContent_Property_GUID
, UIAutomationType_Bool
},
5631 { &LiveSetting_Property_GUID
, UIAutomationType_Int
},
5632 { &FlowsFrom_Property_GUID
, UIAutomationType_ElementArray
},
5633 { &IsPeripheral_Property_GUID
, UIAutomationType_Bool
},
5634 /* Implemented on Win10v1507+. */
5635 { &PositionInSet_Property_GUID
, UIAutomationType_Int
},
5636 { &SizeOfSet_Property_GUID
, UIAutomationType_Int
},
5637 { &Level_Property_GUID
, UIAutomationType_Int
},
5638 { &AnnotationTypes_Property_GUID
, UIAutomationType_IntArray
},
5639 { &AnnotationObjects_Property_GUID
, UIAutomationType_ElementArray
},
5640 /* Implemented on Win10v1809+. */
5641 { &LandmarkType_Property_GUID
, UIAutomationType_Int
},
5642 { &LocalizedLandmarkType_Property_GUID
, UIAutomationType_String
, TRUE
},
5643 { &FullDescription_Property_GUID
, UIAutomationType_String
},
5644 { &FillColor_Property_GUID
, UIAutomationType_Int
},
5645 { &OutlineColor_Property_GUID
, UIAutomationType_IntArray
},
5646 { &FillType_Property_GUID
, UIAutomationType_Int
},
5647 { &VisualEffects_Property_GUID
, UIAutomationType_Int
},
5648 { &OutlineThickness_Property_GUID
, UIAutomationType_DoubleArray
},
5649 { &Rotation_Property_GUID
, UIAutomationType_Double
},
5650 { &Size_Property_GUID
, UIAutomationType_DoubleArray
},
5651 { &HeadingLevel_Property_GUID
, UIAutomationType_Int
},
5652 { &IsDialog_Property_GUID
, UIAutomationType_Bool
},
5655 static void test_UiaGetPropertyValue(void)
5657 const struct uia_element_property
*elem_prop
;
5658 struct UiaRect rect
;
5666 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
5668 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
5669 Provider_child
.prov_opts
= Provider_child2
.prov_opts
= ProviderOptions_ServerSideProvider
;
5670 Provider
.hwnd
= Provider_child
.hwnd
= Provider_child2
.hwnd
= NULL
;
5671 node
= (void *)0xdeadbeef;
5672 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
5673 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5674 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
5675 ok_method_sequence(node_from_prov8
, NULL
);
5677 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
5678 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5680 for (i
= 0; i
< ARRAY_SIZE(element_properties
); i
++)
5682 elem_prop
= &element_properties
[i
];
5684 Provider
.ret_invalid_prop_type
= FALSE
;
5686 prop_id
= UiaLookupId(AutomationIdentifierType_Property
, elem_prop
->prop_guid
);
5689 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop
->prop_guid
));
5692 winetest_push_context("prop_id %d", prop_id
);
5693 hr
= UiaGetPropertyValue(node
, prop_id
, &v
);
5694 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5695 check_uia_prop_val(prop_id
, elem_prop
->type
, &v
, FALSE
);
5698 * Some properties have special behavior if an invalid value is
5699 * returned, skip them here.
5701 if (!elem_prop
->skip_invalid
)
5703 Provider
.ret_invalid_prop_type
= TRUE
;
5704 hr
= UiaGetPropertyValue(node
, prop_id
, &v
);
5705 if (hr
== E_NOTIMPL
)
5706 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5708 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5711 ok_method_sequence(get_prop_invalid_type_seq
, NULL
);
5712 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
5713 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
5718 winetest_pop_context();
5721 /* IValueProvider pattern property IDs. */
5722 Provider
.value_pattern_data
.is_supported
= FALSE
;
5723 hr
= UiaGetPropertyValue(node
, UIA_ValueIsReadOnlyPropertyId
, &v
);
5724 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5725 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
5726 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
5727 ok_method_sequence(get_pattern_prop_seq
, NULL
);
5730 Provider
.value_pattern_data
.is_supported
= TRUE
;
5731 for (i
= 0; i
< 2; i
++)
5733 Provider
.value_pattern_data
.is_read_only
= i
;
5735 hr
= UiaGetPropertyValue(node
, UIA_ValueIsReadOnlyPropertyId
, &v
);
5736 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5737 ok(V_VT(&v
) == VT_BOOL
, "Unexpected VT %d\n", V_VT(&v
));
5738 ok(check_variant_bool(&v
, i
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
5739 ok_method_sequence(get_pattern_prop_seq
, NULL
);
5743 /* ILegacyIAccessibleProvider pattern property IDs. */
5744 Provider
.legacy_acc_pattern_data
.is_supported
= FALSE
;
5745 hr
= UiaGetPropertyValue(node
, UIA_LegacyIAccessibleChildIdPropertyId
, &v
);
5746 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5747 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
5748 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
5749 ok_method_sequence(get_pattern_prop_seq2
, NULL
);
5752 Provider
.legacy_acc_pattern_data
.is_supported
= TRUE
;
5753 for (i
= 0; i
< 2; i
++)
5755 Provider
.legacy_acc_pattern_data
.child_id
= i
;
5757 hr
= UiaGetPropertyValue(node
, UIA_LegacyIAccessibleChildIdPropertyId
, &v
);
5758 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5759 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
5760 ok(V_I4(&v
) == i
, "Unexpected I4 %#lx\n", V_I4(&v
));
5761 ok_method_sequence(get_pattern_prop_seq
, NULL
);
5765 for (i
= 0; i
< 2; i
++)
5767 Provider
.legacy_acc_pattern_data
.role
= i
;
5769 hr
= UiaGetPropertyValue(node
, UIA_LegacyIAccessibleRolePropertyId
, &v
);
5770 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5771 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
5772 ok(V_I4(&v
) == i
, "Unexpected I4 %#lx\n", V_I4(&v
));
5773 ok_method_sequence(get_pattern_prop_seq
, NULL
);
5777 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5778 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
5779 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
5782 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
5783 * It's the only version with this behavior.
5785 if (!UiaLookupId(AutomationIdentifierType_Property
, &OptimizeForVisualContent_Property_GUID
))
5787 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
5791 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
5792 node
= (void *)0xdeadbeef;
5793 hr
= UiaNodeFromProvider(&Provider_child
.IRawElementProviderSimple_iface
, &node
);
5794 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5795 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5797 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
5798 set_uia_rect(&rect
, 0, 0, 50, 50);
5799 Provider_child
.bounds_rect
= rect
;
5800 hr
= UiaGetPropertyValue(node
, UIA_BoundingRectanglePropertyId
, &v
);
5801 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5802 check_uia_rect_val(&v
, &rect
);
5805 ok_method_sequence(get_bounding_rect_seq
, "get_bounding_rect_seq");
5807 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
5808 set_uia_rect(&rect
, 0, 0, 0, 0);
5809 Provider_child
.bounds_rect
= rect
;
5810 hr
= UiaGetPropertyValue(node
, UIA_BoundingRectanglePropertyId
, &v
);
5811 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5812 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
5813 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
5815 ok_method_sequence(get_empty_bounding_rect_seq
, "get_empty_bounding_rect_seq");
5817 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
5818 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5819 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
5823 IUnknown_Release(unk_ns
);
5827 static const struct prov_method_sequence get_runtime_id1
[] = {
5828 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5832 static const struct prov_method_sequence get_runtime_id2
[] = {
5833 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5834 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
5838 static const struct prov_method_sequence get_runtime_id3
[] = {
5839 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5840 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
5841 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
5842 /* Not called on Windows 7. */
5843 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5844 /* Only called on Win8+. */
5845 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5846 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
5847 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5848 { &Provider2
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5852 static const struct prov_method_sequence get_runtime_id4
[] = {
5853 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5854 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
5855 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
5856 /* Not called on Windows 7. */
5857 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
5858 /* These methods are only called on Win8+. */
5859 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
5860 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
5861 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
5865 static const struct prov_method_sequence get_runtime_id5
[] = {
5866 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
5867 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
5868 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
5869 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
5873 static void test_UiaGetRuntimeId(void)
5875 const int root_prov_opts
[] = { ProviderOptions_ServerSideProvider
, ProviderOptions_ServerSideProvider
| ProviderOptions_OverrideProvider
,
5876 ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
};
5877 int rt_id
[4], tmp
, i
;
5888 cls
.lpfnWndProc
= test_wnd_proc
;
5891 cls
.hInstance
= GetModuleHandleA(NULL
);
5894 cls
.hbrBackground
= NULL
;
5895 cls
.lpszMenuName
= NULL
;
5896 cls
.lpszClassName
= "UiaGetRuntimeId class";
5898 RegisterClassA(&cls
);
5900 hwnd
= CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW
,
5901 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
5903 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
5904 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5906 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
5907 Provider
.prov_opts
= Provider2
.prov_opts
= Provider_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
5908 Provider
.hwnd
= Provider2
.hwnd
= Provider_child
.hwnd
= NULL
;
5909 node
= (void *)0xdeadbeef;
5910 hr
= UiaNodeFromProvider(&Provider_child
.IRawElementProviderSimple_iface
, &node
);
5911 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5912 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
5914 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
5915 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
5916 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
5917 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
5920 ok_method_sequence(node_from_prov3
, NULL
);
5922 /* NULL runtime ID. */
5923 Provider_child
.runtime_id
[0] = Provider_child
.runtime_id
[1] = 0;
5924 sa
= (void *)0xdeadbeef;
5925 hr
= UiaGetRuntimeId(node
, &sa
);
5926 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5927 ok(!sa
, "sa != NULL\n");
5928 ok_method_sequence(get_runtime_id1
, "get_runtime_id1");
5930 /* No UiaAppendRuntimeId prefix, returns GetRuntimeId array directly. */
5931 Provider_child
.runtime_id
[0] = rt_id
[0] = 5;
5932 Provider_child
.runtime_id
[1] = rt_id
[1] = 2;
5933 sa
= (void *)0xdeadbeef;
5934 hr
= UiaGetRuntimeId(node
, &sa
);
5935 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5936 ok(!!sa
, "sa == NULL\n");
5937 check_runtime_id(rt_id
, 2, sa
);
5938 SafeArrayDestroy(sa
);
5939 ok_method_sequence(get_runtime_id1
, "get_runtime_id1");
5942 * If a provider returns a RuntimeId beginning with the constant
5943 * UiaAppendRuntimeId, UI Automation will add a prefix based on the
5944 * providers HWND fragment root before returning to the client. The added
5945 * prefix is 3 int values, with:
5947 * idx[0] always being 42. (UIA_RUNTIME_ID_PREFIX)
5948 * idx[1] always being the HWND.
5949 * idx[2] has three different values depending on what type of provider
5950 * the fragment root is. Fragment roots can be an override provider, a
5951 * nonclient provider, or a main provider.
5953 Provider_child
.frag_root
= NULL
;
5954 Provider_child
.runtime_id
[0] = UiaAppendRuntimeId
;
5955 Provider_child
.runtime_id
[1] = 2;
5956 sa
= (void *)0xdeadbeef;
5958 /* Provider_child has no fragment root for UiaAppendRuntimeId. */
5959 hr
= UiaGetRuntimeId(node
, &sa
);
5960 /* Windows 7 returns S_OK. */
5961 ok(hr
== E_FAIL
|| broken(hr
== S_OK
), "Unexpected hr %#lx.\n", hr
);
5962 ok(!sa
, "sa != NULL\n");
5963 ok_method_sequence(get_runtime_id2
, "get_runtime_id2");
5966 * UIA_RuntimeIdPropertyId won't return a failure code from
5967 * UiaGetPropertyValue.
5969 hr
= UiaGetPropertyValue(node
, UIA_RuntimeIdPropertyId
, &v
);
5970 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
5971 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
5972 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
5974 ok_method_sequence(get_runtime_id2
, "get_runtime_id2");
5977 * Provider_child returns a fragment root that doesn't expose an HWND. On
5978 * Win8+, fragment roots are navigated recursively until either a NULL
5979 * fragment root is returned, the same fragment root as the current one is
5980 * returned, or a fragment root with an HWND is returned.
5982 Provider_child
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
5983 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
5984 Provider2
.hwnd
= NULL
;
5985 Provider
.frag_root
= &Provider2
.IRawElementProviderFragmentRoot_iface
;
5986 Provider
.hwnd
= NULL
;
5987 Provider_child
.runtime_id
[0] = UiaAppendRuntimeId
;
5988 Provider_child
.runtime_id
[1] = 2;
5989 sa
= (void *)0xdeadbeef;
5990 hr
= UiaGetRuntimeId(node
, &sa
);
5991 /* Windows 7 returns S_OK. */
5992 ok(hr
== E_FAIL
|| broken(hr
== S_OK
), "Unexpected hr %#lx.\n", hr
);
5993 ok(!sa
, "sa != NULL\n");
5994 ok_method_sequence(get_runtime_id3
, "get_runtime_id3");
5996 /* Provider2 returns an HWND. */
5997 Provider
.hwnd
= NULL
;
5998 Provider
.frag_root
= &Provider2
.IRawElementProviderFragmentRoot_iface
;
5999 Provider2
.hwnd
= hwnd
;
6000 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
6001 Provider_child
.runtime_id
[0] = UiaAppendRuntimeId
;
6002 Provider_child
.runtime_id
[1] = rt_id
[3] = 2;
6004 hr
= UiaGetRuntimeId(node
, &sa
);
6005 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6006 /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */
6007 ok(!!sa
|| broken(!sa
), "sa == NULL\n");
6008 SafeArrayDestroy(sa
);
6010 ok_method_sequence(get_runtime_id4
, "get_runtime_id4");
6012 /* Test RuntimeId values for different root fragment provider types. */
6013 Provider
.frag_root
= NULL
;
6014 Provider
.hwnd
= hwnd
;
6015 Provider_child
.runtime_id
[0] = UiaAppendRuntimeId
;
6016 Provider_child
.runtime_id
[1] = rt_id
[3] = 2;
6017 rt_id
[0] = UIA_RUNTIME_ID_PREFIX
;
6018 rt_id
[1] = HandleToULong(hwnd
);
6019 for (i
= 0; i
< ARRAY_SIZE(root_prov_opts
); i
++)
6023 Provider
.prov_opts
= root_prov_opts
[i
];
6025 hr
= UiaGetRuntimeId(node
, &sa
);
6026 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6027 ok(!!sa
, "sa == NULL\n");
6029 hr
= SafeArrayGetLBound(sa
, 1, &lbound
);
6030 ok(hr
== S_OK
, "Failed to get LBound with hr %#lx\n", hr
);
6032 lbound
= lbound
+ 2;
6033 hr
= SafeArrayGetElement(sa
, &lbound
, &tmp
);
6034 ok(hr
== S_OK
, "Failed to get element with hr %#lx\n", hr
);
6036 ok(rt_id
[2] != tmp
, "Expected different runtime id value from previous\n");
6039 check_runtime_id(rt_id
, 4, sa
);
6041 SafeArrayDestroy(sa
);
6042 ok_method_sequence(get_runtime_id5
, "get_runtime_id5");
6045 UiaNodeRelease(node
);
6047 /* Test behavior on a node with an associated HWND. */
6048 Provider
.prov_opts
= ProviderOptions_ClientSideProvider
;
6049 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
6050 Provider
.hwnd
= Provider2
.hwnd
= hwnd
;
6051 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
6052 node
= (void *)0xdeadbeef;
6053 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6054 /* Windows 7 sends this. */
6055 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
6056 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
6057 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6058 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6059 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
6062 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6063 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6064 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6065 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider2", TRUE
);
6066 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6067 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider", FALSE
);
6070 ok_method_sequence(node_from_prov6
, "node_from_prov6");
6072 /* No methods called, RuntimeId is based on the node's HWND. */
6073 hr
= UiaGetRuntimeId(node
, &sa
);
6074 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6075 ok(!!sa
, "sa == NULL\n");
6076 ok(!sequence_cnt
, "Unexpected sequence_cnt %d\n", sequence_cnt
);
6078 rt_id
[0] = UIA_RUNTIME_ID_PREFIX
;
6079 rt_id
[1] = HandleToULong(hwnd
);
6080 check_runtime_id(rt_id
, 2, sa
);
6081 SafeArrayDestroy(sa
);
6082 UiaNodeRelease(node
);
6084 DestroyWindow(hwnd
);
6085 UnregisterClassA("UiaGetRuntimeId class", NULL
);
6089 static const struct prov_method_sequence node_from_var_seq
[] = {
6090 NODE_CREATE_SEQ(&Provider
),
6094 static void test_UiaHUiaNodeFromVariant(void)
6096 HUIANODE node
, node2
;
6101 hr
= UiaHUiaNodeFromVariant(NULL
, &node
);
6102 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6104 hr
= UiaHUiaNodeFromVariant(&v
, NULL
);
6105 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6107 node
= (void *)0xdeadbeef;
6109 hr
= UiaHUiaNodeFromVariant(&v
, &node
);
6110 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6111 ok(!node
, "node != NULL\n");
6114 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
6115 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
6116 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6117 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
6118 ok(!!node
, "node == NULL\n");
6119 ok_method_sequence(node_from_var_seq
, "node_from_var_seq");
6121 node2
= (void *)0xdeadbeef;
6122 V_VT(&v
) = VT_UNKNOWN
;
6123 V_UNKNOWN(&v
) = (IUnknown
*)node
;
6124 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6125 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6126 ok(node
== node2
, "node != NULL\n");
6128 node_ref
= IUnknown_AddRef((IUnknown
*)node
);
6129 ok(node_ref
== 3, "Unexpected node_ref %ld\n", node_ref
);
6131 IUnknown_Release((IUnknown
*)node
);
6134 node2
= (void *)0xdeadbeef;
6136 V_I4(&v
) = 0xbeefdead;
6137 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6138 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6139 ok(!node2
, "node2 != NULL\n");
6141 node2
= (void *)0xdeadbeef;
6143 V_I8(&v
) = (UINT64
)node
;
6144 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6145 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6146 ok(node2
== (void *)V_I8(&v
), "node2 != V_I8\n");
6148 node2
= (void *)0xdeadbeef;
6150 V_I8(&v
) = 0xbeefdead;
6151 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6152 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6153 ok(!node2
, "node2 != NULL\n");
6155 node2
= (void *)0xdeadbeef;
6157 V_I4(&v
) = (UINT32
)node
;
6158 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6159 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6160 ok(node2
== (void *)V_I4(&v
), "node2 != V_I4\n");
6163 UiaNodeRelease(node
);
6166 static const struct prov_method_sequence node_from_hwnd1
[] = {
6167 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6171 static const struct prov_method_sequence node_from_hwnd2
[] = {
6172 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6173 /* Win10v1507 and below call this. */
6174 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6175 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6176 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6177 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6178 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6179 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6180 /* Windows 10+ calls this. */
6181 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6182 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
6186 static const struct prov_method_sequence node_from_hwnd3
[] = {
6187 NODE_CREATE_SEQ2(&Provider
),
6188 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6189 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win11+ */
6190 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
6191 NODE_CREATE_SEQ2_OPTIONAL(&Provider
),
6192 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6193 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6194 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
6198 static const struct prov_method_sequence node_from_hwnd4
[] = {
6199 { &Provider
, PROV_GET_PROPERTY_VALUE
},
6200 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6201 /* Win10v1507 and below call this. */
6202 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6203 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6204 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6205 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6206 /* Only called on Windows versions past Win10v1507. */
6207 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6208 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
6209 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
6213 static const struct prov_method_sequence node_from_hwnd5
[] = {
6214 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_LabeledByPropertyId */
6215 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6216 /* Win10v1507 and below call this. */
6217 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6218 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6219 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6220 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6221 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6222 /* Only done in Windows 8+. */
6223 { &Provider_child
, FRAG_GET_RUNTIME_ID
, METHOD_OPTIONAL
},
6224 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
6225 /* These two are only done on Windows 7. */
6226 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6227 { &Provider_child
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
6231 static const struct prov_method_sequence node_from_hwnd6
[] = {
6232 { &Provider
, PROV_GET_PROPERTY_VALUE
},
6233 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6234 /* Win10v1507 and below call this. */
6235 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6236 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6237 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6238 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6239 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6240 /* Next 4 are only done in Windows 8+. */
6241 { &Provider_child
, FRAG_GET_RUNTIME_ID
, METHOD_OPTIONAL
},
6242 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
6243 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
6244 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6245 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6246 /* Next two are only done on Win10v1809+. */
6247 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
6248 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
6249 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
6250 /* Next two are only done on Win10v1809+. */
6251 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
6252 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
6253 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
6257 static const struct prov_method_sequence node_from_hwnd7
[] = {
6258 { &Provider
, PROV_GET_PROPERTY_VALUE
},
6259 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6260 /* Win10v1507 and below call this. */
6261 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6262 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6263 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6264 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6265 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6266 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6267 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6268 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6269 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6270 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6271 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6272 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win11+ */
6273 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
6277 static const struct prov_method_sequence node_from_hwnd8
[] = {
6278 NODE_CREATE_SEQ2(&Provider
),
6279 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6280 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win11+ */
6281 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
6282 NODE_CREATE_SEQ2_OPTIONAL(&Provider
),
6283 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6284 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6285 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
6286 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
6290 static const struct prov_method_sequence node_from_hwnd9
[] = {
6291 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6292 /* Win10v1507 and below call this. */
6293 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6294 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6295 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6296 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6297 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6298 /* Only done in Windows 8+. */
6299 { &Provider
, FRAG_GET_RUNTIME_ID
, METHOD_OPTIONAL
},
6300 { &Provider
, FRAG_GET_FRAGMENT_ROOT
, METHOD_OPTIONAL
},
6301 /* These three are only done on Windows 7. */
6302 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
6303 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
6304 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_ProviderDescriptionPropertyId */
6308 static const struct prov_method_sequence node_from_hwnd10
[] = {
6309 NODE_CREATE_SEQ(&Provider
),
6310 /* Next two only done on Windows 8+. */
6311 { &Provider
, FRAG_GET_RUNTIME_ID
, METHOD_OPTIONAL
},
6312 { &Provider
, FRAG_GET_RUNTIME_ID
, METHOD_OPTIONAL
},
6313 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6314 { &Provider
, FRAG_GET_RUNTIME_ID
, METHOD_OPTIONAL
}, /* Only done on Win11+. */
6318 static const struct prov_method_sequence disconnect_prov1
[] = {
6319 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6320 /* Win10v1507 and below call this. */
6321 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6322 { &Provider_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6323 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6324 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6325 { &Provider_child
, PROV_GET_PROVIDER_OPTIONS
},
6326 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
6327 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
6328 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6329 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6333 static const struct prov_method_sequence disconnect_prov2
[] = {
6334 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6335 /* Win10v1507 and below call this. */
6336 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6337 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6338 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6339 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6340 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6341 { &Provider
, FRAG_GET_RUNTIME_ID
},
6342 { &Provider
, FRAG_GET_FRAGMENT_ROOT
},
6346 static const struct prov_method_sequence disconnect_prov3
[] = {
6347 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6348 /* Win10v1507 and below call this. */
6349 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6350 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6351 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
6352 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6353 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6354 { &Provider
, FRAG_GET_RUNTIME_ID
},
6358 static const struct prov_method_sequence disconnect_prov4
[] = {
6359 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6360 /* Win10v1507 and below call this. */
6361 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
6362 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
6363 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
6364 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
6368 static void test_UiaNodeFromHandle_client_proc(void)
6370 APTTYPEQUALIFIER apt_qualifier
;
6379 hwnd
= FindWindowA("UiaNodeFromHandle class", "Test window");
6381 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
6382 ok(hr
== CO_E_NOTINITIALIZED
, "Unexpected hr %#lx\n", hr
);
6384 hr
= UiaNodeFromHandle(hwnd
, &node
);
6385 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6387 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6388 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6390 memset(buf
, 0, sizeof(buf
));
6391 GetWindowThreadProcessId(hwnd
, &pid
);
6392 ok(get_nested_provider_desc(V_BSTR(&v
), L
"Main", FALSE
, buf
), "Failed to get nested provider description\n");
6393 check_node_provider_desc_prefix(buf
, pid
, hwnd
);
6394 check_node_provider_desc(buf
, L
"Main", L
"Provider", TRUE
);
6395 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6396 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6397 check_node_provider_desc_todo(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6401 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
6402 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6403 ok(V_VT(&v
) == VT_I4
, "V_VT(&v) = %d\n", V_VT(&v
));
6404 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
6407 * On Windows 8 and above, if a node contains a nested provider, the
6408 * process will be in an implicit MTA until the node is released.
6410 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
6411 ok(hr
== S_OK
|| broken(hr
== CO_E_NOTINITIALIZED
), "Unexpected hr %#lx\n", hr
);
6414 ok(apt_type
== APTTYPE_MTA
, "Unexpected apt_type %#x\n", apt_type
);
6415 ok(apt_qualifier
== APTTYPEQUALIFIER_IMPLICIT_MTA
, "Unexpected apt_qualifier %#x\n", apt_qualifier
);
6418 UiaNodeRelease(node
);
6420 /* Node released, we're out of the implicit MTA. */
6421 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
6423 /* Windows 10v1709-1809 are stuck in an implicit MTA. */
6424 ok(hr
== CO_E_NOTINITIALIZED
|| broken(hr
== S_OK
), "Unexpected hr %#lx\n", hr
);
6427 ok(apt_type
== APTTYPE_MTA
, "Unexpected apt_type %#x\n", apt_type
);
6428 ok(apt_qualifier
== APTTYPEQUALIFIER_IMPLICIT_MTA
, "Unexpected apt_qualifier %#x\n", apt_qualifier
);
6432 static DWORD WINAPI
uia_node_from_handle_test_thread(LPVOID param
)
6434 HUIANODE node
, node2
, node3
;
6435 HWND hwnd
= (HWND
)param
;
6440 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
6442 /* Only sent twice on Windows 11. */
6443 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
6444 /* Only sent on Win7. */
6445 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
6446 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
6447 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
6448 Provider
.hwnd
= hwnd
;
6449 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0;
6450 Provider
.frag_root
= NULL
;
6451 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
6452 Provider
.ignore_hwnd_prop
= TRUE
;
6453 hr
= UiaNodeFromHandle(hwnd
, &node
);
6454 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6455 ok(Provider
.ref
>= 2, "Unexpected refcnt %ld\n", Provider
.ref
);
6456 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6457 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
6459 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6460 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6462 memset(buf
, 0, sizeof(buf
));
6463 ok(get_nested_provider_desc(V_BSTR(&v
), L
"Main", FALSE
, buf
), "Failed to get nested provider description\n");
6464 check_node_provider_desc_prefix(buf
, GetCurrentProcessId(), hwnd
);
6465 check_node_provider_desc(buf
, L
"Main", L
"Provider", TRUE
);
6466 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6467 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6468 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6472 Provider
.ignore_hwnd_prop
= FALSE
;
6473 ok_method_sequence(node_from_hwnd3
, "node_from_hwnd3");
6475 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
6476 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6477 check_uia_prop_val(UIA_ControlTypePropertyId
, UIAutomationType_Int
, &v
, FALSE
);
6480 * On Windows, nested providers are always called on a separate thread if
6481 * UseComThreading isn't set. Since we're doing COM marshaling, if we're
6482 * currently in an MTA, we just call the nested provider from the current
6485 todo_wine
ok(Provider
.last_call_tid
!= GetCurrentThreadId() &&
6486 Provider
.last_call_tid
!= GetWindowThreadProcessId(hwnd
, NULL
), "Expected method call on separate thread\n");
6489 * Elements returned from nested providers have to be able to get a
6490 * RuntimeId, or else we'll get E_FAIL on Win8+.
6492 Provider_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
6493 Provider_child
.expected_tid
= Provider
.expected_tid
;
6494 Provider_child
.runtime_id
[0] = UiaAppendRuntimeId
;
6495 Provider_child
.runtime_id
[1] = 2;
6496 Provider_child
.frag_root
= NULL
;
6497 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
6498 ok(hr
== E_FAIL
|| broken(hr
== S_OK
), "Unexpected hr %#lx\n", hr
);
6501 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6502 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6503 UiaNodeRelease(node2
);
6506 ok_method_sequence(node_from_hwnd5
, "node_from_hwnd5");
6508 /* RuntimeId check succeeds, we'll get a nested node. */
6509 Provider_child
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
6510 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
6511 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6512 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6514 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6515 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6516 hr
= UiaGetPropertyValue(node2
, UIA_ProviderDescriptionPropertyId
, &v
);
6517 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6520 * Even though this is a nested node, without any additional
6521 * providers, it will not have the 'Nested' prefix.
6523 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
6524 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
6527 hr
= UiaGetPropertyValue(node2
, UIA_ControlTypePropertyId
, &v
);
6528 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6529 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
6530 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
6531 ok_method_sequence(node_from_hwnd6
, "node_from_hwnd6");
6533 UiaNodeRelease(node2
);
6536 * There is a delay between nested nodes being released and the
6537 * corresponding IRawElementProviderSimple release on newer Windows
6540 if (Provider_child
.ref
!= 1)
6542 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6545 * Returned nested elements with an HWND will have client-side providers
6548 Provider_child
.hwnd
= hwnd
;
6549 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6550 /* Only sent on Win7. */
6551 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
6552 Provider_child
.ignore_hwnd_prop
= TRUE
;
6553 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
6554 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6555 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6556 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
6557 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6559 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6560 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6561 hr
= UiaGetPropertyValue(node2
, UIA_ProviderDescriptionPropertyId
, &v
);
6562 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6564 memset(buf
, 0, sizeof(buf
));
6565 ok(get_nested_provider_desc(V_BSTR(&v
), L
"Main", TRUE
, buf
), "Failed to get nested provider description\n");
6567 check_node_provider_desc_prefix(buf
, GetCurrentProcessId(), hwnd
);
6568 check_node_provider_desc(buf
, L
"Main", L
"Provider_child", TRUE
);
6570 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6571 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6572 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", NULL
, FALSE
);
6575 Provider_child
.ignore_hwnd_prop
= FALSE
;
6576 ok_method_sequence(node_from_hwnd7
, "node_from_hwnd7");
6577 UiaNodeRelease(node2
);
6579 if (Provider_child
.ref
!= 1)
6581 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6583 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6584 /* Win10v1809 can be slow to call Release on Provider. */
6585 if (Provider
.ref
!= 1)
6587 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
6589 /* ProviderOptions_UseComThreading test from a separate thread. */
6590 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6591 /* Only sent on Win7. */
6592 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
6593 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
6594 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
| ProviderOptions_UseComThreading
, NULL
, FALSE
);
6595 Provider
.frag_root
= NULL
;
6596 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0xdeadbeef;
6597 hr
= UiaNodeFromHandle(hwnd
, &node
);
6598 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6599 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
6600 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6601 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
6603 ok_method_sequence(node_from_hwnd10
, "node_from_hwnd10");
6605 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6606 /* Win10v1809 can be slow to call Release on Provider. */
6607 if (Provider
.ref
!= 1)
6609 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
6611 if (!pUiaDisconnectProvider
)
6613 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
6618 * UiaDisconnectProvider tests.
6620 /* Only sent twice on Windows 11. */
6621 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
6622 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
6623 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
6624 Provider
.hwnd
= hwnd
;
6625 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0;
6626 Provider
.frag_root
= NULL
;
6627 Provider
.ignore_hwnd_prop
= TRUE
;
6628 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
6629 hr
= UiaNodeFromHandle(hwnd
, &node
);
6630 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6631 ok(Provider
.ref
>= 2, "Unexpected refcnt %ld\n", Provider
.ref
);
6632 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6634 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6635 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6637 memset(buf
, 0, sizeof(buf
));
6638 ok(get_nested_provider_desc(V_BSTR(&v
), L
"Main", FALSE
, buf
), "Failed to get nested provider description\n");
6639 check_node_provider_desc_prefix(buf
, GetCurrentProcessId(), hwnd
);
6640 check_node_provider_desc(buf
, L
"Main", L
"Provider", TRUE
);
6641 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6642 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6643 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6646 Provider
.ignore_hwnd_prop
= FALSE
;
6647 ok_method_sequence(node_from_hwnd3
, "node_from_hwnd3");
6649 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
6650 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6651 check_uia_prop_val(UIA_ControlTypePropertyId
, UIAutomationType_Int
, &v
, FALSE
);
6653 /* Nodes returned from a nested node will be tracked and disconnectable. */
6654 Provider_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
6655 Provider_child
.runtime_id
[0] = UiaAppendRuntimeId
;
6656 Provider_child
.runtime_id
[1] = 2;
6657 Provider_child
.hwnd
= NULL
;
6658 Provider_child
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
6659 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
6660 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6661 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6663 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6664 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6665 hr
= UiaGetPropertyValue(node2
, UIA_ProviderDescriptionPropertyId
, &v
);
6666 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6667 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
6668 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
6671 hr
= UiaGetPropertyValue(node2
, UIA_ControlTypePropertyId
, &v
);
6672 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6673 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
6674 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
6675 ok_method_sequence(node_from_hwnd6
, "node_from_hwnd6");
6677 /* Get a new node for the same provider. */
6678 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
6679 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6680 ok(Provider_child
.ref
== 3, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6682 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
6683 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6684 hr
= UiaGetPropertyValue(node3
, UIA_ProviderDescriptionPropertyId
, &v
);
6685 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6686 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
6687 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
6690 hr
= UiaGetPropertyValue(node3
, UIA_ControlTypePropertyId
, &v
);
6691 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6692 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
6693 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
6694 ok_method_sequence(node_from_hwnd6
, "node_from_hwnd6");
6697 * Both node2 and node3 represent Provider_child, one call to
6698 * UiaDisconnectProvider disconnects both.
6700 hr
= pUiaDisconnectProvider(&Provider_child
.IRawElementProviderSimple_iface
);
6701 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6702 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
6704 hr
= UiaGetPropertyValue(node2
, UIA_ControlTypePropertyId
, &v
);
6705 ok(hr
== UIA_E_ELEMENTNOTAVAILABLE
, "Unexpected hr %#lx\n", hr
);
6707 hr
= UiaGetPropertyValue(node3
, UIA_ControlTypePropertyId
, &v
);
6708 ok(hr
== UIA_E_ELEMENTNOTAVAILABLE
, "Unexpected hr %#lx\n", hr
);
6709 ok_method_sequence(disconnect_prov1
, "disconnect_prov1");
6711 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
6712 ok(UiaNodeRelease(node3
), "UiaNodeRelease returned FALSE\n");
6715 * Returns same failure code as UiaGetRuntimeId when we fail to get a
6716 * fragment root for AppendRuntimeId.
6718 Provider
.hwnd
= NULL
;
6719 Provider
.runtime_id
[0] = UiaAppendRuntimeId
;
6720 Provider
.runtime_id
[1] = 2;
6721 Provider
.frag_root
= NULL
;
6722 hr
= pUiaDisconnectProvider(&Provider
.IRawElementProviderSimple_iface
);
6723 ok(hr
== E_FAIL
, "Unexpected hr %#lx\n", hr
);
6724 ok_method_sequence(disconnect_prov2
, "disconnect_prov2");
6727 * Comparisons for disconnection are only based on RuntimeId comparisons,
6728 * not interface pointer values. If an interface returns a NULL RuntimeId,
6729 * no disconnection will occur.
6731 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0;
6732 hr
= pUiaDisconnectProvider(&Provider
.IRawElementProviderSimple_iface
);
6733 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx\n", hr
);
6734 ok_method_sequence(disconnect_prov3
, "disconnect_prov3");
6736 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
6737 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6738 check_uia_prop_val(UIA_ControlTypePropertyId
, UIAutomationType_Int
, &v
, FALSE
);
6740 /* Finally, disconnect node. */
6741 Provider
.hwnd
= hwnd
;
6742 hr
= pUiaDisconnectProvider(&Provider
.IRawElementProviderSimple_iface
);
6743 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6745 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
6746 ok(hr
== UIA_E_ELEMENTNOTAVAILABLE
, "Unexpected hr %#lx\n", hr
);
6747 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6748 ok_method_sequence(disconnect_prov4
, "disconnect_prov4");
6756 static void test_UiaNodeFromHandle(const char *name
)
6758 APTTYPEQUALIFIER apt_qualifier
;
6759 PROCESS_INFORMATION proc
;
6760 char cmdline
[MAX_PATH
];
6761 STARTUPINFOA startup
;
6762 HUIANODE node
, node2
;
6772 cls
.lpfnWndProc
= test_wnd_proc
;
6775 cls
.hInstance
= GetModuleHandleA(NULL
);
6778 cls
.hbrBackground
= NULL
;
6779 cls
.lpszMenuName
= NULL
;
6780 cls
.lpszClassName
= "UiaNodeFromHandle class";
6781 RegisterClassA(&cls
);
6783 hwnd
= CreateWindowA("UiaNodeFromHandle class", "Test window", WS_OVERLAPPEDWINDOW
,
6784 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
6786 hr
= UiaNodeFromHandle(hwnd
, NULL
);
6787 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6789 hr
= UiaNodeFromHandle(NULL
, &node
);
6790 ok(hr
== UIA_E_ELEMENTNOTAVAILABLE
, "Unexpected hr %#lx.\n", hr
);
6792 /* COM uninitialized, no provider returned by UiaReturnRawElementProvider. */
6794 node
= (void *)0xdeadbeef;
6795 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6796 /* Only sent twice on Win7. */
6797 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT
, 2);
6798 hr
= UiaNodeFromHandle(hwnd
, &node
);
6800 * On all versions of Windows prior to Windows 11, this would fail due to
6801 * COM being uninitialized, presumably because it tries to get an MSAA
6802 * proxy. Windows 11 now has the thread end up in an implicit MTA after
6803 * the call to UiaNodeFromHandle, which is probably why this now succeeds.
6804 * I don't know of anything that relies on this behavior, so for now we
6807 todo_wine
ok(hr
== S_OK
|| broken(hr
== E_FAIL
), "Unexpected hr %#lx.\n", hr
);
6808 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6809 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
6811 UiaNodeRelease(node
);
6814 * COM initialized, no provider returned by UiaReturnRawElementProvider.
6815 * In this case, we get a default MSAA proxy.
6817 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
6819 node
= (void *)0xdeadbeef;
6820 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6821 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT
, 2);
6822 hr
= UiaNodeFromHandle(hwnd
, &node
);
6823 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6824 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6825 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
6827 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6828 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6829 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6830 check_node_provider_desc_todo(V_BSTR(&v
), L
"Annotation", NULL
, FALSE
);
6831 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", NULL
, FALSE
);
6832 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6833 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6836 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6839 * COM initialized, but provider passed into UiaReturnRawElementProvider
6840 * returns a failure code on get_ProviderOptions. Same behavior as before.
6842 Provider
.prov_opts
= 0;
6843 Provider
.hwnd
= hwnd
;
6844 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
6845 node
= (void *)0xdeadbeef;
6846 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6847 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT
, 2);
6848 hr
= UiaNodeFromHandle(hwnd
, &node
);
6849 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6850 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6851 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
6853 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6854 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6855 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6856 check_node_provider_desc_todo(V_BSTR(&v
), L
"Annotation", NULL
, FALSE
);
6857 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", NULL
, FALSE
);
6858 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6859 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6862 ok_method_sequence(node_from_hwnd1
, "node_from_hwnd1");
6864 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6867 * COM initialized, but provider passed into UiaReturnRawElementProvider
6868 * on Win8+ will have its RuntimeId queried for UiaDisconnectProvider.
6869 * It will fail due to the lack of a valid fragment root, and we'll fall
6870 * back to an MSAA proxy. On Win7, RuntimeId isn't queried because the
6871 * disconnection functions weren't implemented yet.
6873 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
6874 Provider
.hwnd
= NULL
;
6875 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
6876 node
= (void *)0xdeadbeef;
6877 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6878 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT
, 2);
6879 Provider
.frag_root
= NULL
;
6880 Provider
.runtime_id
[0] = UiaAppendRuntimeId
;
6881 Provider
.runtime_id
[1] = 1;
6882 hr
= UiaNodeFromHandle(hwnd
, &node
);
6883 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6884 ok(Provider
.ref
== 1 || broken(Provider
.ref
== 2), "Unexpected refcnt %ld\n", Provider
.ref
);
6885 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6886 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
6888 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6889 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6891 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6892 if (Provider
.ref
== 1 || get_provider_desc(V_BSTR(&v
), L
"Annotation:", NULL
))
6894 check_node_provider_desc_todo(V_BSTR(&v
), L
"Annotation", NULL
, FALSE
);
6895 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", NULL
, FALSE
);
6898 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
6900 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6901 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6904 ok_method_sequence(node_from_hwnd9
, "node_from_hwnd9");
6905 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6907 * Bug on Windows 8 through Win10v1709 - if we have a RuntimeId failure,
6908 * refcount doesn't get decremented.
6910 ok(Provider
.ref
== 1 || broken(Provider
.ref
== 2), "Unexpected refcnt %ld\n", Provider
.ref
);
6911 if (Provider
.ref
== 2)
6912 IRawElementProviderSimple_Release(&Provider
.IRawElementProviderSimple_iface
);
6917 * COM uninitialized, return a Provider from UiaReturnRawElementProvider
6918 * with ProviderOptions_ServerSideProvider.
6920 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
6921 Provider
.hwnd
= hwnd
;
6922 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
6923 node
= (void *)0xdeadbeef;
6924 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
6925 /* Only sent on Win7. */
6926 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
6927 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
6928 hr
= UiaNodeFromHandle(hwnd
, &node
);
6929 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
6930 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
6931 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
6932 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
6934 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
6935 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6936 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
6937 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
6938 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
6939 check_node_provider_desc_todo(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
6942 ok_method_sequence(node_from_hwnd2
, "node_from_hwnd2");
6944 /* For same-thread HWND nodes, no disconnection will occur. */
6945 if (pUiaDisconnectProvider
)
6947 hr
= pUiaDisconnectProvider(&Provider
.IRawElementProviderSimple_iface
);
6948 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6950 ok_method_sequence(disconnect_prov4
, "disconnect_prov4");
6954 * This is relevant too: Since we don't get a 'nested' node, all calls
6955 * will occur on the current thread.
6957 Provider
.expected_tid
= GetCurrentThreadId();
6958 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
6959 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6960 check_uia_prop_val(UIA_ControlTypePropertyId
, UIAutomationType_Int
, &v
, FALSE
);
6962 /* UIAutomationType_Element properties will return a normal node. */
6963 Provider_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
6964 Provider_child
.hwnd
= NULL
;
6965 hr
= UiaGetPropertyValue(node
, UIA_LabeledByPropertyId
, &v
);
6966 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6968 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
6969 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6970 hr
= UiaGetPropertyValue(node2
, UIA_ProviderDescriptionPropertyId
, &v
);
6971 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6972 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
6973 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
6976 Provider_child
.expected_tid
= GetCurrentThreadId();
6977 hr
= UiaGetPropertyValue(node2
, UIA_ControlTypePropertyId
, &v
);
6978 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
6979 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
6980 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
6981 ok_method_sequence(node_from_hwnd4
, "node_from_hwnd4");
6983 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
6985 Provider
.expected_tid
= Provider_child
.expected_tid
= 0;
6986 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
6989 * On Windows 8 and above, after the first successful call to
6990 * UiaReturnRawElementProvider the process ends up in an implicit MTA
6991 * until the process exits.
6993 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
6994 /* Wine's provider thread doesn't always terminate immediately. */
6995 if (hr
== S_OK
&& !strcmp(winetest_platform
, "wine"))
6998 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
7000 todo_wine
ok(hr
== S_OK
|| broken(hr
== CO_E_NOTINITIALIZED
), "Unexpected hr %#lx\n", hr
);
7003 ok(apt_type
== APTTYPE_MTA
, "Unexpected apt_type %#x\n", apt_type
);
7004 ok(apt_qualifier
== APTTYPEQUALIFIER_IMPLICIT_MTA
, "Unexpected apt_qualifier %#x\n", apt_qualifier
);
7007 CoInitializeEx(NULL
, COINIT_APARTMENTTHREADED
);
7008 thread
= CreateThread(NULL
, 0, uia_node_from_handle_test_thread
, (void *)hwnd
, 0, NULL
);
7009 while (MsgWaitForMultipleObjects(1, &thread
, FALSE
, INFINITE
, QS_ALLINPUT
) != WAIT_OBJECT_0
)
7012 while(PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
7014 TranslateMessage(&msg
);
7015 DispatchMessageW(&msg
);
7018 CloseHandle(thread
);
7020 /* Test behavior from separate process. */
7021 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
7022 Provider
.hwnd
= hwnd
;
7023 Provider
.ignore_hwnd_prop
= TRUE
;
7024 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
7025 sprintf(cmdline
, "\"%s\" uiautomation UiaNodeFromHandle_client_proc", name
);
7026 memset(&startup
, 0, sizeof(startup
));
7027 startup
.cb
= sizeof(startup
);
7028 /* Only called twice on Windows 11. */
7029 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
7030 /* Only sent on Win7. */
7031 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
7032 CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &proc
);
7033 while (MsgWaitForMultipleObjects(1, &proc
.hProcess
, FALSE
, INFINITE
, QS_ALLINPUT
) != WAIT_OBJECT_0
)
7036 while(PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
7038 TranslateMessage(&msg
);
7039 DispatchMessageW(&msg
);
7043 GetExitCodeProcess(proc
.hProcess
, &exit_code
);
7044 if (exit_code
> 255)
7045 ok(0, "unhandled exception %08x in child process %04x\n", (UINT
)exit_code
, (UINT
)GetProcessId(proc
.hProcess
));
7047 ok(0, "%u failures in child process\n", (UINT
)exit_code
);
7049 CloseHandle(proc
.hProcess
);
7050 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7051 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
7052 Provider
.ignore_hwnd_prop
= FALSE
;
7053 ok_method_sequence(node_from_hwnd8
, "node_from_hwnd8");
7057 DestroyWindow(hwnd
);
7058 UnregisterClassA("UiaNodeFromHandle class", NULL
);
7062 static const struct prov_method_sequence reg_prov_cb1
[] = {
7063 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7064 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win10+. */
7065 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7069 static const struct prov_method_sequence reg_prov_cb2
[] = {
7070 /* These two are only done on Win10v1809+. */
7071 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7072 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7073 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7074 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win10+. */
7075 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7079 static const struct prov_method_sequence reg_prov_cb3
[] = {
7080 { &Provider_proxy2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_TODO
},
7081 /* These two are only done on Win10v1809+. */
7082 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7083 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7084 { &Provider_proxy
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7085 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7086 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7087 /* These three only done on Win10+. */
7088 { &Provider_proxy
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7089 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7090 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7091 { &Provider_proxy
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7092 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7093 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7097 static const struct prov_method_sequence reg_prov_cb4
[] = {
7098 { &Provider_proxy2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_TODO
},
7099 /* These two are only done on Win10v1809+. */
7100 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7101 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7102 { &Provider_override
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
7103 { &Provider_proxy
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7104 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7105 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7106 /* These four only done on Win10+. */
7107 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7108 { &Provider_proxy
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7109 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7110 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7111 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ProviderDescriptionPropertyId */
7112 { &Provider_proxy
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7113 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7114 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7118 static const struct prov_method_sequence reg_prov_cb5
[] = {
7119 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
7123 static const struct prov_method_sequence reg_prov_cb6
[] = {
7124 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
7125 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7126 { &Provider_proxy
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7130 static const struct prov_method_sequence reg_prov_cb7
[] = {
7131 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
7132 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7133 { &Provider_proxy
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7134 { &Provider_proxy
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7135 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7139 static const struct prov_method_sequence reg_prov_cb8
[] = {
7140 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
7141 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7142 { &Provider_proxy
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7143 { &Provider_proxy
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7144 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7145 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7146 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7150 static const struct prov_method_sequence reg_prov_cb9
[] = {
7151 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
7152 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7153 { &Provider_proxy
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7154 { &Provider_proxy
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7155 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7156 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7157 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
7158 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win7. */
7162 static const struct prov_method_sequence reg_prov_cb10
[] = {
7163 { &Provider_proxy2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_TODO
},
7164 /* These two are only done on Win10v1809+. */
7165 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7166 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7167 { &Provider_override
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
7168 { &Provider_proxy
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7169 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7170 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7171 /* These four only done on Win10+. */
7172 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7173 { &Provider_proxy
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7174 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7175 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7179 static const struct prov_method_sequence reg_prov_cb11
[] = {
7180 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7181 /* Win10v1507 and below call this. */
7182 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7183 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
7184 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7185 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7186 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7187 { &Provider_proxy2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_TODO
},
7188 /* These two are only done on Win10v1809+. */
7189 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7190 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7191 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7192 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7193 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7194 /* These three only done on Win10+. */
7195 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7196 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7197 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7198 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7199 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7200 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7204 static const struct prov_method_sequence reg_prov_cb12
[] = {
7205 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7206 /* Win10v1507 and below call this. */
7207 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7208 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
7209 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7210 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7211 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7212 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
7213 /* Win10v1507 and below call this. */
7214 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7215 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_TODO
},
7216 { &Provider2
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
7217 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
7218 { &Provider2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_OPTIONAL
}, /* Only done on Win10v1809+ */
7219 { &Provider_proxy2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_TODO
},
7220 /* These two are only done on Win10v1809+. */
7221 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7222 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7223 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7224 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7225 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7226 /* These three only done on Win10+. */
7227 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7228 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7229 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7230 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7231 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7232 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7236 static const struct prov_method_sequence reg_prov_cb13
[] = {
7237 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7238 /* Win10v1507 and below call this. */
7239 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7240 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
7241 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7242 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7243 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
7244 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
7245 /* Win10v1507 and below call this. */
7246 { &Provider2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7247 { &Provider2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_TODO
},
7248 { &Provider2
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
7249 { &Provider2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
7250 { &Provider2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_OPTIONAL
}, /* Only done on Win10v1809+ */
7251 /* Provider override only retrieved successfully on Win10v1809+ */
7252 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7253 { &Provider_override
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7254 { &Provider_override
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
7255 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7256 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7257 { &Provider_proxy2
, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
, METHOD_OPTIONAL
}, /* Only done on Win10v1507 and below. */
7258 /* These two are only done on Win10v1809+. */
7259 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
7260 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
7261 /* Only done on Win10v1809+. */
7262 { &Provider_override
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
7263 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7264 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7265 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7266 { &Provider_override
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Win10v1809+ */
7267 /* These three only done on Win10+. */
7268 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7269 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7270 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
7271 /* Only done on Win10v1809+. */
7272 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_ProviderDescriptionPropertyId */
7273 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7274 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7275 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
7279 static IRawElementProviderSimple
*base_hwnd_prov
, *proxy_prov
, *parent_proxy_prov
, *nc_prov
;
7280 static SAFEARRAY WINAPI
*test_uia_provider_callback(HWND hwnd
, enum ProviderType prov_type
)
7282 IRawElementProviderSimple
*elprov
= NULL
;
7286 case ProviderType_BaseHwnd
:
7287 CHECK_EXPECT(prov_callback_base_hwnd
);
7288 if (hwnd
== Provider_hwnd3
.hwnd
)
7289 elprov
= &Provider_hwnd3
.IRawElementProviderSimple_iface
;
7290 else if (hwnd
== Provider_hwnd2
.hwnd
)
7291 elprov
= &Provider_hwnd2
.IRawElementProviderSimple_iface
;
7293 elprov
= base_hwnd_prov
;
7296 case ProviderType_Proxy
:
7297 if (Provider_proxy
.hwnd
== hwnd
)
7299 CHECK_EXPECT(prov_callback_proxy
);
7300 elprov
= proxy_prov
;
7302 else if (hwnd
== GetParent(Provider_proxy
.hwnd
))
7304 CHECK_EXPECT(prov_callback_parent_proxy
);
7305 elprov
= parent_proxy_prov
;
7309 case ProviderType_NonClientArea
:
7310 CHECK_EXPECT(prov_callback_nonclient
);
7311 if (hwnd
== Provider_nc3
.hwnd
)
7312 elprov
= &Provider_nc3
.IRawElementProviderSimple_iface
;
7313 else if (hwnd
== Provider_nc2
.hwnd
)
7314 elprov
= &Provider_nc2
.IRawElementProviderSimple_iface
;
7328 sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, 1);
7330 SafeArrayPutElement(sa
, &idx
, (void *)elprov
);
7338 static void test_UiaRegisterProviderCallback(void)
7347 cls
.lpfnWndProc
= test_wnd_proc
;
7350 cls
.hInstance
= GetModuleHandleA(NULL
);
7353 cls
.hbrBackground
= NULL
;
7354 cls
.lpszMenuName
= NULL
;
7355 cls
.lpszClassName
= "UiaRegisterProviderCallback class";
7357 RegisterClassA(&cls
);
7359 cls
.lpfnWndProc
= child_test_wnd_proc
;
7360 cls
.lpszClassName
= "UiaRegisterProviderCallback child class";
7361 RegisterClassA(&cls
);
7363 hwnd
= CreateWindowA("UiaRegisterProviderCallback class", "Test window", WS_OVERLAPPEDWINDOW
,
7364 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
7366 hwnd2
= CreateWindowA("UiaRegisterProviderCallback child class", "Test child window", WS_CHILD
,
7367 0, 0, 100, 100, hwnd
, NULL
, NULL
, NULL
);
7369 UiaRegisterProviderCallback(test_uia_provider_callback
);
7371 /* No providers returned by UiaRootObjectId or the provider callback. */
7372 Provider_proxy
.hwnd
= hwnd2
;
7373 child_win_prov_root
= prov_root
= NULL
;
7374 node
= (void *)0xdeadbeef;
7375 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7376 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7377 SET_EXPECT(prov_callback_base_hwnd
);
7378 SET_EXPECT(prov_callback_nonclient
);
7379 SET_EXPECT(prov_callback_proxy
);
7380 SET_EXPECT(prov_callback_parent_proxy
);
7381 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7382 /* Windows 7 returns S_OK with a NULL HUIANODE. */
7383 ok(hr
== E_FAIL
|| broken(hr
== S_OK
), "Unexpected hr %#lx.\n", hr
);
7384 ok(!node
, "node != NULL\n");
7385 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7386 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7387 CHECK_CALLED(prov_callback_base_hwnd
);
7388 CHECK_CALLED(prov_callback_nonclient
);
7389 CHECK_CALLED(prov_callback_proxy
);
7390 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7392 /* Return only nonclient proxy provider. */
7393 base_hwnd_prov
= proxy_prov
= parent_proxy_prov
= NULL
;
7394 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
7395 child_win_prov_root
= prov_root
= NULL
;
7396 node
= (void *)0xdeadbeef;
7397 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7398 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7399 SET_EXPECT(prov_callback_base_hwnd
);
7400 SET_EXPECT(prov_callback_nonclient
);
7401 SET_EXPECT(prov_callback_proxy
);
7402 SET_EXPECT(prov_callback_parent_proxy
);
7403 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7404 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7405 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
7406 ok(!!node
, "node == NULL\n");
7407 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7408 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7409 CHECK_CALLED(prov_callback_base_hwnd
);
7410 CHECK_CALLED(prov_callback_nonclient
);
7411 CHECK_CALLED(prov_callback_proxy
);
7412 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7414 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7415 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7416 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7417 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", TRUE
);
7420 ok_method_sequence(reg_prov_cb1
, "reg_prov_cb1");
7422 UiaNodeRelease(node
);
7423 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
7425 /* Return only base_hwnd provider. */
7426 nc_prov
= proxy_prov
= parent_proxy_prov
= NULL
;
7427 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
7428 child_win_prov_root
= prov_root
= NULL
;
7429 node
= (void *)0xdeadbeef;
7430 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7431 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7432 SET_EXPECT(prov_callback_base_hwnd
);
7433 SET_EXPECT(prov_callback_nonclient
);
7434 SET_EXPECT(prov_callback_proxy
);
7435 SET_EXPECT(prov_callback_parent_proxy
);
7436 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7437 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7438 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
7439 ok(!!node
, "node == NULL\n");
7440 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7441 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7442 CHECK_CALLED(prov_callback_base_hwnd
);
7443 CHECK_CALLED(prov_callback_nonclient
);
7444 CHECK_CALLED(prov_callback_proxy
);
7445 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7447 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7448 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7449 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7450 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", TRUE
);
7453 ok_method_sequence(reg_prov_cb2
, "reg_prov_cb2");
7455 UiaNodeRelease(node
);
7456 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
7458 /* Return providers for all ProviderTypes. */
7459 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
7460 proxy_prov
= &Provider_proxy
.IRawElementProviderSimple_iface
;
7461 parent_proxy_prov
= &Provider_proxy2
.IRawElementProviderSimple_iface
;
7462 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
7463 Provider_proxy
.hwnd
= hwnd2
;
7464 child_win_prov_root
= prov_root
= NULL
;
7465 node
= (void *)0xdeadbeef;
7466 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7467 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7468 SET_EXPECT(prov_callback_base_hwnd
);
7469 SET_EXPECT(prov_callback_nonclient
);
7470 SET_EXPECT(prov_callback_proxy
);
7471 SET_EXPECT(prov_callback_parent_proxy
);
7472 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7473 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7474 ok(!!node
, "node == NULL\n");
7475 ok(Provider_proxy
.ref
== 2, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
7476 ok(Provider_proxy2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_proxy2
.ref
);
7477 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
7478 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
7479 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7480 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7481 CHECK_CALLED(prov_callback_base_hwnd
);
7482 CHECK_CALLED(prov_callback_nonclient
);
7483 CHECK_CALLED(prov_callback_proxy
);
7484 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7486 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7487 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7488 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7489 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_proxy", TRUE
);
7490 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
7491 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
7494 ok_method_sequence(reg_prov_cb3
, "reg_prov_cb3");
7496 UiaNodeRelease(node
);
7497 ok(Provider_proxy
.ref
== 1, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
7498 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
7499 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
7501 /* Return an override provider from Provider_proxy2. */
7502 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
7503 proxy_prov
= &Provider_proxy
.IRawElementProviderSimple_iface
;
7504 parent_proxy_prov
= &Provider_proxy2
.IRawElementProviderSimple_iface
;
7505 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
7506 Provider_proxy2
.override_hwnd
= hwnd2
;
7507 child_win_prov_root
= prov_root
= NULL
;
7508 node
= (void *)0xdeadbeef;
7509 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7510 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7511 SET_EXPECT(prov_callback_base_hwnd
);
7512 SET_EXPECT(prov_callback_nonclient
);
7513 SET_EXPECT(prov_callback_proxy
);
7514 SET_EXPECT(prov_callback_parent_proxy
);
7515 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7516 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7517 ok(!!node
, "node == NULL\n");
7518 ok(Provider_proxy
.ref
== 2, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
7519 ok(Provider_proxy2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_proxy2
.ref
);
7520 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
7521 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
7522 todo_wine
ok(Provider_override
.ref
== 2, "Unexpected refcnt %ld\n", Provider_override
.ref
);
7523 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7524 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7525 CHECK_CALLED(prov_callback_base_hwnd
);
7526 CHECK_CALLED(prov_callback_nonclient
);
7527 CHECK_CALLED(prov_callback_proxy
);
7528 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7530 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7531 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7532 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7533 check_node_provider_desc_todo(V_BSTR(&v
), L
"Override", L
"Provider_override", TRUE
);
7534 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider_proxy", FALSE
);
7535 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
7536 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
7539 ok_method_sequence(reg_prov_cb4
, "reg_prov_cb4");
7542 * Test the order that Providers are queried for properties. The order is:
7543 * Override provider.
7545 * Nonclient provider.
7548 * UI Automation tries to get a property from each in this order until one
7549 * returns a value. If none do, the property isn't supported.
7551 if (Provider_override
.ref
== 2)
7553 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
7554 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7555 ok(V_VT(&v
) == VT_I4
, "Unexpected vt %d\n", V_VT(&v
));
7556 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
7557 ok_method_sequence(reg_prov_cb5
, "reg_prov_cb5");
7560 /* Property retrieved from Provider_proxy (Main) */
7561 Provider_override
.ret_invalid_prop_type
= TRUE
;
7562 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
7563 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7564 ok(V_VT(&v
) == VT_I4
, "Unexpected vt %d\n", V_VT(&v
));
7565 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
7566 ok_method_sequence(reg_prov_cb6
, "reg_prov_cb6");
7568 /* Property retrieved from Provider_nc (Nonclient) */
7569 Provider_override
.ret_invalid_prop_type
= Provider_proxy
.ret_invalid_prop_type
= TRUE
;
7570 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
7571 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7572 ok(V_VT(&v
) == VT_I4
, "Unexpected vt %d\n", V_VT(&v
));
7573 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
7574 ok_method_sequence(reg_prov_cb7
, "reg_prov_cb7");
7576 /* Property retrieved from Provider_hwnd (Hwnd) */
7577 Provider_override
.ret_invalid_prop_type
= Provider_proxy
.ret_invalid_prop_type
= TRUE
;
7578 Provider_nc
.ret_invalid_prop_type
= TRUE
;
7579 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
7580 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7581 ok(V_VT(&v
) == VT_I4
, "Unexpected vt %d\n", V_VT(&v
));
7582 ok(V_I4(&v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(&v
));
7583 ok_method_sequence(reg_prov_cb8
, "reg_prov_cb8");
7585 /* Property retrieved from none of the providers. */
7586 Provider_override
.ret_invalid_prop_type
= Provider_proxy
.ret_invalid_prop_type
= TRUE
;
7587 Provider_nc
.ret_invalid_prop_type
= Provider_hwnd
.ret_invalid_prop_type
= TRUE
;
7588 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
7589 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7590 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
7591 ok_method_sequence(reg_prov_cb9
, "reg_prov_cb9");
7593 UiaNodeRelease(node
);
7594 ok(Provider_proxy
.ref
== 1, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
7595 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
7596 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
7597 ok(Provider_override
.ref
== 1, "Unexpected refcnt %ld\n", Provider_override
.ref
);
7598 Provider_override
.ret_invalid_prop_type
= Provider_proxy
.ret_invalid_prop_type
= FALSE
;
7599 Provider_nc
.ret_invalid_prop_type
= Provider_hwnd
.ret_invalid_prop_type
= FALSE
;
7602 * Provider_hwnd has ProviderOptions_UseComThreading, and COM hasn't been
7603 * initialized. One provider failing will cause the entire node to fail
7604 * creation on Win10+.
7606 Provider_hwnd
.prov_opts
= ProviderOptions_ClientSideProvider
| ProviderOptions_UseComThreading
;
7607 node
= (void *)0xdeadbeef;
7608 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7609 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7610 SET_EXPECT(prov_callback_base_hwnd
);
7611 SET_EXPECT(prov_callback_nonclient
);
7612 SET_EXPECT(prov_callback_proxy
);
7613 SET_EXPECT(prov_callback_parent_proxy
);
7614 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7615 ok(hr
== CO_E_NOTINITIALIZED
|| broken(hr
== S_OK
), "Unexpected hr %#lx.\n", hr
);
7616 ok(!node
|| broken(!!node
), "node != NULL\n");
7617 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7618 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7619 CHECK_CALLED(prov_callback_base_hwnd
);
7620 CHECK_CALLED(prov_callback_nonclient
);
7621 CHECK_CALLED(prov_callback_proxy
);
7622 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7623 ok_method_sequence(reg_prov_cb10
, "reg_prov_cb10");
7624 UiaNodeRelease(node
);
7625 Provider_hwnd
.prov_opts
= ProviderOptions_ClientSideProvider
;
7628 * Provider returned by UiaRootObjectId on hwnd2. No ProviderType_Proxy
7629 * callback for hwnd2.
7631 Provider
.hwnd
= hwnd2
;
7632 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
7633 child_win_prov_root
= &Provider
.IRawElementProviderSimple_iface
;
7634 Provider_proxy2
.override_hwnd
= NULL
;
7635 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7636 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7637 SET_EXPECT(prov_callback_base_hwnd
);
7638 SET_EXPECT(prov_callback_nonclient
);
7639 SET_EXPECT(prov_callback_parent_proxy
);
7640 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7641 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7642 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
7643 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7644 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7645 CHECK_CALLED(prov_callback_base_hwnd
);
7646 CHECK_CALLED(prov_callback_nonclient
);
7647 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7649 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7650 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7651 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7652 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
7653 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
7654 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
7657 ok_method_sequence(reg_prov_cb11
, "reg_prov_cb11");
7659 UiaNodeRelease(node
);
7662 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
7663 * doesn't give an HWND override provider, UIA will attempt to get a proxy
7664 * provider to check it for an HWND override provider.
7666 Provider
.hwnd
= hwnd2
;
7667 Provider2
.hwnd
= hwnd
;
7668 Provider
.prov_opts
= Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
7669 child_win_prov_root
= &Provider
.IRawElementProviderSimple_iface
;
7670 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
7671 Provider_proxy2
.override_hwnd
= NULL
;
7672 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7673 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7674 SET_EXPECT(prov_callback_base_hwnd
);
7675 SET_EXPECT(prov_callback_nonclient
);
7676 SET_EXPECT(prov_callback_parent_proxy
);
7677 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7678 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7679 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
7680 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7681 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7682 CHECK_CALLED(prov_callback_base_hwnd
);
7683 CHECK_CALLED(prov_callback_nonclient
);
7684 todo_wine
CHECK_CALLED(prov_callback_parent_proxy
);
7686 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7687 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7688 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7689 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
7690 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
7691 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
7694 ok_method_sequence(reg_prov_cb12
, "reg_prov_cb12");
7696 UiaNodeRelease(node
);
7699 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
7700 * returns an HWND override, no ProviderType_Proxy callback for hwnd.
7702 Provider
.hwnd
= hwnd2
;
7703 Provider2
.hwnd
= hwnd
;
7704 Provider2
.override_hwnd
= Provider_override
.hwnd
= hwnd2
;
7705 Provider2
.ignore_hwnd_prop
= Provider_override
.ignore_hwnd_prop
= TRUE
;
7706 Provider
.prov_opts
= Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
7707 child_win_prov_root
= &Provider
.IRawElementProviderSimple_iface
;
7708 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
7709 Provider_proxy2
.override_hwnd
= NULL
;
7710 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
7711 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
7712 SET_EXPECT(prov_callback_base_hwnd
);
7713 SET_EXPECT(prov_callback_nonclient
);
7714 SET_EXPECT(prov_callback_parent_proxy
);
7715 hr
= UiaNodeFromHandle(hwnd2
, &node
);
7716 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7717 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
7718 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
7719 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
7720 CHECK_CALLED(prov_callback_base_hwnd
);
7721 CHECK_CALLED(prov_callback_nonclient
);
7723 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7724 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7725 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
7726 check_node_provider_desc_todo(V_BSTR(&v
), L
"Override", L
"Provider_override", TRUE
);
7727 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
7728 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
7729 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
7732 ok_method_sequence(reg_prov_cb13
, "reg_prov_cb13");
7734 UiaNodeRelease(node
);
7736 Provider2
.ignore_hwnd_prop
= Provider_override
.ignore_hwnd_prop
= FALSE
;
7737 UiaRegisterProviderCallback(NULL
);
7739 DestroyWindow(hwnd
);
7740 UnregisterClassA("UiaRegisterProviderCallback class", NULL
);
7741 UnregisterClassA("UiaRegisterProviderCallback child class", NULL
);
7744 static void set_cache_request(struct UiaCacheRequest
*req
, struct UiaCondition
*view_cond
, int scope
,
7745 PROPERTYID
*prop_ids
, int prop_ids_count
, PATTERNID
*pattern_ids
, int pattern_ids_count
, int elem_mode
)
7747 req
->pViewCondition
= view_cond
;
7750 req
->pProperties
= prop_ids
;
7751 req
->cProperties
= prop_ids_count
;
7752 req
->pPatterns
= pattern_ids
;
7753 req
->cPatterns
= pattern_ids_count
;
7755 req
->automationElementMode
= elem_mode
;
7758 static void set_property_condition(struct UiaPropertyCondition
*cond
, int prop_id
, VARIANT
*val
, int flags
)
7760 cond
->ConditionType
= ConditionType_Property
;
7761 cond
->PropertyId
= prop_id
;
7763 cond
->Flags
= flags
;
7766 static void set_and_or_condition(struct UiaAndOrCondition
*cond
, int cond_type
,
7767 struct UiaCondition
**conds
, int cond_count
)
7769 cond
->ConditionType
= cond_type
;
7770 cond
->ppConditions
= conds
;
7771 cond
->cConditions
= cond_count
;
7774 static void set_not_condition(struct UiaNotCondition
*cond
, struct UiaCondition
*not_cond
)
7776 cond
->ConditionType
= ConditionType_Not
;
7777 cond
->pConditions
= not_cond
;
7780 #define MAX_NODE_PROVIDERS 4
7781 struct node_provider_desc
{
7785 const WCHAR
*prov_type
[MAX_NODE_PROVIDERS
];
7786 const WCHAR
*prov_name
[MAX_NODE_PROVIDERS
];
7787 BOOL parent_link
[MAX_NODE_PROVIDERS
];
7791 static void init_node_provider_desc(struct node_provider_desc
*desc
, DWORD pid
, HWND hwnd
)
7793 memset(desc
, 0, sizeof(*desc
));
7798 static void add_provider_desc(struct node_provider_desc
*desc
, const WCHAR
*prov_type
, const WCHAR
*prov_name
,
7801 desc
->prov_type
[desc
->prov_count
] = prov_type
;
7802 desc
->prov_name
[desc
->prov_count
] = prov_name
;
7803 desc
->parent_link
[desc
->prov_count
] = parent_link
;
7807 #define test_node_provider_desc( desc, desc_str ) \
7808 test_node_provider_desc_( (desc), (desc_str), __FILE__, __LINE__)
7809 static void test_node_provider_desc_(struct node_provider_desc
*desc
, BSTR desc_str
, const char *file
, int line
)
7813 check_node_provider_desc_prefix_(desc_str
, desc
->pid
, desc
->hwnd
, file
, line
);
7814 for (i
= 0; i
< desc
->prov_count
; i
++)
7815 check_node_provider_desc_(desc_str
, desc
->prov_type
[i
], desc
->prov_name
[i
], desc
->parent_link
[i
], FALSE
, file
, line
);
7819 * Cache requests are returned as a two dimensional safearray, with the first
7820 * dimension being the element index, and the second index being the
7821 * node/property/pattern value index for the element. The first element value is
7822 * always an HUIANODE, followed by requested property values, and finally
7823 * requested pattern handles.
7825 #define test_cache_req_sa( sa, exp_lbound, exp_elems, exp_node_desc ) \
7826 test_cache_req_sa_( (sa), (exp_lbound), (exp_elems), (exp_node_desc), __FILE__, __LINE__)
7827 static void test_cache_req_sa_(SAFEARRAY
*sa
, LONG exp_lbound
[2], LONG exp_elems
[2],
7828 struct node_provider_desc
*exp_node_desc
, const char *file
, int line
)
7837 hr
= SafeArrayGetVartype(sa
, &vt
);
7838 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7839 ok_(file
, line
)(vt
== VT_VARIANT
, "Unexpected vt %d\n", vt
);
7841 dims
= SafeArrayGetDim(sa
);
7842 ok_(file
, line
)(dims
== 2, "Unexpected dims %d\n", dims
);
7844 for (i
= 0; i
< 2; i
++)
7846 LONG lbound
, ubound
, elems
;
7848 lbound
= ubound
= elems
= 0;
7849 hr
= SafeArrayGetLBound(sa
, 1 + i
, &lbound
);
7850 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr
);
7851 ok_(file
, line
)(exp_lbound
[i
] == lbound
, "Unexpected lbound[%d] %ld\n", i
, lbound
);
7853 hr
= SafeArrayGetUBound(sa
, 1 + i
, &ubound
);
7854 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr
);
7856 elems
= (ubound
- lbound
) + 1;
7857 ok_(file
, line
)(exp_elems
[i
] == elems
, "Unexpected elems[%d] %ld\n", i
, elems
);
7860 for (i
= 0; i
< exp_elems
[0]; i
++)
7862 LONG idx
[2] = { (exp_lbound
[0] + i
), exp_lbound
[1] };
7864 hr
= SafeArrayGetElement(sa
, idx
, &v
);
7865 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7867 hr
= UiaHUiaNodeFromVariant(&v
, &node
);
7868 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7871 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
7872 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
7873 test_node_provider_desc_(&exp_node_desc
[i
], V_BSTR(&v
), file
, line
);
7876 UiaNodeRelease(node
);
7880 static const struct prov_method_sequence cache_req_seq1
[] = {
7881 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7886 * Win10v1507 and below will attempt to do parent navigation if the
7887 * conditional check fails.
7889 static const struct prov_method_sequence cache_req_seq2
[] = {
7890 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
7894 static const struct prov_method_sequence cache_req_seq3
[] = {
7895 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
7896 NODE_CREATE_SEQ(&Provider_child
),
7897 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
7898 NODE_CREATE_SEQ(&Provider_child2
),
7899 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
7900 /* Navigates towards parent to check for clientside provider siblings. */
7901 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7902 NODE_CREATE_SEQ(&Provider
),
7903 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7904 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7908 static const struct prov_method_sequence cache_req_seq4
[] = {
7909 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* Dependent upon property condition. */
7910 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7914 /* Sequence for non-matching property condition. */
7915 static const struct prov_method_sequence cache_req_seq5
[] = {
7916 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* Dependent upon property condition. */
7917 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* Dependent upon property condition. */
7918 /* Only done on Win10v1507 and below. */
7919 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
7923 static const struct prov_method_sequence cache_req_seq6
[] = {
7924 { &Provider
, FRAG_GET_RUNTIME_ID
},
7925 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7926 /* Only done on Win10v1507 and below. */
7927 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
7931 static const struct prov_method_sequence cache_req_seq7
[] = {
7932 { &Provider
, FRAG_GET_RUNTIME_ID
},
7933 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId. */
7934 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7938 static const struct prov_method_sequence cache_req_seq8
[] = {
7939 NODE_CREATE_SEQ(&Provider_child
),
7943 static const struct prov_method_sequence cache_req_seq9
[] = {
7944 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
7945 /* Done twice on Windows, but we shouldn't need to replicate this. */
7946 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_IsControlElementPropertyId */
7947 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7948 NODE_CREATE_SEQ(&Provider
),
7949 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
7950 /* Only done on Win10v1507 and below. */
7951 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
7955 static const struct prov_method_sequence cache_req_seq10
[] = {
7956 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
7957 /* Done twice on Windows, but we shouldn't need to replicate this. */
7958 { &Provider_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_IsControlElementPropertyId */
7959 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
7960 NODE_CREATE_SEQ(&Provider
),
7961 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
7962 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
7966 static const struct UiaCondition UiaTrueCondition
= { ConditionType_True
};
7967 static const struct UiaCondition UiaFalseCondition
= { ConditionType_False
};
7968 static void test_UiaGetUpdatedCache(void)
7970 LONG exp_lbound
[2], exp_elems
[2], idx
[2], i
;
7971 struct Provider_prop_override prop_override
;
7972 struct node_provider_desc exp_node_desc
[2];
7973 struct UiaPropertyCondition prop_cond
;
7974 struct UiaAndOrCondition and_or_cond
;
7975 struct UiaCacheRequest cache_req
;
7976 struct UiaCondition
*cond_arr
[2];
7977 struct UiaNotCondition not_cond
;
7978 VARIANT v
, v_arr
[2];
7986 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
7988 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
7989 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7991 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
7992 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
7994 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
7995 Provider
.hwnd
= NULL
;
7996 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
7997 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
7998 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
8000 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
8001 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8002 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
8003 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
8006 ok_method_sequence(node_from_prov2
, NULL
);
8008 /* NULL arg tests. */
8009 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8010 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, NULL
);
8011 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8013 hr
= UiaGetUpdatedCache(node
, NULL
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8014 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8016 hr
= UiaGetUpdatedCache(NULL
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8017 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8020 * Cache request with NULL view condition, doesn't matter with
8021 * NormalizeState_None as passed in HUIANODE isn't evaluated against any
8024 tree_struct
= NULL
; out_req
= NULL
;
8025 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
8026 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8027 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8028 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8029 ok(!!out_req
, "out_req == NULL\n");
8030 ok(!!tree_struct
, "tree_struct == NULL\n");
8032 exp_lbound
[0] = exp_lbound
[1] = 0;
8033 exp_elems
[0] = exp_elems
[1] = 1;
8034 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8035 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8036 ok_method_sequence(cache_req_seq1
, "cache_req_seq1");
8038 SafeArrayDestroy(out_req
);
8039 SysFreeString(tree_struct
);
8042 * NormalizeState_View, HUIANODE gets checked against the ConditionType_False
8043 * condition within the cache request structure, nothing is returned.
8045 tree_struct
= NULL
; out_req
= NULL
;
8046 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaFalseCondition
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8047 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8048 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8049 ok(!out_req
, "out_req != NULL\n");
8051 /* Empty tree structure string. */
8052 ok(!!tree_struct
, "tree_struct == NULL\n");
8053 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8054 SysFreeString(tree_struct
);
8055 ok_method_sequence(cache_req_seq2
, "cache_req_seq2");
8058 * NormalizeState_View, HUIANODE gets checked against the ConditionType_True
8059 * condition within the cache request structure, returns this HUIANODE.
8061 tree_struct
= NULL
; out_req
= NULL
;
8062 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8063 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8064 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8065 ok(!!out_req
, "out_req == NULL\n");
8066 ok(!!tree_struct
, "tree_struct == NULL\n");
8068 exp_lbound
[0] = exp_lbound
[1] = 0;
8069 exp_elems
[0] = exp_elems
[1] = 1;
8070 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8071 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8072 ok_method_sequence(cache_req_seq1
, "cache_req_seq1");
8074 SafeArrayDestroy(out_req
);
8075 SysFreeString(tree_struct
);
8078 * NormalizeState_Custom, HUIANODE gets checked against our passed in
8079 * ConditionType_False condition.
8081 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8082 tree_struct
= NULL
; out_req
= NULL
;
8083 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_Custom
, (struct UiaCondition
*)&UiaFalseCondition
, &out_req
, &tree_struct
);
8084 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8085 ok(!out_req
, "out_req != NULL\n");
8087 /* Empty tree structure string. */
8088 ok(!!tree_struct
, "tree_struct == NULL\n");
8089 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8090 SysFreeString(tree_struct
);
8092 ok_method_sequence(cache_req_seq2
, "cache_req_seq2");
8095 * NormalizeState_Custom, HUIANODE gets checked against the ConditionType_True
8096 * condition we pass in, returns this HUIANODE.
8098 tree_struct
= NULL
; out_req
= NULL
;
8099 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8100 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_Custom
, (struct UiaCondition
*)&UiaTrueCondition
, &out_req
, &tree_struct
);
8101 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8102 ok(!!out_req
, "out_req == NULL\n");
8103 ok(!!tree_struct
, "tree_struct == NULL\n");
8105 exp_lbound
[0] = exp_lbound
[1] = 0;
8106 exp_elems
[0] = exp_elems
[1] = 1;
8107 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8108 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8109 ok_method_sequence(cache_req_seq1
, "cache_req_seq1");
8111 SafeArrayDestroy(out_req
);
8112 SysFreeString(tree_struct
);
8115 * CacheRequest with TreeScope_Children.
8117 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
8118 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
8119 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
8120 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child2", TRUE
);
8121 tree_struct
= NULL
; out_req
= NULL
;
8122 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Children
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8123 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8124 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8125 todo_wine
ok(!!out_req
, "out_req == NULL\n");
8126 todo_wine
ok(!!tree_struct
, "tree_struct == NULL\n");
8127 todo_wine
ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
8128 todo_wine
ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
8133 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8135 ok(!wcscmp(tree_struct
, L
"(P)P))"), "tree structure %s\n", debugstr_w(tree_struct
));
8136 ok_method_sequence(cache_req_seq3
, "cache_req_seq3");
8139 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
8140 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
8141 SafeArrayDestroy(out_req
);
8142 SysFreeString(tree_struct
);
8145 * ConditionType_And tests.
8147 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
8148 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
8149 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
8150 cond_arr
[0] = (struct UiaCondition
*)&UiaTrueCondition
;
8151 cond_arr
[1] = (struct UiaCondition
*)&UiaTrueCondition
;
8152 set_and_or_condition(&and_or_cond
, ConditionType_And
, cond_arr
, ARRAY_SIZE(cond_arr
));
8153 set_cache_request(&cache_req
, (struct UiaCondition
*)&and_or_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8154 AutomationElementMode_Full
);
8155 tree_struct
= NULL
; out_req
= NULL
;
8157 /* Equivalent to: if (1 && 1) */
8158 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8159 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8160 ok(!!out_req
, "out_req == NULL\n");
8161 ok(!!tree_struct
, "tree_struct == NULL\n");
8163 exp_lbound
[0] = exp_lbound
[1] = 0;
8164 exp_elems
[0] = exp_elems
[1] = 1;
8165 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8166 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8167 ok_method_sequence(cache_req_seq1
, NULL
);
8169 SafeArrayDestroy(out_req
);
8170 SysFreeString(tree_struct
);
8172 cond_arr
[0] = (struct UiaCondition
*)&UiaTrueCondition
;
8173 cond_arr
[1] = (struct UiaCondition
*)&UiaFalseCondition
;
8174 set_and_or_condition(&and_or_cond
, ConditionType_And
, cond_arr
, ARRAY_SIZE(cond_arr
));
8175 set_cache_request(&cache_req
, (struct UiaCondition
*)&and_or_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8176 AutomationElementMode_Full
);
8177 tree_struct
= NULL
; out_req
= NULL
;
8179 /* Equivalent to: if (1 && 0) */
8180 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8181 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8182 ok_method_sequence(cache_req_seq2
, NULL
);
8183 ok(!out_req
, "out_req != NULL\n");
8184 ok(!!tree_struct
, "tree_struct == NULL\n");
8185 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8187 SysFreeString(tree_struct
);
8190 * ConditionType_Or tests.
8192 cond_arr
[0] = (struct UiaCondition
*)&UiaTrueCondition
;
8193 cond_arr
[1] = (struct UiaCondition
*)&UiaFalseCondition
;
8194 set_and_or_condition(&and_or_cond
, ConditionType_Or
, cond_arr
, ARRAY_SIZE(cond_arr
));
8195 set_cache_request(&cache_req
, (struct UiaCondition
*)&and_or_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8196 AutomationElementMode_Full
);
8197 tree_struct
= NULL
; out_req
= NULL
;
8199 /* Equivalent to: if (1 || 0) */
8200 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8201 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8202 ok(!!out_req
, "out_req == NULL\n");
8203 ok(!!tree_struct
, "tree_struct == NULL\n");
8205 exp_lbound
[0] = exp_lbound
[1] = 0;
8206 exp_elems
[0] = exp_elems
[1] = 1;
8207 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8208 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8209 ok_method_sequence(cache_req_seq1
, NULL
);
8211 SafeArrayDestroy(out_req
);
8212 SysFreeString(tree_struct
);
8214 cond_arr
[0] = (struct UiaCondition
*)&UiaFalseCondition
;
8215 cond_arr
[1] = (struct UiaCondition
*)&UiaFalseCondition
;
8216 set_and_or_condition(&and_or_cond
, ConditionType_Or
, cond_arr
, ARRAY_SIZE(cond_arr
));
8217 set_cache_request(&cache_req
, (struct UiaCondition
*)&and_or_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8218 AutomationElementMode_Full
);
8219 tree_struct
= NULL
; out_req
= NULL
;
8221 /* Equivalent to: if (0 || 0) */
8222 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8223 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8224 ok_method_sequence(cache_req_seq2
, NULL
);
8225 ok(!out_req
, "out_req != NULL\n");
8226 ok(!!tree_struct
, "tree_struct == NULL\n");
8227 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8229 SysFreeString(tree_struct
);
8232 * ConditionType_Not tests.
8234 set_not_condition(¬_cond
, (struct UiaCondition
*)&UiaFalseCondition
);
8235 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8236 AutomationElementMode_Full
);
8237 tree_struct
= NULL
; out_req
= NULL
;
8239 /* Equivalent to: if (!0) */
8240 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8241 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8242 ok(!!out_req
, "out_req == NULL\n");
8243 ok(!!tree_struct
, "tree_struct == NULL\n");
8245 exp_lbound
[0] = exp_lbound
[1] = 0;
8246 exp_elems
[0] = exp_elems
[1] = 1;
8247 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8248 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8249 ok_method_sequence(cache_req_seq1
, NULL
);
8251 SafeArrayDestroy(out_req
);
8252 SysFreeString(tree_struct
);
8254 set_not_condition(¬_cond
, (struct UiaCondition
*)&UiaTrueCondition
);
8255 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8256 AutomationElementMode_Full
);
8257 tree_struct
= NULL
; out_req
= NULL
;
8259 /* Equivalent to: if (!1) */
8260 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8261 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8262 ok(!out_req
, "out_req != NULL\n");
8263 ok(!!tree_struct
, "tree_struct == NULL\n");
8264 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8265 SysFreeString(tree_struct
);
8266 ok_method_sequence(cache_req_seq2
, NULL
);
8269 * ConditionType_Property tests.
8271 Provider
.ret_invalid_prop_type
= FALSE
;
8273 /* Test UIAutomationType_IntArray property conditions. */
8274 if (UiaLookupId(AutomationIdentifierType_Property
, &OutlineColor_Property_GUID
))
8276 V_VT(&v
) = VT_I4
| VT_ARRAY
;
8277 V_ARRAY(&v
) = create_i4_safearray();
8278 set_property_condition(&prop_cond
, UIA_OutlineColorPropertyId
, &v
, PropertyConditionFlags_None
);
8279 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8280 AutomationElementMode_Full
);
8281 tree_struct
= NULL
; out_req
= NULL
;
8283 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8284 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8285 ok(!!out_req
, "out_req == NULL\n");
8286 ok(!!tree_struct
, "tree_struct == NULL\n");
8288 exp_lbound
[0] = exp_lbound
[1] = 0;
8289 exp_elems
[0] = exp_elems
[1] = 1;
8290 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8291 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8292 ok_method_sequence(cache_req_seq4
, NULL
);
8294 SafeArrayDestroy(out_req
);
8295 SysFreeString(tree_struct
);
8298 /* Same values, except we're short by one element. */
8299 V_VT(&v
) = VT_I4
| VT_ARRAY
;
8300 V_ARRAY(&v
) = SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(uia_i4_arr_prop_val
) - 1);
8302 for (i
= 0; i
< ARRAY_SIZE(uia_i4_arr_prop_val
) - 1; i
++)
8303 SafeArrayPutElement(V_ARRAY(&prop_cond
.Value
), &i
, (void *)&uia_i4_arr_prop_val
[i
]);
8305 set_property_condition(&prop_cond
, UIA_OutlineColorPropertyId
, &v
, PropertyConditionFlags_None
);
8306 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8307 AutomationElementMode_Full
);
8308 tree_struct
= NULL
; out_req
= NULL
;
8310 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8311 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8312 ok_method_sequence(cache_req_seq5
, NULL
);
8313 ok(!out_req
, "out_req != NULL\n");
8314 ok(!!tree_struct
, "tree_struct == NULL\n");
8315 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8317 SysFreeString(tree_struct
);
8321 win_skip("UIA_OutlineColorPropertyId unavailable, skipping property condition tests for it.\n");
8323 /* UIA_RuntimeIdPropertyId comparison. */
8324 Provider
.runtime_id
[0] = 0xdeadbeef; Provider
.runtime_id
[1] = 0xfeedbeef;
8325 V_VT(&v
) = VT_I4
| VT_ARRAY
;
8326 V_ARRAY(&v
) = SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(Provider
.runtime_id
));
8327 for (i
= 0; i
< ARRAY_SIZE(Provider
.runtime_id
); i
++)
8328 SafeArrayPutElement(V_ARRAY(&v
), &i
, (void *)&Provider
.runtime_id
[i
]);
8330 set_property_condition(&prop_cond
, UIA_RuntimeIdPropertyId
, &v
, PropertyConditionFlags_None
);
8331 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8332 AutomationElementMode_Full
);
8333 tree_struct
= NULL
; out_req
= NULL
;
8335 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8336 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8337 ok(!!out_req
, "out_req == NULL\n");
8338 ok(!!tree_struct
, "tree_struct == NULL\n");
8340 exp_lbound
[0] = exp_lbound
[1] = 0;
8341 exp_elems
[0] = exp_elems
[1] = 1;
8342 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8343 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8344 ok_method_sequence(cache_req_seq6
, NULL
);
8346 SafeArrayDestroy(out_req
);
8347 SysFreeString(tree_struct
);
8348 VariantClear(&prop_cond
.Value
);
8350 /* UIAutomationType_Bool property condition tests. */
8351 prop_override
.prop_id
= UIA_IsControlElementPropertyId
;
8352 V_VT(&prop_override
.val
) = VT_BOOL
;
8353 V_BOOL(&prop_override
.val
) = VARIANT_FALSE
;
8354 Provider
.prop_override
= &prop_override
;
8355 Provider
.prop_override_count
= 1;
8358 V_BOOL(&v
) = VARIANT_FALSE
;
8359 set_property_condition(&prop_cond
, UIA_IsControlElementPropertyId
, &v
, PropertyConditionFlags_None
);
8360 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8361 AutomationElementMode_Full
);
8362 tree_struct
= NULL
; out_req
= NULL
;
8364 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8365 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8366 ok(!!out_req
, "out_req == NULL\n");
8367 ok(!!tree_struct
, "tree_struct == NULL\n");
8369 exp_lbound
[0] = exp_lbound
[1] = 0;
8370 exp_elems
[0] = exp_elems
[1] = 1;
8371 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8372 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8373 ok_method_sequence(cache_req_seq4
, NULL
);
8375 SafeArrayDestroy(out_req
);
8376 SysFreeString(tree_struct
);
8380 * Provider now returns VARIANT_TRUE for UIA_IsControlElementPropertyId,
8381 * conditional check will fail.
8383 prop_override
.prop_id
= UIA_IsControlElementPropertyId
;
8384 V_VT(&prop_override
.val
) = VT_BOOL
;
8385 V_BOOL(&prop_override
.val
) = VARIANT_TRUE
;
8386 Provider
.prop_override
= &prop_override
;
8387 Provider
.prop_override_count
= 1;
8390 V_BOOL(&v
) = VARIANT_FALSE
;
8391 set_property_condition(&prop_cond
, UIA_IsControlElementPropertyId
, &v
, PropertyConditionFlags_None
);
8392 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0,
8393 AutomationElementMode_Full
);
8394 tree_struct
= NULL
; out_req
= NULL
;
8396 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8397 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8398 ok_method_sequence(cache_req_seq5
, NULL
);
8399 ok(!out_req
, "out_req != NULL\n");
8400 ok(!!tree_struct
, "tree_struct == NULL\n");
8401 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8403 SysFreeString(tree_struct
);
8406 Provider
.prop_override
= NULL
;
8407 Provider
.prop_override_count
= 0;
8410 * Tests for property value caching.
8412 prop_ids
[0] = UIA_RuntimeIdPropertyId
;
8413 /* Invalid property ID, no work will be done. */
8415 tree_struct
= NULL
; out_req
= NULL
;
8416 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, prop_ids
, ARRAY_SIZE(prop_ids
), NULL
, 0, AutomationElementMode_Full
);
8417 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8418 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
8419 ok(!out_req
, "out_req != NULL\n");
8420 ok(!tree_struct
, "tree_struct != NULL\n");
8423 * Retrieve values for UIA_RuntimeIdPropertyId and
8424 * UIA_IsControlElementPropertyId in the returned cache.
8426 prop_ids
[0] = UIA_RuntimeIdPropertyId
;
8427 prop_ids
[1] = UIA_IsControlElementPropertyId
;
8428 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
8429 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
8430 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
8432 tree_struct
= NULL
; out_req
= NULL
;
8433 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, prop_ids
, ARRAY_SIZE(prop_ids
), NULL
, 0, AutomationElementMode_Full
);
8434 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8435 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8436 ok(!!out_req
, "out_req == NULL\n");
8437 ok(!!tree_struct
, "tree_struct == NULL\n");
8439 exp_lbound
[0] = exp_lbound
[1] = 0;
8442 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8443 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8446 for (i
= 0; i
< ARRAY_SIZE(prop_ids
); i
++)
8449 VariantInit(&v_arr
[i
]);
8450 hr
= SafeArrayGetElement(out_req
, idx
, &v_arr
[i
]);
8451 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8454 ok(V_VT(&v_arr
[0]) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
8455 ok(V_UNKNOWN(&v_arr
[0]) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v_arr
[0]));
8456 VariantClear(&v_arr
[0]);
8458 ok(check_variant_bool(&v_arr
[1], TRUE
), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr
[1]));
8459 VariantClear(&v_arr
[1]);
8461 ok_method_sequence(cache_req_seq7
, "cache_req_seq7");
8462 SafeArrayDestroy(out_req
);
8463 SysFreeString(tree_struct
);
8466 * Again, but return a valid runtime ID and a different value for
8467 * UIA_IsControlElementPropertyId.
8470 V_BOOL(&v
) = VARIANT_FALSE
;
8471 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
8472 set_provider_prop_override(&Provider
, &prop_override
, 1);
8473 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0xdeadbeef;
8474 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
8475 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
8477 tree_struct
= NULL
; out_req
= NULL
;
8478 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, prop_ids
, ARRAY_SIZE(prop_ids
), NULL
, 0, AutomationElementMode_Full
);
8479 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_None
, NULL
, &out_req
, &tree_struct
);
8480 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8481 ok(!!out_req
, "out_req == NULL\n");
8482 ok(!!tree_struct
, "tree_struct == NULL\n");
8484 exp_lbound
[0] = exp_lbound
[1] = 0;
8487 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8488 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8491 for (i
= 0; i
< ARRAY_SIZE(prop_ids
); i
++)
8494 VariantInit(&v_arr
[i
]);
8495 hr
= SafeArrayGetElement(out_req
, idx
, &v_arr
[i
]);
8496 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8499 ok(V_VT(&v_arr
[0]) == (VT_I4
| VT_ARRAY
), "Unexpected vt %d\n", V_VT(&v_arr
[0]));
8500 check_runtime_id(Provider
.runtime_id
, ARRAY_SIZE(Provider
.runtime_id
), V_ARRAY(&v_arr
[0]));
8501 VariantClear(&v_arr
[0]);
8503 ok(check_variant_bool(&v_arr
[1], FALSE
), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr
[1]));
8504 VariantClear(&v_arr
[1]);
8506 ok_method_sequence(cache_req_seq7
, "cache_req_seq7");
8507 SafeArrayDestroy(out_req
);
8508 SysFreeString(tree_struct
);
8510 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
8511 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
8513 /* Normalization navigation tests. */
8514 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
8515 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
8517 hr
= UiaNodeFromProvider(&Provider_child
.IRawElementProviderSimple_iface
, &node
);
8518 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8519 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
8520 ok_method_sequence(cache_req_seq8
, "cache_req_seq8");
8523 * Neither Provider_child or Provider match this condition, return
8526 variant_init_bool(&v
, FALSE
);
8527 set_property_condition(&prop_cond
, UIA_IsControlElementPropertyId
, &v
, PropertyConditionFlags_None
);
8528 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8529 tree_struct
= NULL
; out_req
= NULL
;
8530 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8531 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8532 ok(!out_req
, "out_req != NULL\n");
8533 ok(!!tree_struct
, "tree_struct == NULL\n");
8534 ok(!wcscmp(tree_struct
, L
""), "tree structure %s\n", debugstr_w(tree_struct
));
8535 SysFreeString(tree_struct
);
8536 ok_method_sequence(cache_req_seq9
, "cache_req_seq9");
8539 * Provider now matches our condition, we'll get Provider in the cache
8542 variant_init_bool(&v
, FALSE
);
8543 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
8544 set_provider_prop_override(&Provider
, &prop_override
, 1);
8545 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
8546 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
8548 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8549 tree_struct
= NULL
; out_req
= NULL
;
8550 hr
= UiaGetUpdatedCache(node
, &cache_req
, NormalizeState_View
, NULL
, &out_req
, &tree_struct
);
8551 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8552 ok(!!out_req
, "out_req == NULL\n");
8553 ok(!!tree_struct
, "tree_struct == NULL\n");
8554 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
8556 exp_lbound
[0] = exp_lbound
[1] = 0;
8557 exp_elems
[0] = exp_elems
[1] = 1;
8558 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8559 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8560 ok_method_sequence(cache_req_seq10
, "cache_req_seq10");
8562 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
8563 SafeArrayDestroy(out_req
);
8564 SysFreeString(tree_struct
);
8567 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
8568 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
8569 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
8570 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
8572 IUnknown_Release(unk_ns
);
8576 static const struct prov_method_sequence nav_seq1
[] = {
8577 NODE_CREATE_SEQ2(&Provider
),
8578 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8579 /* Only done on Win10v1809+ */
8580 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8581 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8582 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8583 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8584 /* Windows 10+ calls these. */
8585 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8586 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8587 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8588 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8589 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8590 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8594 static const struct prov_method_sequence nav_seq2
[] = {
8595 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
8596 NODE_CREATE_SEQ(&Provider_hwnd_child
),
8597 { &Provider_hwnd_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8601 static const struct prov_method_sequence nav_seq3
[] = {
8602 { &Provider_hwnd_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8603 NODE_CREATE_SEQ(&Provider_hwnd_child2
),
8604 { &Provider_hwnd_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8608 static const struct prov_method_sequence nav_seq4
[] = {
8609 { &Provider_hwnd_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8610 { &Provider_hwnd_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8611 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
},
8612 /* All Windows versions use the NativeWindowHandle provider type check here. */
8613 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_NativeWindowHandlePropertyId */
8614 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8615 NODE_CREATE_SEQ2(&Provider
),
8616 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8617 /* Only done on Win10v1809+ */
8618 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8619 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8620 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8621 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8622 /* Windows 10+ calls these. */
8623 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8624 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8625 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8626 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
8627 { &Provider_nc_child
, PROV_GET_PROVIDER_OPTIONS
},
8628 /* Win10v1507 and below call this. */
8629 { &Provider_nc_child
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
8630 { &Provider_nc_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8631 { &Provider_nc_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
8632 { &Provider_nc_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8633 /* Only called on Windows versions past Win10v1507. */
8634 { &Provider_nc_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8635 { &Provider_nc_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8639 static const struct prov_method_sequence nav_seq5
[] = {
8640 { &Provider_nc_child
, FRAG_NAVIGATE
}, /* NavigateDirection_PreviousSibling */
8641 { &Provider_nc_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8642 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
},
8643 { &Provider_nc
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8644 NODE_CREATE_SEQ2(&Provider
),
8645 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8646 /* Only done on Win10v1809+ */
8647 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8648 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8649 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8650 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8651 /* Windows 10+ calls these. */
8652 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8653 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8654 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8655 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_LastChild */
8656 NODE_CREATE_SEQ(&Provider_hwnd_child2
),
8657 { &Provider_hwnd_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8661 static const struct prov_method_sequence nav_seq6
[] = {
8662 { &Provider_nc_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8663 NODE_CREATE_SEQ(&Provider_nc_child2
),
8664 { &Provider_nc_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8668 static const struct prov_method_sequence nav_seq7
[] = {
8669 { &Provider_nc_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8670 { &Provider_nc_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8671 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
},
8672 { &Provider_nc
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8673 NODE_CREATE_SEQ2(&Provider
),
8674 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8675 /* Only done on Win10v1809+ */
8676 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8677 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8678 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8679 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8680 /* Windows 10+ calls these. */
8681 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8682 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8683 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8684 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
8685 NODE_CREATE_SEQ(&Provider_child
),
8686 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8690 static const struct prov_method_sequence nav_seq8
[] = {
8691 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8692 NODE_CREATE_SEQ(&Provider_child2
),
8693 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8697 static const struct prov_method_sequence nav_seq9
[] = {
8698 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8699 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8700 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8701 /* Win10v1507 and below call this. */
8702 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
8703 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8704 NODE_CREATE_SEQ2(&Provider
),
8705 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8706 /* Only done on Win10v1809+ */
8707 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8708 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8709 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8710 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8711 /* Windows 10+ calls these. */
8712 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8713 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8714 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8715 /* Navigates to parent a second time. */
8716 { &Provider_child2
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
8717 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
8718 /* Win10v1507 and below call this. */
8719 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
8720 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_TODO
},
8721 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
8722 /* Win10v1507 and below call this. */
8723 { &Provider
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
8724 { &Provider
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_TODO
},
8725 { &Provider
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
8726 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
8727 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
8728 /* Only done on Win10v1809+ */
8729 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8730 { &Provider
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
8731 { &Provider_nc
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
8732 { &Provider_hwnd
, FRAG_NAVIGATE
, METHOD_TODO
}, /* NavigateDirection_Parent */
8733 /* Windows 10+ calls these. */
8734 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8735 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8736 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8739 static const struct prov_method_sequence nav_seq10
[] = {
8740 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_LastChild */
8741 NODE_CREATE_SEQ(&Provider_child2
),
8742 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8746 static const struct prov_method_sequence nav_seq11
[] = {
8747 { &Provider_hwnd
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
8748 { &Provider_hwnd_child
, PROV_GET_PROVIDER_OPTIONS
},
8749 /* All Windows versions use the NativeWindowHandle provider type check here. */
8750 { &Provider_hwnd_child
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_NativeWindowHandlePropertyId */
8751 { &Provider_hwnd_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8752 NODE_CREATE_SEQ2(&Provider
),
8753 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8754 /* Only done on Win10v1809+ */
8755 { &Provider_hwnd_child
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8756 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8757 /* Windows 10+ calls these. */
8758 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8759 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8760 { &Provider_hwnd_child
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8761 { &Provider_hwnd_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
8762 NODE_CREATE_SEQ(&Provider_hwnd_child2
),
8763 { &Provider_hwnd_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8767 static const struct prov_method_sequence nav_seq12
[] = {
8768 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_LastChild */
8769 { &Provider_child2
, PROV_GET_PROVIDER_OPTIONS
},
8770 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
, METHOD_OPTIONAL
}, /* UIA_NativeWindowHandlePropertyId */
8771 { &Provider_child2
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
},
8772 NODE_CREATE_SEQ2(&Provider
),
8773 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8774 /* Only done on Win10v1809+ */
8775 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8776 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8777 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8778 /* Windows 10+ calls these. */
8779 { &Provider_child2
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8780 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8781 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8782 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_PreviousSibling */
8783 NODE_CREATE_SEQ(&Provider_child
),
8784 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8788 static const struct prov_method_sequence nav_seq13
[] = {
8789 NODE_CREATE_SEQ2(&Provider
),
8790 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
8791 /* Only done on Win10v1809+ */
8792 { &Provider_hwnd
, PROV_GET_HOST_RAW_ELEMENT_PROVIDER
, METHOD_OPTIONAL
},
8793 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8794 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8795 /* Windows 10+ calls these. */
8796 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8797 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8798 { &Provider_hwnd
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
},
8799 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8800 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8801 { &Provider_hwnd
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8805 static const struct prov_method_sequence nav_seq14
[] = {
8806 { &Provider_nc
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8807 NODE_CREATE_SEQ(&Provider2
),
8808 { &Provider2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8812 static const struct prov_method_sequence nav_seq15
[] = {
8813 NODE_CREATE_SEQ(&Provider_child2_child_child
),
8814 { &Provider_child2_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8817 static const struct prov_method_sequence nav_seq16
[] = {
8818 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8819 NODE_CREATE_SEQ(&Provider_child2_child
),
8820 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
8821 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8822 NODE_CREATE_SEQ(&Provider_child2
),
8823 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
8824 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8825 NODE_CREATE_SEQ(&Provider
),
8826 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
8827 /* Only done on Win10v1507 and below. */
8828 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
8832 static const struct prov_method_sequence nav_seq17
[] = {
8833 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8834 NODE_CREATE_SEQ(&Provider_child2_child
),
8835 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
8836 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8837 NODE_CREATE_SEQ(&Provider_child2
),
8838 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
8839 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
8840 NODE_CREATE_SEQ(&Provider
),
8841 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
8842 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
8846 static void set_provider_nav_ifaces(struct Provider
*prov
, struct Provider
*parent
, struct Provider
*frag_root
,
8847 struct Provider
*prev_sibling
, struct Provider
*next_sibling
, struct Provider
*first_child
,
8848 struct Provider
*last_child
)
8850 prov
->parent
= NULL
;
8851 prov
->frag_root
= NULL
;
8852 prov
->prev_sibling
= NULL
;
8853 prov
->next_sibling
= NULL
;
8854 prov
->first_child
= NULL
;
8855 prov
->last_child
= NULL
;
8858 prov
->parent
= &parent
->IRawElementProviderFragment_iface
;
8860 prov
->frag_root
= &frag_root
->IRawElementProviderFragmentRoot_iface
;
8862 prov
->prev_sibling
= &prev_sibling
->IRawElementProviderFragment_iface
;
8864 prov
->next_sibling
= &next_sibling
->IRawElementProviderFragment_iface
;
8866 prov
->first_child
= &first_child
->IRawElementProviderFragment_iface
;
8868 prov
->last_child
= &last_child
->IRawElementProviderFragment_iface
;
8871 static void test_UiaNavigate(void)
8873 struct Provider_prop_override prop_override
;
8874 LONG exp_lbound
[2], exp_elems
[2], idx
[2], i
;
8875 struct node_provider_desc exp_node_desc
[4];
8876 struct UiaPropertyCondition prop_cond
;
8877 struct UiaCacheRequest cache_req
;
8878 HUIANODE node
, node2
, node3
;
8886 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
8888 cls
.lpfnWndProc
= test_wnd_proc
;
8891 cls
.hInstance
= GetModuleHandleA(NULL
);
8894 cls
.hbrBackground
= NULL
;
8895 cls
.lpszMenuName
= NULL
;
8896 cls
.lpszClassName
= "UiaNavigate class";
8898 RegisterClassA(&cls
);
8900 hwnd
= CreateWindowA("UiaNavigate class", "Test window", WS_OVERLAPPEDWINDOW
,
8901 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
8903 UiaRegisterProviderCallback(test_uia_provider_callback
);
8904 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
8905 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
8907 set_provider_nav_ifaces(&Provider_nc
, NULL
, NULL
, NULL
, NULL
, &Provider_nc_child
, &Provider_nc_child2
);
8908 set_provider_nav_ifaces(&Provider_nc_child
, &Provider_nc
, &Provider_nc
, NULL
,
8909 &Provider_nc_child2
, NULL
, NULL
);
8910 set_provider_nav_ifaces(&Provider_nc_child2
, &Provider_nc
, &Provider_nc
, &Provider_nc_child
,
8913 set_provider_nav_ifaces(&Provider_hwnd
, NULL
, NULL
, NULL
, NULL
, &Provider_hwnd_child
, &Provider_hwnd_child2
);
8914 set_provider_nav_ifaces(&Provider_hwnd_child
, &Provider_hwnd
, &Provider_hwnd
, NULL
,
8915 &Provider_hwnd_child2
, NULL
, NULL
);
8916 set_provider_nav_ifaces(&Provider_hwnd_child2
, &Provider_hwnd
, &Provider_hwnd
, &Provider_hwnd_child
,
8920 * Show navigation behavior for multi-provider nodes. Navigation order is:
8921 * HWND provider children.
8922 * Non-Client provider children.
8923 * Main provider children.
8924 * Override provider children.
8926 Provider
.prov_opts
= ProviderOptions_ServerSideProvider
;
8927 Provider
.hwnd
= Provider_hwnd
.hwnd
= Provider_nc
.hwnd
= hwnd
;
8928 Provider
.ignore_hwnd_prop
= Provider_nc
.ignore_hwnd_prop
= TRUE
;
8929 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
8930 node
= (void *)0xdeadbeef;
8931 /* Only sent on Win7. */
8932 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
8933 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
8934 SET_EXPECT(prov_callback_base_hwnd
);
8935 SET_EXPECT(prov_callback_nonclient
);
8936 hr
= UiaNodeFromHandle(hwnd
, &node
);
8937 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
8938 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
8939 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
8940 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
8941 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
8942 CHECK_CALLED(prov_callback_base_hwnd
);
8943 CHECK_CALLED(prov_callback_nonclient
);
8944 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
8946 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
8947 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8948 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
8949 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
8950 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
8951 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
8954 ok_method_sequence(nav_seq1
, "nav_seq1");
8956 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
8957 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
8958 idx
[0] = idx
[1] = 0;
8960 /* Navigate to Provider_hwnd_child. */
8961 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_hwnd_child", TRUE
);
8962 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
8963 tree_struct
= NULL
; out_req
= NULL
;
8964 hr
= UiaNavigate(node
, NavigateDirection_FirstChild
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
8965 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8966 ok(!!out_req
, "out_req == NULL\n");
8967 ok(!!tree_struct
, "tree_struct == NULL\n");
8968 ok(Provider_hwnd_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd_child
.ref
);
8970 node2
= node3
= NULL
;
8971 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
8972 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8974 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
8975 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8976 IUnknown_AddRef((IUnknown
*)node2
);
8978 exp_lbound
[0] = exp_lbound
[1] = 0;
8979 exp_elems
[0] = exp_elems
[1] = 1;
8980 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
8982 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
8983 ok_method_sequence(nav_seq2
, "nav_seq2");
8985 SafeArrayDestroy(out_req
);
8986 SysFreeString(tree_struct
);
8988 /* Navigate to Provider_hwnd_child2. */
8989 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
8990 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_hwnd_child2", TRUE
);
8991 hr
= UiaNavigate(node2
, NavigateDirection_NextSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
8992 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
8993 ok(!!out_req
, "out_req == NULL\n");
8994 ok(!!tree_struct
, "tree_struct == NULL\n");
8995 ok(Provider_hwnd_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
8997 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
8998 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9000 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
9001 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9002 IUnknown_AddRef((IUnknown
*)node3
);
9004 exp_lbound
[0] = exp_lbound
[1] = 0;
9005 exp_elems
[0] = exp_elems
[1] = 1;
9006 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9008 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9009 ok_method_sequence(nav_seq3
, "nav_seq3");
9011 SafeArrayDestroy(out_req
);
9012 SysFreeString(tree_struct
);
9014 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9015 ok(Provider_hwnd_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd_child
.ref
);
9018 /* Navigate to Provider_nc_child. */
9019 SET_EXPECT(prov_callback_nonclient
);
9020 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
9021 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9022 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_nc_child", TRUE
);
9023 hr
= UiaNavigate(node2
, NavigateDirection_NextSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9024 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9025 ok(!!out_req
, "out_req == NULL\n");
9026 ok(!!tree_struct
, "tree_struct == NULL\n");
9027 ok(Provider_nc_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc_child
.ref
);
9028 CHECK_CALLED(prov_callback_nonclient
);
9029 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
9031 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9032 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9034 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
9035 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9036 IUnknown_AddRef((IUnknown
*)node3
);
9038 exp_lbound
[0] = exp_lbound
[1] = 0;
9039 exp_elems
[0] = exp_elems
[1] = 1;
9040 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9042 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9043 ok_method_sequence(nav_seq4
, "nav_seq4");
9045 SafeArrayDestroy(out_req
);
9046 SysFreeString(tree_struct
);
9048 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9049 ok(Provider_hwnd_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
9052 /* Navigate back to Provider_hwnd_child2. */
9053 SET_EXPECT(prov_callback_base_hwnd
);
9054 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
9055 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9056 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_hwnd_child2", TRUE
);
9057 hr
= UiaNavigate(node2
, NavigateDirection_PreviousSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9058 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9059 ok(!!out_req
, "out_req == NULL\n");
9060 ok(!!tree_struct
, "tree_struct == NULL\n");
9061 ok(Provider_hwnd_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
9062 CHECK_CALLED(prov_callback_base_hwnd
);
9063 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
9065 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9066 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9068 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
9069 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9070 IUnknown_AddRef((IUnknown
*)node3
);
9072 exp_lbound
[0] = exp_lbound
[1] = 0;
9073 exp_elems
[0] = exp_elems
[1] = 1;
9074 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9076 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9077 ok_method_sequence(nav_seq5
, "nav_seq5");
9079 SafeArrayDestroy(out_req
);
9080 SysFreeString(tree_struct
);
9082 ok(UiaNodeRelease(node3
), "UiaNodeRelease returned FALSE\n");
9083 ok(Provider_hwnd_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
9085 /* Navigate to Provider_nc_child2. */
9086 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9087 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_nc_child2", TRUE
);
9088 hr
= UiaNavigate(node2
, NavigateDirection_NextSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9089 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9090 ok(!!out_req
, "out_req == NULL\n");
9091 ok(!!tree_struct
, "tree_struct == NULL\n");
9092 ok(Provider_nc_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc_child2
.ref
);
9094 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9095 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9097 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
9098 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9099 IUnknown_AddRef((IUnknown
*)node3
);
9101 exp_lbound
[0] = exp_lbound
[1] = 0;
9102 exp_elems
[0] = exp_elems
[1] = 1;
9103 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9105 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9106 ok_method_sequence(nav_seq6
, "nav_seq6");
9108 SafeArrayDestroy(out_req
);
9109 SysFreeString(tree_struct
);
9111 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9112 ok(Provider_nc_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc_child
.ref
);
9115 /* Navigate to Provider_child. */
9116 SET_EXPECT(prov_callback_base_hwnd
);
9117 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
9118 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9119 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
9120 hr
= UiaNavigate(node2
, NavigateDirection_NextSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9121 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9122 ok(!!out_req
, "out_req == NULL\n");
9123 ok(!!tree_struct
, "tree_struct == NULL\n");
9124 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
9125 CHECK_CALLED(prov_callback_base_hwnd
);
9126 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
9128 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9129 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9131 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
9132 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9133 IUnknown_AddRef((IUnknown
*)node3
);
9135 exp_lbound
[0] = exp_lbound
[1] = 0;
9136 exp_elems
[0] = exp_elems
[1] = 1;
9137 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9139 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9140 ok_method_sequence(nav_seq7
, "nav_seq7");
9142 SafeArrayDestroy(out_req
);
9143 SysFreeString(tree_struct
);
9145 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9146 ok(Provider_nc_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc_child2
.ref
);
9149 /* Navigate to Provider_child2. */
9150 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9151 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child2", TRUE
);
9152 hr
= UiaNavigate(node2
, NavigateDirection_NextSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9153 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9154 ok(!!out_req
, "out_req == NULL\n");
9155 ok(!!tree_struct
, "tree_struct == NULL\n");
9156 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
9158 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9159 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9161 hr
= UiaHUiaNodeFromVariant(&v
, &node3
);
9162 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9163 IUnknown_AddRef((IUnknown
*)node3
);
9165 exp_lbound
[0] = exp_lbound
[1] = 0;
9166 exp_elems
[0] = exp_elems
[1] = 1;
9167 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9169 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9170 ok_method_sequence(nav_seq8
, "nav_seq8");
9172 SafeArrayDestroy(out_req
);
9173 SysFreeString(tree_struct
);
9175 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9176 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
9179 /* Try navigating to next sibling on the final child of the node. */
9180 SET_EXPECT_MULTI(prov_callback_nonclient
, 2);
9181 SET_EXPECT_MULTI(prov_callback_base_hwnd
, 2);
9182 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
9183 hr
= UiaNavigate(node2
, NavigateDirection_NextSibling
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9184 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9185 ok_method_sequence(nav_seq9
, "nav_seq9");
9186 ok(!out_req
, "out_req != NULL\n");
9187 ok(!tree_struct
, "tree_struct != NULL\n");
9188 todo_wine
CHECK_CALLED_MULTI(prov_callback_nonclient
, 2);
9189 todo_wine
CHECK_CALLED_MULTI(prov_callback_base_hwnd
, 2);
9190 todo_wine
CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
9192 SafeArrayDestroy(out_req
);
9193 SysFreeString(tree_struct
);
9194 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9195 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
9197 /* Navigate to Provider_child2, last child. */
9198 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9199 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child2", TRUE
);
9200 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
9203 hr
= UiaNavigate(node
, NavigateDirection_LastChild
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9204 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9205 ok(!!out_req
, "out_req == NULL\n");
9206 ok(!!tree_struct
, "tree_struct == NULL\n");
9207 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd_child
.ref
);
9209 exp_lbound
[0] = exp_lbound
[1] = 0;
9210 exp_elems
[0] = exp_elems
[1] = 1;
9211 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9213 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9214 ok_method_sequence(nav_seq10
, "nav_seq10");
9216 SafeArrayDestroy(out_req
);
9217 SysFreeString(tree_struct
);
9220 * If the child we navigate to from a parent isn't considered the "parent
9221 * link" of it's HUIANODE, it is skipped. Here, we set Provider_hwnd_child
9222 * to an HWND provider, and set its main provider as Provider, which is
9223 * the parent link of the node.
9225 Provider_hwnd_child
.hwnd
= hwnd
;
9226 Provider_hwnd_child
.prov_opts
= ProviderOptions_ClientSideProvider
;
9227 Provider
.parent
= &Provider2
.IRawElementProviderFragment_iface
;
9228 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9229 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_hwnd_child2", TRUE
);
9232 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
9233 SET_EXPECT(prov_callback_nonclient
);
9234 hr
= UiaNavigate(node
, NavigateDirection_FirstChild
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9235 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9236 ok(!!out_req
, "out_req == NULL\n");
9237 ok(!!tree_struct
, "tree_struct == NULL\n");
9238 ok(Provider_hwnd_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
9239 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
9240 CHECK_CALLED(prov_callback_nonclient
);
9242 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9243 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9245 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
9246 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9247 IUnknown_AddRef((IUnknown
*)node2
);
9249 exp_lbound
[0] = exp_lbound
[1] = 0;
9250 exp_elems
[0] = exp_elems
[1] = 1;
9251 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9253 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9254 ok_method_sequence(nav_seq11
, "nav_seq11");
9256 SafeArrayDestroy(out_req
);
9257 SysFreeString(tree_struct
);
9259 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9260 ok(Provider_hwnd_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
9263 * Same test as before, except with NavigateDirection_LastChild. This will
9264 * end up with Provider_nc as the parent link for the node instead of
9267 Provider_child2
.hwnd
= hwnd
;
9268 Provider_child2
.ignore_hwnd_prop
= TRUE
;
9269 Provider_child2
.parent
= NULL
;
9270 Provider_nc
.parent
= &Provider2
.IRawElementProviderFragment_iface
;
9271 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
9272 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9273 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
9276 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
9277 SET_EXPECT(prov_callback_nonclient
);
9278 SET_EXPECT(prov_callback_base_hwnd
);
9279 hr
= UiaNavigate(node
, NavigateDirection_LastChild
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9280 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9281 ok(!!out_req
, "out_req == NULL\n");
9282 ok(!!tree_struct
, "tree_struct == NULL\n");
9283 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2
.ref
);
9284 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
9285 CHECK_CALLED(prov_callback_nonclient
);
9286 CHECK_CALLED(prov_callback_base_hwnd
);
9288 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
9289 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9291 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
9292 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9293 IUnknown_AddRef((IUnknown
*)node2
);
9295 exp_lbound
[0] = exp_lbound
[1] = 0;
9296 exp_elems
[0] = exp_elems
[1] = 1;
9297 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9299 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9300 ok_method_sequence(nav_seq12
, "nav_seq12");
9302 SafeArrayDestroy(out_req
);
9303 SysFreeString(tree_struct
);
9305 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
9306 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
9308 Provider_child2
.hwnd
= NULL
;
9309 Provider_child2
.ignore_hwnd_prop
= FALSE
;
9310 Provider_child2
.parent
= &Provider
.IRawElementProviderFragment_iface
;
9312 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
9313 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
9314 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
9315 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
9317 /* Create a node with Provider_nc as the parent link. */
9318 Provider
.parent
= Provider_hwnd
.parent
= NULL
;
9319 Provider_nc
.parent
= &Provider2
.IRawElementProviderFragment_iface
;
9320 Provider2
.prov_opts
= ProviderOptions_ServerSideProvider
;
9321 Provider2
.hwnd
= NULL
;
9323 node
= (void *)0xdeadbeef;
9324 /* Only sent on Win7. */
9325 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
9326 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
9327 SET_EXPECT(prov_callback_base_hwnd
);
9328 SET_EXPECT(prov_callback_nonclient
);
9329 hr
= UiaNodeFromHandle(hwnd
, &node
);
9330 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9331 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
9332 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
9333 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
9334 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
9335 CHECK_CALLED(prov_callback_base_hwnd
);
9336 CHECK_CALLED(prov_callback_nonclient
);
9337 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
9339 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
9340 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9341 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
9342 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
9343 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", TRUE
);
9344 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
9347 ok_method_sequence(nav_seq13
, "nav_seq13");
9349 /* Navigate to Provider2, parent of Provider_nc. */
9350 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9351 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider2", TRUE
);
9352 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
9355 hr
= UiaNavigate(node
, NavigateDirection_Parent
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
9356 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9357 ok(!!out_req
, "out_req == NULL\n");
9358 ok(!!tree_struct
, "tree_struct == NULL\n");
9359 ok(Provider2
.ref
== 2, "Unexpected refcnt %ld\n", Provider2
.ref
);
9361 exp_lbound
[0] = exp_lbound
[1] = 0;
9362 exp_elems
[0] = exp_elems
[1] = 1;
9363 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9365 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9367 SafeArrayDestroy(out_req
);
9368 SysFreeString(tree_struct
);
9369 ok(Provider2
.ref
== 1, "Unexpected refcnt %ld\n", Provider2
.ref
);
9370 ok_method_sequence(nav_seq14
, "nav_seq14");
9372 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
9373 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
9374 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
9375 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
9377 Provider_hwnd_child
.hwnd
= NULL
;
9378 Provider_hwnd_child
.prov_opts
= ProviderOptions_ServerSideProvider
;
9379 Provider
.ignore_hwnd_prop
= Provider_nc
.ignore_hwnd_prop
= FALSE
;
9380 base_hwnd_prov
= nc_prov
= NULL
;
9382 UiaRegisterProviderCallback(NULL
);
9385 * Conditional navigation for conditions other than ConditionType_True.
9387 initialize_provider_tree(TRUE
);
9388 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
9389 provider_add_child(&Provider
, &Provider_child2
);
9390 provider_add_child(&Provider_child2
, &Provider_child2_child
);
9391 provider_add_child(&Provider_child2_child
, &Provider_child2_child_child
);
9393 hr
= UiaNodeFromProvider(&Provider_child2_child_child
.IRawElementProviderSimple_iface
, &node
);
9394 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9395 ok(Provider_child2_child_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2_child_child
.ref
);
9397 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
9398 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9399 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
9400 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child2_child_child", TRUE
);
9403 ok_method_sequence(nav_seq15
, "nav_seq15");
9406 * Navigate from Provider_child2_child_child to a parent that has
9407 * UIA_IsControlElementPropertyId set to FALSE.
9410 V_BOOL(&v
) = VARIANT_FALSE
;
9411 set_property_condition(&prop_cond
, UIA_IsControlElementPropertyId
, &v
, PropertyConditionFlags_None
);
9413 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9414 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
9415 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
9418 hr
= UiaNavigate(node
, NavigateDirection_Parent
, (struct UiaCondition
*)&prop_cond
, &cache_req
, &out_req
, &tree_struct
);
9419 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9420 ok(!out_req
, "out_req != NULL\n");
9421 ok(!tree_struct
, "tree_struct != NULL\n");
9422 ok_method_sequence(nav_seq16
, "nav_seq16");
9424 /* Provider will now return FALSE for UIA_IsControlElementPropertyId. */
9425 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
9426 set_provider_prop_override(&Provider
, &prop_override
, 1);
9428 set_property_condition(&prop_cond
, UIA_IsControlElementPropertyId
, &v
, PropertyConditionFlags_None
);
9429 init_node_provider_desc(&exp_node_desc
[0], GetCurrentProcessId(), NULL
);
9430 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
9431 set_cache_request(&cache_req
, NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
);
9434 hr
= UiaNavigate(node
, NavigateDirection_Parent
, (struct UiaCondition
*)&prop_cond
, &cache_req
, &out_req
, &tree_struct
);
9435 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9436 ok(!!out_req
, "out_req == NULL\n");
9437 ok(!!tree_struct
, "tree_struct == NULL\n");
9438 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
9440 exp_lbound
[0] = exp_lbound
[1] = 0;
9441 exp_elems
[0] = exp_elems
[1] = 1;
9442 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9444 ok(!wcscmp(tree_struct
, L
"P)"), "tree structure %s\n", debugstr_w(tree_struct
));
9445 ok_method_sequence(nav_seq17
, "nav_seq17");
9446 SafeArrayDestroy(out_req
);
9447 SysFreeString(tree_struct
);
9449 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
9450 ok(Provider_child2_child_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2_child_child
.ref
);
9453 DestroyWindow(hwnd
);
9454 UnregisterClassA("UiaNavigate class", NULL
);
9457 static void set_find_params(struct UiaFindParams
*params
, int max_depth
, BOOL find_first
, BOOL exclude_root
,
9458 struct UiaCondition
*find_cond
)
9460 params
->MaxDepth
= max_depth
;
9461 params
->FindFirst
= find_first
;
9462 params
->ExcludeRoot
= exclude_root
;
9463 params
->pFindCondition
= find_cond
;
9466 static void set_provider_prop_override(struct Provider
*prov
, struct Provider_prop_override
*override
, int count
)
9468 prov
->prop_override
= override
;
9469 prov
->prop_override_count
= count
;
9472 static void set_property_override(struct Provider_prop_override
*override
, int prop_id
, VARIANT
*val
)
9474 override
->prop_id
= prop_id
;
9475 override
->val
= *val
;
9478 static void initialize_provider(struct Provider
*prov
, int prov_opts
, HWND hwnd
, BOOL initialize_nav_links
)
9480 prov
->prov_opts
= prov_opts
;
9482 prov
->ret_invalid_prop_type
= FALSE
;
9483 prov
->expected_tid
= 0;
9484 prov
->runtime_id
[0] = prov
->runtime_id
[1] = 0;
9485 prov
->last_call_tid
= 0;
9486 prov
->ignore_hwnd_prop
= FALSE
;
9487 prov
->override_hwnd
= NULL
;
9488 prov
->prop_override
= NULL
;
9489 prov
->prop_override_count
= 0;
9490 memset(&prov
->bounds_rect
, 0, sizeof(prov
->bounds_rect
));
9491 memset(&prov
->value_pattern_data
, 0, sizeof(prov
->value_pattern_data
));
9492 memset(&prov
->legacy_acc_pattern_data
, 0, sizeof(prov
->legacy_acc_pattern_data
));
9493 prov
->focus_prov
= NULL
;
9494 if (initialize_nav_links
)
9496 prov
->frag_root
= NULL
;
9497 prov
->parent
= prov
->prev_sibling
= prov
->next_sibling
= prov
->first_child
= prov
->last_child
= NULL
;
9501 static void initialize_provider_tree(BOOL initialize_nav_links
)
9503 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9504 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9505 initialize_provider(&Provider_child_child
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9506 initialize_provider(&Provider_child_child2
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9507 initialize_provider(&Provider_child2
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9508 initialize_provider(&Provider_child2_child
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9509 initialize_provider(&Provider_child2_child_child
, ProviderOptions_ServerSideProvider
, NULL
, initialize_nav_links
);
9512 static void provider_add_child(struct Provider
*prov
, struct Provider
*child
)
9514 if (!prov
->first_child
)
9516 prov
->first_child
= prov
->last_child
= &child
->IRawElementProviderFragment_iface
;
9517 child
->next_sibling
= child
->prev_sibling
= NULL
;
9521 struct Provider
*tmp
= impl_from_ProviderFragment(prov
->last_child
);
9523 tmp
->next_sibling
= &child
->IRawElementProviderFragment_iface
;
9524 child
->prev_sibling
= prov
->last_child
;
9525 prov
->last_child
= &child
->IRawElementProviderFragment_iface
;
9528 child
->parent
= &prov
->IRawElementProviderFragment_iface
;
9529 child
->frag_root
= prov
->frag_root
;
9532 #define test_find_sa_results( tree_structs, offsets, exp_elems, exp_tree_struct, exp_offsets ) \
9533 test_find_sa_results_( (tree_structs), (offsets), (exp_elems), (exp_tree_struct), (exp_offsets), __FILE__, __LINE__)
9534 static void test_find_sa_results_(SAFEARRAY
*tree_structs
, SAFEARRAY
*offsets
, LONG exp_elems
,
9535 const WCHAR
**exp_tree_struct
, int *exp_offset
, const char *file
, int line
)
9537 LONG lbound
, ubound
, elems
;
9543 /* Tree structures SA. */
9544 hr
= SafeArrayGetVartype(tree_structs
, &vt
);
9545 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9546 ok_(file
, line
)(vt
== VT_BSTR
, "Unexpected tree structures sa vt %d\n", vt
);
9547 dims
= SafeArrayGetDim(tree_structs
);
9548 ok_(file
, line
)(dims
== 1, "Unexpected tree structures sa dims %d\n", dims
);
9550 lbound
= ubound
= elems
= 0;
9551 hr
= SafeArrayGetLBound(tree_structs
, 1, &lbound
);
9552 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr
);
9553 ok_(file
, line
)(!lbound
, "Unexpected lbound %ld\n", lbound
);
9555 hr
= SafeArrayGetUBound(tree_structs
, 1, &ubound
);
9556 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr
);
9558 elems
= (ubound
- lbound
) + 1;
9559 ok_(file
, line
)(exp_elems
== elems
, "Unexpected elems %ld\n", elems
);
9562 hr
= SafeArrayGetVartype(offsets
, &vt
);
9563 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9564 ok_(file
, line
)(vt
== VT_I4
, "Unexpected offsets sa vt %d\n", vt
);
9565 dims
= SafeArrayGetDim(offsets
);
9566 ok_(file
, line
)(dims
== 1, "Unexpected offsets sa dims %d\n", dims
);
9568 lbound
= ubound
= elems
= 0;
9569 hr
= SafeArrayGetLBound(offsets
, 1, &lbound
);
9570 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr
);
9571 ok_(file
, line
)(!lbound
, "Unexpected lbound %ld\n", lbound
);
9573 hr
= SafeArrayGetUBound(offsets
, 1, &ubound
);
9574 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr
);
9576 elems
= (ubound
- lbound
) + 1;
9577 ok_(file
, line
)(exp_elems
== elems
, "Unexpected elems %ld\n", elems
);
9579 for (i
= 0; i
< exp_elems
; i
++)
9584 hr
= SafeArrayGetElement(tree_structs
, &i
, &tree_struct
);
9585 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9586 ok_(file
, line
)(!wcscmp(tree_struct
, exp_tree_struct
[i
]), "Unexpected tree structure %s\n", debugstr_w(tree_struct
));
9587 SysFreeString(tree_struct
);
9589 hr
= SafeArrayGetElement(offsets
, &i
, &offset
);
9590 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9591 ok_(file
, line
)(exp_offset
[i
] == offset
, "Unexpected offset %d\n", offset
);
9595 static const struct prov_method_sequence find_seq1
[] = {
9596 { &Provider
, FRAG_GET_RUNTIME_ID
},
9597 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9598 NODE_CREATE_SEQ(&Provider_child
),
9599 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9600 NODE_CREATE_SEQ(&Provider_child_child
),
9601 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9602 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9603 NODE_CREATE_SEQ(&Provider_child_child2
),
9604 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9605 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9606 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9607 NODE_CREATE_SEQ(&Provider_child
),
9608 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9609 NODE_CREATE_SEQ(&Provider_child2
),
9610 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9611 NODE_CREATE_SEQ(&Provider_child2_child
),
9612 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9613 NODE_CREATE_SEQ(&Provider_child2_child_child
),
9614 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9615 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9616 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9617 NODE_CREATE_SEQ(&Provider_child2_child
),
9618 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9619 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9620 NODE_CREATE_SEQ(&Provider_child2
),
9621 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9622 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9623 NODE_CREATE_SEQ(&Provider
),
9624 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9625 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9626 /* Only done on Win10v1507 and below. */
9627 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
9628 { &Provider
, FRAG_GET_RUNTIME_ID
},
9629 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9630 { &Provider_child_child
, FRAG_GET_RUNTIME_ID
},
9631 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9632 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9633 { &Provider_child2_child
, FRAG_GET_RUNTIME_ID
},
9634 { &Provider_child2_child_child
, FRAG_GET_RUNTIME_ID
},
9635 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9636 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9637 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9638 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9639 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9640 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9641 { &Provider_child2_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9645 static const struct prov_method_sequence find_seq2
[] = {
9646 { &Provider
, FRAG_GET_RUNTIME_ID
},
9647 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9648 NODE_CREATE_SEQ(&Provider_child
),
9649 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9650 NODE_CREATE_SEQ(&Provider_child2
),
9651 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9652 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9653 NODE_CREATE_SEQ(&Provider
),
9654 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9655 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9656 /* Only done on Win10v1507 and below. */
9657 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
9658 { &Provider
, FRAG_GET_RUNTIME_ID
},
9659 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9660 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9661 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9662 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9663 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9667 static const struct prov_method_sequence find_seq3
[] = {
9668 { &Provider
, FRAG_GET_RUNTIME_ID
},
9669 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9670 NODE_CREATE_SEQ(&Provider_child
),
9671 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9672 NODE_CREATE_SEQ(&Provider_child2
),
9673 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9674 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9675 NODE_CREATE_SEQ(&Provider
),
9676 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9677 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9678 /* Only done on Win10v1507 and below. */
9679 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
9680 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9681 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9682 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9683 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9687 static const struct prov_method_sequence find_seq4
[] = {
9688 { &Provider
, FRAG_GET_RUNTIME_ID
},
9689 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9690 NODE_CREATE_SEQ(&Provider_child
),
9691 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9692 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9696 static const struct prov_method_sequence find_seq5
[] = {
9697 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9698 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9699 NODE_CREATE_SEQ(&Provider_child2
),
9700 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9701 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9702 NODE_CREATE_SEQ(&Provider
),
9703 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9704 NODE_CREATE_SEQ(&Provider
),
9705 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9706 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9707 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9708 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9712 static const struct prov_method_sequence find_seq6
[] = {
9713 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9714 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9715 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9716 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9720 static const struct prov_method_sequence find_seq7
[] = {
9721 { &Provider
, FRAG_GET_RUNTIME_ID
},
9722 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9723 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9724 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9725 NODE_CREATE_SEQ(&Provider_child
),
9726 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9727 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9728 NODE_CREATE_SEQ(&Provider_child_child
),
9729 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9730 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9731 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9732 NODE_CREATE_SEQ(&Provider_child_child2
),
9733 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9734 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9735 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9736 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9737 NODE_CREATE_SEQ(&Provider_child
),
9738 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9739 NODE_CREATE_SEQ(&Provider_child2
),
9740 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9741 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9742 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9743 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9744 NODE_CREATE_SEQ(&Provider
),
9745 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9746 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9747 /* Only done on Win10v1507 and below. */
9748 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
9749 { &Provider
, FRAG_GET_RUNTIME_ID
},
9750 { &Provider_child_child
, FRAG_GET_RUNTIME_ID
},
9751 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9752 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9753 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9754 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9755 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9756 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9760 static const struct prov_method_sequence find_seq8
[] = {
9761 { &Provider
, FRAG_GET_RUNTIME_ID
},
9762 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9763 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9764 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9765 NODE_CREATE_SEQ(&Provider_child
),
9766 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9767 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9768 NODE_CREATE_SEQ(&Provider_child_child
),
9769 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9770 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9771 { &Provider_child_child
, FRAG_GET_RUNTIME_ID
},
9772 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9773 NODE_CREATE_SEQ(&Provider_child_child2
),
9774 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9775 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9776 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9777 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9778 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9779 NODE_CREATE_SEQ(&Provider_child
),
9780 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
9781 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9782 NODE_CREATE_SEQ(&Provider_child2
),
9783 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9784 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9785 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9786 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9787 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9788 NODE_CREATE_SEQ(&Provider
),
9789 { &Provider
, FRAG_GET_RUNTIME_ID
},
9790 { &Provider
, FRAG_GET_RUNTIME_ID
},
9791 { &Provider_child_child
, FRAG_GET_RUNTIME_ID
},
9792 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9793 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9794 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9795 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9796 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9797 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9801 static const struct prov_method_sequence find_seq9
[] = {
9802 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9803 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9804 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9805 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9806 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9807 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9808 NODE_CREATE_SEQ(&Provider_child
),
9809 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9810 NODE_CREATE_SEQ(&Provider_child
),
9811 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9812 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9813 NODE_CREATE_SEQ(&Provider_child2
),
9814 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9815 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9816 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9817 NODE_CREATE_SEQ(&Provider_child2_child
),
9818 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9819 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9820 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9821 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9822 NODE_CREATE_SEQ(&Provider_child2
),
9823 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9824 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9825 NODE_CREATE_SEQ(&Provider
),
9826 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9827 NODE_CREATE_SEQ(&Provider
),
9828 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9829 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9830 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9831 /* Only done on Win10v1507 and below. */
9832 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
9833 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9834 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9835 { &Provider_child2_child
, FRAG_GET_RUNTIME_ID
},
9836 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9837 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9838 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9842 static const struct prov_method_sequence find_seq10
[] = {
9843 { &Provider
, FRAG_GET_RUNTIME_ID
},
9844 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9845 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9846 NODE_CREATE_SEQ(&Provider_child
),
9847 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9848 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9849 NODE_CREATE_SEQ(&Provider_child_child
),
9850 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9851 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9852 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9853 NODE_CREATE_SEQ(&Provider_child_child2
),
9854 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9855 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9856 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9857 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9858 NODE_CREATE_SEQ(&Provider_child
),
9859 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9860 NODE_CREATE_SEQ(&Provider_child2
),
9861 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9862 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9863 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9864 NODE_CREATE_SEQ(&Provider_child2_child
),
9865 { &Provider_child2_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9866 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9867 NODE_CREATE_SEQ(&Provider_child2_child_child
),
9868 { &Provider_child2_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9869 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9870 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9871 { &Provider_child2_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9872 NODE_CREATE_SEQ(&Provider_child2_child
),
9873 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9874 { &Provider_child2_child
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9875 NODE_CREATE_SEQ(&Provider_child2
),
9876 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9877 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9878 NODE_CREATE_SEQ(&Provider
),
9879 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9880 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
9881 /* Only done on Win10v1507 and below. */
9882 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
9883 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
9884 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9888 static const struct prov_method_sequence find_seq11
[] = {
9889 { &Provider
, FRAG_GET_RUNTIME_ID
},
9890 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9891 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9892 NODE_CREATE_SEQ(&Provider_child
),
9893 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9894 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9895 NODE_CREATE_SEQ(&Provider_child_child
),
9896 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9897 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
9898 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
9899 NODE_CREATE_SEQ(&Provider_child_child2
),
9900 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
9901 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
9902 { &Provider_child_child2
, FRAG_GET_RUNTIME_ID
},
9903 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
9907 static void test_UiaFind(void)
9909 struct Provider_prop_override prop_override
;
9910 LONG exp_lbound
[2], exp_elems
[2], idx
[2], i
;
9911 SAFEARRAY
*out_req
, *offsets
, *tree_structs
;
9912 struct node_provider_desc exp_node_desc
[7];
9913 struct UiaPropertyCondition prop_cond
[2];
9914 struct UiaCacheRequest cache_req
;
9915 struct UiaFindParams find_params
;
9916 const WCHAR
*exp_tree_struct
[7];
9917 int exp_offset
[7], cache_prop
;
9918 HUIANODE node
, node2
;
9922 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
9924 initialize_provider_tree(TRUE
);
9925 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
9926 provider_add_child(&Provider
, &Provider_child
);
9927 provider_add_child(&Provider
, &Provider_child2
);
9928 provider_add_child(&Provider_child
, &Provider_child_child
);
9929 provider_add_child(&Provider_child
, &Provider_child_child2
);
9930 provider_add_child(&Provider_child2
, &Provider_child2_child
);
9931 provider_add_child(&Provider_child2_child
, &Provider_child2_child_child
);
9933 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
9934 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
9936 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
9937 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9938 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
9940 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
9941 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
9942 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
9943 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
9946 ok_method_sequence(node_from_prov2
, NULL
);
9949 * Maximum find depth of -1, find first is FALSE, exclude root is FALSE. A
9950 * maximum depth of -1 will search the entire tree.
9952 out_req
= offsets
= tree_structs
= NULL
;
9953 cache_prop
= UIA_RuntimeIdPropertyId
;
9954 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
9955 AutomationElementMode_Full
);
9956 set_find_params(&find_params
, -1, FALSE
, FALSE
, (struct UiaCondition
*)&UiaTrueCondition
);
9957 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
9958 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
9959 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
9960 ok(Provider_child_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child
.ref
);
9961 ok(Provider_child_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
9962 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
9963 ok(Provider_child2_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2_child
.ref
);
9964 ok(Provider_child2_child_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2_child_child
.ref
);
9966 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
9967 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child", TRUE
);
9968 add_provider_desc(&exp_node_desc
[2], L
"Main", L
"Provider_child_child", TRUE
);
9969 add_provider_desc(&exp_node_desc
[3], L
"Main", L
"Provider_child_child2", TRUE
);
9970 add_provider_desc(&exp_node_desc
[4], L
"Main", L
"Provider_child2", TRUE
);
9971 add_provider_desc(&exp_node_desc
[5], L
"Main", L
"Provider_child2_child", TRUE
);
9972 add_provider_desc(&exp_node_desc
[6], L
"Main", L
"Provider_child2_child_child", TRUE
);
9973 exp_lbound
[0] = exp_lbound
[1] = 0;
9977 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
9979 for (i
= 0; i
< exp_elems
[0]; i
++)
9982 exp_tree_struct
[i
] = L
"P)";
9984 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
9985 ok_method_sequence(find_seq1
, "find_seq1");
9987 SafeArrayDestroy(out_req
);
9988 SafeArrayDestroy(offsets
);
9989 SafeArrayDestroy(tree_structs
);
9991 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
9992 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
9995 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
9997 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
9998 AutomationElementMode_Full
);
9999 set_find_params(&find_params
, 1, FALSE
, FALSE
, (struct UiaCondition
*)&UiaTrueCondition
);
10000 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10001 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10002 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10003 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10005 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
10006 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child", TRUE
);
10007 add_provider_desc(&exp_node_desc
[2], L
"Main", L
"Provider_child2", TRUE
);
10008 exp_lbound
[0] = exp_lbound
[1] = 0;
10012 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10014 for (i
= 0; i
< exp_elems
[0]; i
++)
10017 exp_tree_struct
[i
] = L
"P)";
10020 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10021 ok_method_sequence(find_seq2
, "find_seq2");
10023 SafeArrayDestroy(out_req
);
10024 SafeArrayDestroy(offsets
);
10025 SafeArrayDestroy(tree_structs
);
10027 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10028 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10031 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
10033 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10034 AutomationElementMode_Full
);
10035 set_find_params(&find_params
, 1, FALSE
, TRUE
, (struct UiaCondition
*)&UiaTrueCondition
);
10036 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10037 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10038 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10039 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10041 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
10042 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child2", TRUE
);
10043 exp_lbound
[0] = exp_lbound
[1] = 0;
10047 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10049 for (i
= 0; i
< exp_elems
[0]; i
++)
10052 exp_tree_struct
[i
] = L
"P)";
10054 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10055 ok_method_sequence(find_seq3
, "find_seq3");
10057 SafeArrayDestroy(out_req
);
10058 SafeArrayDestroy(offsets
);
10059 SafeArrayDestroy(tree_structs
);
10061 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10062 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10065 * Maximum find depth of 1, find first is TRUE, exclude root is TRUE. Will
10066 * retrieve only Provider_child.
10068 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10069 AutomationElementMode_Full
);
10070 set_find_params(&find_params
, 1, TRUE
, TRUE
, (struct UiaCondition
*)&UiaTrueCondition
);
10071 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10072 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10073 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10075 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
10076 exp_lbound
[0] = exp_lbound
[1] = 0;
10080 idx
[0] = idx
[1] = 0;
10081 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
10082 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10084 /* node2 is now set as Provider_child. */
10085 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
10086 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10087 IUnknown_AddRef((IUnknown
*)node2
);
10089 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10091 for (i
= 0; i
< exp_elems
[0]; i
++)
10094 exp_tree_struct
[i
] = L
"P)";
10096 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10097 ok_method_sequence(find_seq4
, "find_seq4");
10099 SafeArrayDestroy(out_req
);
10100 SafeArrayDestroy(offsets
);
10101 SafeArrayDestroy(tree_structs
);
10103 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10104 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10107 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
10108 * Provider_child doesn't have a runtime id for UI Automation to use as a
10109 * way to check if it has navigated back to the node that began the
10110 * search, so it will get siblings.
10112 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10113 AutomationElementMode_Full
);
10114 set_find_params(&find_params
, 0, FALSE
, FALSE
, (struct UiaCondition
*)&UiaTrueCondition
);
10115 hr
= UiaFind(node2
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10116 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10117 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10119 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
10120 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child2", TRUE
);
10121 exp_lbound
[0] = exp_lbound
[1] = 0;
10125 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10127 for (i
= 0; i
< exp_elems
[0]; i
++)
10130 exp_tree_struct
[i
] = L
"P)";
10132 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10133 ok_method_sequence(find_seq5
, "find_seq5");
10135 SafeArrayDestroy(out_req
);
10136 SafeArrayDestroy(offsets
);
10137 SafeArrayDestroy(tree_structs
);
10139 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10140 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10143 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
10144 * Provider_child has a runtime id for UI Automation to use as a
10145 * way to check if it has navigated back to the node that began the
10146 * search, so it will stop at Provider_child.
10148 Provider_child
.runtime_id
[0] = Provider_child
.runtime_id
[1] = 0xdeadbeef;
10149 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10150 AutomationElementMode_Full
);
10151 set_find_params(&find_params
, 0, FALSE
, FALSE
, (struct UiaCondition
*)&UiaTrueCondition
);
10152 hr
= UiaFind(node2
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10153 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10155 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child", TRUE
);
10156 exp_lbound
[0] = exp_lbound
[1] = 0;
10160 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10162 for (i
= 0; i
< exp_elems
[0]; i
++)
10165 exp_tree_struct
[i
] = L
"P)";
10167 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10168 ok_method_sequence(find_seq6
, "find_seq6");
10170 SafeArrayDestroy(out_req
);
10171 SafeArrayDestroy(offsets
);
10172 SafeArrayDestroy(tree_structs
);
10174 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
10175 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10177 initialize_provider_tree(FALSE
);
10178 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10179 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10182 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
10183 * The cache request view condition is used to determine tree depth, if an
10184 * element matches the cache request view condition, depth is incremented.
10185 * Since Provider_child does not, Provider_child_child, Provider_child_child2,
10186 * and Provider_child2 are all considered to be at depth 1.
10188 V_VT(&v
) = VT_BOOL
;
10189 V_BOOL(&v
) = VARIANT_FALSE
;
10190 set_property_condition(&prop_cond
[0], UIA_IsContentElementPropertyId
, &v
, 0);
10191 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
10193 V_VT(&v
) = VT_BOOL
;
10194 V_BOOL(&v
) = VARIANT_TRUE
;
10195 set_property_condition(&prop_cond
[1], UIA_IsControlElementPropertyId
, &v
, 0);
10197 set_provider_prop_override(&Provider
, &prop_override
, 1);
10198 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
10199 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
10200 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
10202 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
[0], TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10203 AutomationElementMode_Full
);
10204 set_find_params(&find_params
, 1, FALSE
, FALSE
, (struct UiaCondition
*)&prop_cond
[1]);
10205 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10206 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10207 ok(Provider_child_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child
.ref
);
10208 ok(Provider_child_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
10209 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10211 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
10212 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child_child", TRUE
);
10213 add_provider_desc(&exp_node_desc
[2], L
"Main", L
"Provider_child_child2", TRUE
);
10214 add_provider_desc(&exp_node_desc
[3], L
"Main", L
"Provider_child2", TRUE
);
10215 exp_lbound
[0] = exp_lbound
[1] = 0;
10219 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10221 for (i
= 0; i
< exp_elems
[0]; i
++)
10224 exp_tree_struct
[i
] = L
"P)";
10226 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10227 ok_method_sequence(find_seq7
, "find_seq7");
10229 SafeArrayDestroy(out_req
);
10230 SafeArrayDestroy(offsets
);
10231 SafeArrayDestroy(tree_structs
);
10233 initialize_provider_tree(FALSE
);
10234 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10235 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10238 * Same test as before, except Provider has a runtime id.
10240 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0xdeadbeef;
10241 V_VT(&v
) = VT_BOOL
;
10242 V_BOOL(&v
) = VARIANT_FALSE
;
10243 set_property_condition(&prop_cond
[0], UIA_IsContentElementPropertyId
, &v
, 0);
10244 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
10246 V_VT(&v
) = VT_BOOL
;
10247 V_BOOL(&v
) = VARIANT_TRUE
;
10248 set_property_condition(&prop_cond
[1], UIA_IsControlElementPropertyId
, &v
, 0);
10250 set_provider_prop_override(&Provider
, &prop_override
, 1);
10251 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
10252 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
10253 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
10255 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
[0], TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10256 AutomationElementMode_Full
);
10257 set_find_params(&find_params
, 1, FALSE
, FALSE
, (struct UiaCondition
*)&prop_cond
[1]);
10258 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10259 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10260 ok(Provider_child_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child
.ref
);
10261 ok(Provider_child_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
10262 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10264 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider", TRUE
);
10265 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child_child", TRUE
);
10266 add_provider_desc(&exp_node_desc
[2], L
"Main", L
"Provider_child_child2", TRUE
);
10267 add_provider_desc(&exp_node_desc
[3], L
"Main", L
"Provider_child2", TRUE
);
10268 exp_lbound
[0] = exp_lbound
[1] = 0;
10274 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
10275 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10277 /* node2 is now set as Provider_child_child2. */
10278 hr
= UiaHUiaNodeFromVariant(&v
, &node2
);
10279 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10280 IUnknown_AddRef((IUnknown
*)node2
);
10282 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10284 for (i
= 0; i
< exp_elems
[0]; i
++)
10287 exp_tree_struct
[i
] = L
"P)";
10289 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10290 ok_method_sequence(find_seq8
, "find_seq8");
10292 SafeArrayDestroy(out_req
);
10293 SafeArrayDestroy(offsets
);
10294 SafeArrayDestroy(tree_structs
);
10296 initialize_provider_tree(FALSE
);
10297 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10298 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10301 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
10302 * Starting at Provider_child_child2, find will be able to traverse the
10303 * tree in the same order as it would if we had started at the tree root
10304 * Provider, retrieving Provider_child2 as a sibling and
10305 * Provider_child2_child as a node at depth 1.
10307 V_VT(&v
) = VT_BOOL
;
10308 V_BOOL(&v
) = VARIANT_FALSE
;
10309 set_property_condition(&prop_cond
[0], UIA_IsContentElementPropertyId
, &v
, 0);
10311 V_VT(&v
) = VT_BOOL
;
10312 V_BOOL(&v
) = VARIANT_TRUE
;
10313 set_property_condition(&prop_cond
[1], UIA_IsControlElementPropertyId
, &v
, 0);
10315 prop_override
.prop_id
= UIA_IsContentElementPropertyId
;
10316 V_VT(&prop_override
.val
) = VT_BOOL
;
10317 V_BOOL(&prop_override
.val
) = VARIANT_FALSE
;
10318 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
10319 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
10320 set_provider_prop_override(&Provider_child2_child
, &prop_override
, 1);
10322 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
[0], TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10323 AutomationElementMode_Full
);
10324 set_find_params(&find_params
, 1, FALSE
, FALSE
, (struct UiaCondition
*)&prop_cond
[1]);
10325 hr
= UiaFind(node2
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10326 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10327 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10328 ok(Provider_child2_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2_child
.ref
);
10330 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child_child2", TRUE
);
10331 add_provider_desc(&exp_node_desc
[1], L
"Main", L
"Provider_child2", TRUE
);
10332 add_provider_desc(&exp_node_desc
[2], L
"Main", L
"Provider_child2_child", TRUE
);
10333 exp_lbound
[0] = exp_lbound
[1] = 0;
10337 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10339 for (i
= 0; i
< exp_elems
[0]; i
++)
10342 exp_tree_struct
[i
] = L
"P)";
10344 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10345 ok_method_sequence(find_seq9
, "find_seq9");
10347 SafeArrayDestroy(out_req
);
10348 SafeArrayDestroy(offsets
);
10349 SafeArrayDestroy(tree_structs
);
10351 initialize_provider_tree(FALSE
);
10352 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10353 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10355 ok(UiaNodeRelease(node2
), "UiaNodeRelease returned FALSE\n");
10356 ok(Provider_child_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
10359 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
10360 * Exclude root applies to the first node that matches the view
10361 * condition, and not the node that is passed into UiaFind(). Since
10362 * Provider doesn't match our view condition here, Provider_child will be
10365 V_VT(&v
) = VT_BOOL
;
10366 V_BOOL(&v
) = VARIANT_FALSE
;
10367 set_property_condition(&prop_cond
[0], UIA_IsContentElementPropertyId
, &v
, 0);
10368 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
10370 V_VT(&v
) = VT_BOOL
;
10371 V_BOOL(&v
) = VARIANT_TRUE
;
10372 set_property_condition(&prop_cond
[1], UIA_IsControlElementPropertyId
, &v
, 0);
10374 set_provider_prop_override(&Provider_child
, &prop_override
, 1);
10375 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
10377 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
[0], TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10378 AutomationElementMode_Full
);
10379 set_find_params(&find_params
, 1, FALSE
, TRUE
, (struct UiaCondition
*)&prop_cond
[1]);
10380 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10381 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10382 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10384 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child2", TRUE
);
10385 exp_lbound
[0] = exp_lbound
[1] = 0;
10389 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10391 for (i
= 0; i
< exp_elems
[0]; i
++)
10394 exp_tree_struct
[i
] = L
"P)";
10396 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10398 ok_method_sequence(find_seq10
, "find_seq10");
10400 SafeArrayDestroy(out_req
);
10401 SafeArrayDestroy(offsets
);
10402 SafeArrayDestroy(tree_structs
);
10404 initialize_provider_tree(FALSE
);
10405 for (i
= 0; i
< ARRAY_SIZE(exp_node_desc
); i
++)
10406 init_node_provider_desc(&exp_node_desc
[i
], GetCurrentProcessId(), NULL
);
10409 * Maximum find depth of -1, find first is TRUE, exclude root is FALSE.
10410 * Provider_child_child2 is the only element in the tree to match our
10413 V_VT(&v
) = VT_BOOL
;
10414 V_BOOL(&v
) = VARIANT_FALSE
;
10415 set_property_condition(&prop_cond
[0], UIA_IsContentElementPropertyId
, &v
, 0);
10416 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
10418 V_VT(&v
) = VT_BOOL
;
10419 V_BOOL(&v
) = VARIANT_TRUE
;
10420 set_property_condition(&prop_cond
[1], UIA_IsControlElementPropertyId
, &v
, 0);
10422 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
10424 set_cache_request(&cache_req
, (struct UiaCondition
*)&prop_cond
[0], TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
10425 AutomationElementMode_Full
);
10426 set_find_params(&find_params
, -1, TRUE
, FALSE
, (struct UiaCondition
*)&prop_cond
[1]);
10427 hr
= UiaFind(node
, &find_params
, &cache_req
, &out_req
, &offsets
, &tree_structs
);
10428 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10429 ok(Provider_child_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
10431 add_provider_desc(&exp_node_desc
[0], L
"Main", L
"Provider_child_child2", TRUE
);
10432 exp_lbound
[0] = exp_lbound
[1] = 0;
10436 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10438 for (i
= 0; i
< exp_elems
[0]; i
++)
10441 exp_tree_struct
[i
] = L
"P)";
10443 test_find_sa_results(tree_structs
, offsets
, exp_elems
[0], exp_tree_struct
, exp_offset
);
10444 ok_method_sequence(find_seq11
, "find_seq11");
10446 SafeArrayDestroy(out_req
);
10447 SafeArrayDestroy(offsets
);
10448 SafeArrayDestroy(tree_structs
);
10450 initialize_provider_tree(TRUE
);
10452 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
10453 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
10458 static HWND
create_test_hwnd(const char *class_name
)
10460 WNDCLASSA cls
= { 0 };
10462 cls
.lpfnWndProc
= test_wnd_proc
;
10463 cls
.hInstance
= GetModuleHandleA(NULL
);
10464 cls
.lpszClassName
= class_name
;
10465 RegisterClassA(&cls
);
10467 return CreateWindowA(class_name
, "Test window", WS_OVERLAPPEDWINDOW
,
10468 0, 0, 100, 100, NULL
, NULL
, NULL
, NULL
);
10471 static HWND
create_child_test_hwnd(const char *class_name
, HWND parent
)
10473 WNDCLASSA cls
= { 0 };
10475 cls
.lpfnWndProc
= child_test_wnd_proc
;
10476 cls
.hInstance
= GetModuleHandleA(NULL
);
10477 cls
.lpszClassName
= class_name
;
10478 RegisterClassA(&cls
);
10480 return CreateWindowA(class_name
, "Test child window", WS_CHILD
,
10481 0, 0, 50, 50, parent
, NULL
, NULL
, NULL
);
10484 static IUIAutomationElement
*create_test_element_from_hwnd(IUIAutomation
*uia_iface
, HWND hwnd
, BOOL block_hwnd_provs
)
10486 IUIAutomationElement
*element
;
10490 if (block_hwnd_provs
)
10492 SET_EXPECT(prov_callback_base_hwnd
);
10493 SET_EXPECT(prov_callback_nonclient
);
10494 base_hwnd_prov
= proxy_prov
= parent_proxy_prov
= nc_prov
= NULL
;
10495 UiaRegisterProviderCallback(test_uia_provider_callback
);
10498 UiaRegisterProviderCallback(NULL
);
10500 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, hwnd
, TRUE
);
10501 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
10502 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
10503 /* Only sent on Win7. */
10504 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
10505 hr
= IUIAutomation_ElementFromHandle(uia_iface
, hwnd
, &element
);
10506 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10507 ok(!!element
, "element == NULL\n");
10508 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
10509 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
10510 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
10511 if (block_hwnd_provs
)
10513 CHECK_CALLED(prov_callback_base_hwnd
);
10514 CHECK_CALLED(prov_callback_nonclient
);
10517 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
10518 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10520 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
10521 if (!block_hwnd_provs
)
10523 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
10524 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
10525 check_node_provider_desc_todo(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
10528 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
10531 ok_method_sequence(node_from_hwnd2
, "create_test_element");
10532 UiaRegisterProviderCallback(NULL
);
10537 static void test_ElementFromHandle(IUIAutomation
*uia_iface
, BOOL is_cui8
)
10539 HWND hwnd
= create_test_hwnd("test_ElementFromHandle class");
10540 IUIAutomationElement2
*element_2
;
10541 IUIAutomationElement
*element
;
10544 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, FALSE
);
10545 hr
= IUIAutomationElement_QueryInterface(element
, &IID_IUIAutomationElement2
, (void **)&element_2
);
10548 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10549 ok(!!element_2
, "element_2 == NULL\n");
10550 IUIAutomationElement2_Release(element_2
);
10553 ok(hr
== E_NOINTERFACE
, "Unexpected hr %#lx.\n", hr
);
10555 IUIAutomationElement_Release(element
);
10556 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
10558 DestroyWindow(hwnd
);
10559 UnregisterClassA("test_ElementFromHandle class", NULL
);
10563 static void test_Element_GetPropertyValue(IUIAutomation
*uia_iface
)
10565 HWND hwnd
= create_test_hwnd("test_Element_GetPropertyValue class");
10566 const struct uia_element_property
*elem_prop
;
10567 struct Provider_prop_override prop_override
;
10568 IUIAutomationElement
*element
, *element2
;
10569 IUIAutomationElementArray
*element_arr
;
10570 int i
, len
, prop_id
, tmp_int
;
10571 struct UiaRect uia_rect
;
10578 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, TRUE
);
10579 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
10580 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
10581 provider_add_child(&Provider
, &Provider_child
);
10583 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
10584 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10586 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_ControlTypePropertyId
, TRUE
, NULL
);
10587 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
10590 V_VT(&v
) = VT_BOOL
;
10591 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, 1, TRUE
, &v
);
10592 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10593 ok(V_VT(&v
) == VT_EMPTY
, "Unexpected vt %d\n", V_VT(&v
));
10595 for (i
= 0; i
< ARRAY_SIZE(element_properties
); i
++)
10597 elem_prop
= &element_properties
[i
];
10599 Provider
.ret_invalid_prop_type
= FALSE
;
10601 if (!(prop_id
= UiaLookupId(AutomationIdentifierType_Property
, elem_prop
->prop_guid
)))
10603 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop
->prop_guid
));
10607 winetest_push_context("Element prop_id %d", prop_id
);
10608 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, prop_id
, TRUE
, &v
);
10609 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10610 check_uia_prop_val(prop_id
, elem_prop
->type
, &v
, TRUE
);
10613 * Some properties have special behavior if an invalid value is
10614 * returned, skip them here.
10616 if (!elem_prop
->skip_invalid
)
10618 Provider
.ret_invalid_prop_type
= TRUE
;
10619 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, prop_id
, TRUE
, &v
);
10620 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10623 ok_method_sequence(get_prop_invalid_type_seq
, NULL
);
10624 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
10625 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
10630 winetest_pop_context();
10633 /* Test IUIAutomationElementArray interface behavior. */
10634 Provider
.ret_invalid_prop_type
= FALSE
;
10635 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_ControllerForPropertyId
, TRUE
, &v
);
10636 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10637 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
10638 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10639 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10641 element_arr
= NULL
;
10642 hr
= IUnknown_QueryInterface(V_UNKNOWN(&v
), &IID_IUIAutomationElementArray
, (void **)&element_arr
);
10643 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10644 ok(!!element_arr
, "element_arr == NULL\n");
10647 hr
= IUIAutomationElementArray_get_Length(element_arr
, &len
);
10648 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10649 ok(len
== ARRAY_SIZE(uia_unk_arr_prop_val
), "Unexpected length %d\n", len
);
10651 /* Invalid argument tests. */
10652 hr
= IUIAutomationElementArray_get_Length(element_arr
, NULL
);
10653 ok(hr
== E_POINTER
, "Unexpected hr %#lx\n", hr
);
10655 element2
= (void *)0xdeadbeef;
10656 hr
= IUIAutomationElementArray_GetElement(element_arr
, len
, &element2
);
10657 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx\n", hr
);
10658 /* Pointer isn't cleared. */
10659 ok(!!element2
, "element2 == NULL\n");
10661 hr
= IUIAutomationElementArray_GetElement(element_arr
, -1, &element2
);
10662 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx\n", hr
);
10663 /* Pointer isn't cleared. */
10664 ok(!!element2
, "element2 == NULL\n");
10666 hr
= IUIAutomationElementArray_GetElement(element_arr
, 0, NULL
);
10667 ok(hr
== E_POINTER
, "Unexpected hr %#lx\n", hr
);
10669 for (i
= 0; i
< len
; i
++)
10672 hr
= IUIAutomationElementArray_GetElement(element_arr
, i
, &element2
);
10673 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
10674 ok(!!element2
, "element2 == NULL\n");
10676 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element2
, UIA_ControlTypePropertyId
, TRUE
, &v
);
10677 ok(hr
== S_OK
, "element[%d] Unexpected hr %#lx\n", i
, hr
);
10678 ok(V_VT(&v
) == VT_I4
, "element[%d] Unexpected VT %d\n", i
, V_VT(&v
));
10679 ok(V_I4(&v
) == uia_i4_prop_val
, "element[%d] Unexpected I4 %#lx\n", i
, V_I4(&v
));
10681 IUIAutomationElement_Release(element2
);
10685 IUIAutomationElementArray_Release(element_arr
);
10686 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10687 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
10688 ok_method_sequence(get_elem_arr_prop_seq
, NULL
);
10691 * IUIAutomationElement_get_CurrentControlType tests. If the value
10692 * returned for UIA_ControlTypePropertyId is not a registered control
10693 * type ID, we'll get back UIA_CustomControlTypeId.
10695 tmp_int
= 0xdeadb33f;
10696 hr
= IUIAutomationElement_get_CurrentControlType(element
, &tmp_int
);
10697 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10700 * Win10v1507 and below don't check whether or not the returned control
10701 * type ID is valid.
10703 ok(tmp_int
== UIA_CustomControlTypeId
|| broken(tmp_int
== 0xdeadbeef), "Unexpected control type %#x\n", tmp_int
);
10704 ok_method_sequence(get_prop_seq
, NULL
);
10706 Provider
.ret_invalid_prop_type
= TRUE
;
10707 tmp_int
= 0xdeadbeef;
10708 hr
= IUIAutomationElement_get_CurrentControlType(element
, &tmp_int
);
10709 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10710 ok(tmp_int
== UIA_CustomControlTypeId
, "Unexpected control type %#x\n", tmp_int
);
10711 Provider
.ret_invalid_prop_type
= FALSE
;
10712 ok_method_sequence(get_prop_invalid_type_seq
, NULL
);
10714 /* Finally, a valid control type. */
10716 V_I4(&v
) = UIA_HyperlinkControlTypeId
;
10717 set_property_override(&prop_override
, UIA_ControlTypePropertyId
, &v
);
10718 set_provider_prop_override(&Provider
, &prop_override
, 1);
10719 hr
= IUIAutomationElement_get_CurrentControlType(element
, &tmp_int
);
10720 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10721 ok(tmp_int
== UIA_HyperlinkControlTypeId
, "Unexpected control type %#x\n", tmp_int
);
10722 set_provider_prop_override(&Provider
, NULL
, 0);
10723 ok_method_sequence(get_prop_seq
, NULL
);
10726 * IUIAutomationElement_get_CurrentName tests.
10729 hr
= IUIAutomationElement_get_CurrentName(element
, &tmp_bstr
);
10730 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10731 ok(!lstrcmpW(tmp_bstr
, uia_bstr_prop_str
), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr
));
10732 SysFreeString(tmp_bstr
);
10733 ok_method_sequence(get_prop_seq
, NULL
);
10736 Provider
.ret_invalid_prop_type
= TRUE
;
10737 hr
= IUIAutomationElement_get_CurrentName(element
, &tmp_bstr
);
10738 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10739 ok(!lstrcmpW(tmp_bstr
, L
""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr
));
10740 SysFreeString(tmp_bstr
);
10741 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
10742 ok_method_sequence(get_prop_invalid_type_seq
, NULL
);
10745 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
10746 * It's the only version with this behavior.
10748 if (!UiaLookupId(AutomationIdentifierType_Property
, &OptimizeForVisualContent_Property_GUID
))
10750 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
10755 * IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests.
10757 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_LabeledByPropertyId
, TRUE
, &v
);
10758 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10759 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
10760 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
10762 hr
= IUnknown_QueryInterface(V_UNKNOWN(&v
), &IID_IUIAutomationElement
, (void **)&element2
);
10763 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10764 ok(!!element2
, "element2 == NULL\n");
10767 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
10768 set_uia_rect(&uia_rect
, 0, 0, 50, 50);
10769 Provider_child
.bounds_rect
= uia_rect
;
10770 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element2
, UIA_BoundingRectanglePropertyId
, TRUE
, &v
);
10771 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10772 check_uia_rect_val(&v
, &uia_rect
);
10774 ok_method_sequence(get_bounding_rect_seq2
, "get_bounding_rect_seq2");
10776 hr
= IUIAutomationElement_get_CurrentBoundingRectangle(element2
, &rect
);
10777 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10778 check_uia_rect_rect_val(&rect
, &uia_rect
);
10779 memset(&rect
, 0, sizeof(rect
));
10780 ok_method_sequence(get_bounding_rect_seq3
, "get_bounding_rect_seq3");
10782 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
10783 set_uia_rect(&uia_rect
, 0, 0, 0, 0);
10784 Provider_child
.bounds_rect
= uia_rect
;
10785 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element2
, UIA_BoundingRectanglePropertyId
, TRUE
, &v
);
10786 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10787 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
10788 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
10790 ok_method_sequence(get_empty_bounding_rect_seq
, "get_empty_bounding_rect_seq");
10792 /* Returns an all 0 rect. */
10793 hr
= IUIAutomationElement_get_CurrentBoundingRectangle(element2
, &rect
);
10794 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10795 check_uia_rect_rect_val(&rect
, &uia_rect
);
10796 ok_method_sequence(get_empty_bounding_rect_seq
, "get_empty_bounding_rect_seq");
10798 IUIAutomationElement_Release(element2
);
10799 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
10800 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
10803 IUIAutomationElement_Release(element
);
10804 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
10806 DestroyWindow(hwnd
);
10807 UnregisterClassA("test_Element_GetPropertyValue class", NULL
);
10810 static void test_CUIAutomation_value_conversion(IUIAutomation
*uia_iface
)
10812 static const VARTYPE invalid_int_vts
[] = { VT_I8
, VT_INT
};
10813 int in_arr
[3] = { 0xdeadbeef, 0xfeedbeef, 0x1337b33f };
10814 int *out_arr
, out_arr_count
, i
;
10815 LONG lbound
, ubound
;
10822 * Conversion from VT_I4 SAFEARRAY to native int array.
10824 for (i
= 0; i
< ARRAY_SIZE(invalid_int_vts
); i
++)
10826 vt
= invalid_int_vts
[i
];
10827 sa
= SafeArrayCreateVector(vt
, 0, 2);
10828 ok(!!sa
, "sa == NULL\n");
10830 out_arr_count
= 0xdeadbeef;
10831 out_arr
= (int *)0xdeadbeef;
10832 hr
= IUIAutomation_IntSafeArrayToNativeArray(uia_iface
, sa
, &out_arr
, &out_arr_count
);
10833 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10834 ok(!out_arr
, "out_arr != NULL\n");
10835 ok(out_arr_count
== 0xdeadbeef, "Unexpected out_arr_count %#x\n", out_arr_count
);
10836 SafeArrayDestroy(sa
);
10839 /* Only accepts VT_I4 as an input array type. */
10840 sa
= create_i4_safearray();
10841 hr
= IUIAutomation_IntSafeArrayToNativeArray(uia_iface
, sa
, &out_arr
, &out_arr_count
);
10842 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10843 ok(out_arr_count
== ARRAY_SIZE(uia_i4_arr_prop_val
), "Unexpected out_arr_count %#x\n", out_arr_count
);
10844 for (i
= 0; i
< ARRAY_SIZE(uia_i4_arr_prop_val
); i
++)
10845 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
]);
10847 SafeArrayDestroy(sa
);
10848 CoTaskMemFree(out_arr
);
10851 * Conversion from native int array to VT_I4 SAFEARRAY.
10854 hr
= IUIAutomation_IntNativeArrayToSafeArray(uia_iface
, in_arr
, ARRAY_SIZE(in_arr
), &sa
);
10855 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10857 hr
= SafeArrayGetVartype(sa
, &vt
);
10858 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10859 ok(vt
== VT_I4
, "Unexpected vt %d.\n", vt
);
10861 dims
= SafeArrayGetDim(sa
);
10862 ok(dims
== 1, "Unexpected array dims %d\n", dims
);
10864 hr
= SafeArrayGetLBound(sa
, 1, &lbound
);
10865 ok(hr
== S_OK
, "Failed to get LBound with hr %#lx\n", hr
);
10866 ok(lbound
== 0, "Unexpected LBound %#lx\n", lbound
);
10868 hr
= SafeArrayGetUBound(sa
, 1, &ubound
);
10869 ok(hr
== S_OK
, "Failed to get UBound with hr %#lx\n", hr
);
10870 ok(((ubound
- lbound
) + 1) == ARRAY_SIZE(in_arr
), "Unexpected array size %#lx\n", ((ubound
- lbound
) + 1));
10872 for (i
= 0; i
< ARRAY_SIZE(in_arr
); i
++)
10874 LONG idx
= lbound
+ i
;
10877 hr
= SafeArrayGetElement(sa
, &idx
, &tmp_val
);
10878 ok(hr
== S_OK
, "Failed to get element at idx %ld, hr %#lx\n", idx
, hr
);
10879 ok(tmp_val
== in_arr
[i
], "Expected %d at idx %d, got %d\n", in_arr
[i
], i
, tmp_val
);
10882 SafeArrayDestroy(sa
);
10885 static HRESULT WINAPI
Object_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
10888 if (IsEqualIID(riid
, &IID_IUnknown
))
10891 return E_NOINTERFACE
;
10896 static ULONG WINAPI
Object_AddRef(IUnknown
*iface
)
10901 static ULONG WINAPI
Object_Release(IUnknown
*iface
)
10906 static IUnknownVtbl ObjectVtbl
= {
10907 Object_QueryInterface
,
10911 static IUnknown Object
= {&ObjectVtbl
};
10913 static void test_CUIAutomation_condition_ifaces(IUIAutomation
*uia_iface
)
10915 IUIAutomationPropertyCondition
*prop_cond
, *prop_cond2
;
10916 IUIAutomationCondition
*cond
, **cond_arr
;
10917 enum PropertyConditionFlags prop_flags
;
10918 IUIAutomationBoolCondition
*bool_cond
;
10919 IUIAutomationNotCondition
*not_cond
;
10920 IUIAutomationOrCondition
*or_cond
;
10921 PROPERTYID prop_id
;
10928 hr
= IUIAutomation_CreateTrueCondition(uia_iface
, NULL
);
10929 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
10932 hr
= IUIAutomation_CreateTrueCondition(uia_iface
, &cond
);
10933 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10934 ok(!!cond
, "cond == NULL\n");
10936 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationBoolCondition
, (void **)&bool_cond
);
10937 IUIAutomationCondition_Release(cond
);
10938 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10939 ok(!!bool_cond
, "bool_cond == NULL\n");
10941 hr
= IUIAutomationBoolCondition_get_BooleanValue(bool_cond
, NULL
);
10942 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
10945 hr
= IUIAutomationBoolCondition_get_BooleanValue(bool_cond
, &tmp_b
);
10946 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10947 ok(tmp_b
== TRUE
, "tmp_b != TRUE\n");
10948 IUIAutomationBoolCondition_Release(bool_cond
);
10950 hr
= IUIAutomation_CreateFalseCondition(uia_iface
, NULL
);
10951 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
10954 hr
= IUIAutomation_CreateFalseCondition(uia_iface
, &cond
);
10955 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10956 ok(!!cond
, "cond == NULL\n");
10958 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationBoolCondition
, (void **)&bool_cond
);
10959 IUIAutomationCondition_Release(cond
);
10960 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10961 ok(!!bool_cond
, "bool_cond == NULL\n");
10963 hr
= IUIAutomationBoolCondition_get_BooleanValue(bool_cond
, NULL
);
10964 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
10967 hr
= IUIAutomationBoolCondition_get_BooleanValue(bool_cond
, &tmp_b
);
10968 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10969 ok(tmp_b
== FALSE
, "tmp_b != FALSE\n");
10970 IUIAutomationBoolCondition_Release(bool_cond
);
10973 * IUIAutomationPropertyCondition tests.
10975 cond
= (void *)0xdeadbeef;
10977 /* Invalid property ID. */
10978 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, 0, v
, &cond
);
10979 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10980 ok(!cond
, "cond != NULL\n");
10982 /* Invalid variant type for property ID. */
10983 cond
= (void *)0xdeadbeef;
10985 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_RuntimeIdPropertyId
, v
, &cond
);
10986 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
10987 ok(!cond
, "cond != NULL\n");
10989 /* NULL Condition argument. */
10990 V_VT(&v
) = VT_I4
| VT_ARRAY
;
10991 V_ARRAY(&v
) = create_i4_safearray();
10992 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_RuntimeIdPropertyId
, v
, NULL
);
10993 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
10995 /* Finally, create property condition interface. */
10997 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_RuntimeIdPropertyId
, v
, &cond
);
10998 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
10999 ok(!!cond
, "cond == NULL\n");
11001 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationPropertyCondition
, (void **)&prop_cond
);
11002 IUIAutomationCondition_Release(cond
);
11003 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11004 ok(!!prop_cond
, "prop_cond == NULL\n");
11006 hr
= IUIAutomationPropertyCondition_get_PropertyId(prop_cond
, NULL
);
11007 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11009 hr
= IUIAutomationPropertyCondition_get_PropertyId(prop_cond
, &prop_id
);
11010 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11011 ok(prop_id
== UIA_RuntimeIdPropertyId
, "Unexpected prop_id %d.\n", prop_id
);
11013 hr
= IUIAutomationPropertyCondition_get_PropertyValue(prop_cond
, NULL
);
11014 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11017 hr
= IUIAutomationPropertyCondition_get_PropertyValue(prop_cond
, &v
);
11018 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11019 ok(V_VT(&v
) == (VT_I4
| VT_ARRAY
), "Unexpected vt %d.\n", V_VT(&v
));
11020 ok(!!V_ARRAY(&v
), "V_ARRAY(&v) == NULL\n");
11023 hr
= IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond
, NULL
);
11024 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11026 hr
= IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond
, &prop_flags
);
11027 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11028 ok(prop_flags
== PropertyConditionFlags_None
, "Unexpected flags %#x.\n", prop_flags
);
11031 * IUIAutomationNotCondition tests.
11033 cond
= (void *)0xdeadbeef;
11036 * Passing in an interface that isn't a valid IUIAutomationCondition
11039 hr
= IUIAutomation_CreateNotCondition(uia_iface
, (IUIAutomationCondition
*)&Object
, &cond
);
11040 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
11041 ok(!cond
, "cond != NULL\n");
11043 /* NULL input argument tests. */
11044 cond
= (void *)0xdeadbeef;
11045 hr
= IUIAutomation_CreateNotCondition(uia_iface
, NULL
, &cond
);
11046 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11047 ok(!cond
, "cond != NULL\n");
11049 hr
= IUIAutomation_CreateNotCondition(uia_iface
, (IUIAutomationCondition
*)prop_cond
, NULL
);
11050 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11052 /* Create the IUIAutomationNotCondition with our property condition. */
11054 hr
= IUIAutomation_CreateNotCondition(uia_iface
, (IUIAutomationCondition
*)prop_cond
, &cond
);
11055 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11056 ok(!!cond
, "cond == NULL\n");
11058 /* IUIAutomationNotCondition holds a reference to the passed in condition. */
11059 ref
= IUIAutomationPropertyCondition_Release(prop_cond
);
11060 ok(ref
== 1, "Unexpected ref %ld\n", ref
);
11062 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationNotCondition
, (void **)¬_cond
);
11063 IUIAutomationCondition_Release(cond
);
11064 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11065 ok(!!not_cond
, "not_cond == NULL\n");
11067 hr
= IUIAutomationNotCondition_GetChild(not_cond
, NULL
);
11068 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11071 hr
= IUIAutomationNotCondition_GetChild(not_cond
, &cond
);
11072 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11073 ok(iface_cmp((IUnknown
*)cond
, (IUnknown
*)prop_cond
), "cond != prop_cond\n");
11074 IUIAutomationCondition_Release(cond
);
11076 IUIAutomationNotCondition_Release(not_cond
);
11079 * IUIAutomationOrCondition tests.
11083 V_VT(&v
) = VT_BOOL
;
11084 V_BOOL(&v
) = VARIANT_FALSE
;
11085 /* Create two condition interfaces to use for our IUIAutomationOrCondition. */
11086 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_IsControlElementPropertyId
, v
, &cond
);
11087 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11088 ok(!!cond
, "cond == NULL\n");
11090 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationPropertyCondition
, (void **)&prop_cond
);
11091 IUIAutomationCondition_Release(cond
);
11092 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11093 ok(!!prop_cond
, "prop_cond == NULL\n");
11097 V_VT(&v
) = VT_BOOL
;
11098 V_BOOL(&v
) = VARIANT_TRUE
;
11099 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_IsContentElementPropertyId
, v
, &cond
);
11100 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11101 ok(!!cond
, "cond == NULL\n");
11103 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationPropertyCondition
, (void **)&prop_cond2
);
11104 IUIAutomationCondition_Release(cond
);
11105 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11106 ok(!!prop_cond2
, "prop_cond2 == NULL\n");
11108 /* NULL input argument tests. */
11109 hr
= IUIAutomation_CreateOrCondition(uia_iface
, (IUIAutomationCondition
*)prop_cond
,
11110 (IUIAutomationCondition
*)prop_cond2
, NULL
);
11111 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11113 cond
= (void *)0xdeadbeef;
11114 hr
= IUIAutomation_CreateOrCondition(uia_iface
, NULL
, (IUIAutomationCondition
*)prop_cond2
, &cond
);
11115 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11116 ok(!cond
, "cond != NULL\n");
11118 cond
= (void *)0xdeadbeef;
11119 hr
= IUIAutomation_CreateOrCondition(uia_iface
, (IUIAutomationCondition
*)prop_cond
, NULL
, &cond
);
11120 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11121 ok(!cond
, "cond != NULL\n");
11123 /* One of the IUIAutomationCondition interfaces are invalid. */
11124 cond
= (void *)0xdeadbeef;
11125 hr
= IUIAutomation_CreateOrCondition(uia_iface
, (IUIAutomationCondition
*)prop_cond
,
11126 (IUIAutomationCondition
*)&Object
, &cond
);
11127 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
11128 ok(!cond
, "cond != NULL\n");
11131 hr
= IUIAutomation_CreateOrCondition(uia_iface
, (IUIAutomationCondition
*)prop_cond
,
11132 (IUIAutomationCondition
*)prop_cond2
, &cond
);
11133 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11134 ok(!!cond
, "cond == NULL\n");
11137 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationOrCondition
, (void **)&or_cond
);
11138 IUIAutomationCondition_Release(cond
);
11139 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11140 ok(!!or_cond
, "or_cond == NULL\n");
11142 /* References held to both passed in interfaces. */
11143 ref
= IUIAutomationPropertyCondition_Release(prop_cond
);
11144 ok(ref
== 1, "Unexpected ref %ld\n", ref
);
11146 ref
= IUIAutomationPropertyCondition_Release(prop_cond2
);
11147 ok(ref
== 1, "Unexpected ref %ld\n", ref
);
11149 hr
= IUIAutomationOrCondition_get_ChildCount(or_cond
, NULL
);
11150 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11153 hr
= IUIAutomationOrCondition_get_ChildCount(or_cond
, &child_count
);
11154 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11155 ok(child_count
== 2, "Unexpected child_count %d.\n", child_count
);
11158 hr
= IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond
, NULL
, &child_count
);
11159 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11160 ok(child_count
== 10, "Unexpected child_count %d.\n", child_count
);
11162 cond_arr
= (void *)0xdeadbeef;
11163 hr
= IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond
, &cond_arr
, NULL
);
11164 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11165 ok(!cond_arr
, "cond_arr != NULL\n");
11169 hr
= IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond
, &cond_arr
, &child_count
);
11170 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11171 ok(child_count
== 2, "Unexpected child_count %d.\n", child_count
);
11172 ok(!!cond_arr
, "cond_arr == NULL\n");
11174 ok(iface_cmp((IUnknown
*)cond_arr
[0], (IUnknown
*)prop_cond
), "cond_arr[0] != prop_cond\n");
11175 IUIAutomationCondition_Release(cond_arr
[0]);
11177 ok(iface_cmp((IUnknown
*)cond_arr
[1], (IUnknown
*)prop_cond2
), "cond_arr[1] != prop_cond2\n");
11178 IUIAutomationCondition_Release(cond_arr
[1]);
11180 CoTaskMemFree(cond_arr
);
11181 IUIAutomationOrCondition_Release(or_cond
);
11184 * Condition used to get the control TreeView. Equivalent to:
11185 * if (!(UIA_IsControlElementPropertyId == VARIANT_FALSE))
11187 hr
= IUIAutomation_get_ControlViewCondition(uia_iface
, NULL
);
11188 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11191 hr
= IUIAutomation_get_ControlViewCondition(uia_iface
, &cond
);
11192 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11193 ok(!!cond
, "cond == NULL\n");
11195 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationNotCondition
, (void **)¬_cond
);
11196 IUIAutomationCondition_Release(cond
);
11197 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11198 ok(!!not_cond
, "not_cond == NULL\n");
11201 hr
= IUIAutomationNotCondition_GetChild(not_cond
, &cond
);
11202 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11203 ok(!!cond
, "cond == NULL\n");
11205 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationPropertyCondition
, (void **)&prop_cond
);
11206 IUIAutomationCondition_Release(cond
);
11207 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11208 ok(!!prop_cond
, "prop_cond == NULL\n");
11210 hr
= IUIAutomationPropertyCondition_get_PropertyId(prop_cond
, &prop_id
);
11211 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11212 ok(prop_id
== UIA_IsControlElementPropertyId
, "Unexpected prop_id %d.\n", prop_id
);
11215 hr
= IUIAutomationPropertyCondition_get_PropertyValue(prop_cond
, &v
);
11216 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11217 ok(check_variant_bool(&v
, FALSE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
11220 hr
= IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond
, &prop_flags
);
11221 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11222 ok(prop_flags
== PropertyConditionFlags_None
, "Unexpected flags %#x.\n", prop_flags
);
11224 IUIAutomationPropertyCondition_Release(prop_cond
);
11225 IUIAutomationNotCondition_Release(not_cond
);
11228 * Condition used to get the raw TreeView. Equivalent to:
11231 hr
= IUIAutomation_get_RawViewCondition(uia_iface
, NULL
);
11232 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11235 hr
= IUIAutomation_get_RawViewCondition(uia_iface
, &cond
);
11236 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11237 ok(!!cond
, "cond == NULL\n");
11239 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationBoolCondition
, (void **)&bool_cond
);
11240 IUIAutomationCondition_Release(cond
);
11241 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11242 ok(!!bool_cond
, "bool_cond == NULL\n");
11245 hr
= IUIAutomationBoolCondition_get_BooleanValue(bool_cond
, &tmp_b
);
11246 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11247 ok(tmp_b
== TRUE
, "tmp_b != TRUE\n");
11248 IUIAutomationBoolCondition_Release(bool_cond
);
11251 static void test_CUIAutomation_cache_request_iface(IUIAutomation
*uia_iface
)
11253 IUIAutomationPropertyCondition
*prop_cond
;
11254 enum PropertyConditionFlags prop_flags
;
11255 IUIAutomationCacheRequest
*cache_req
;
11256 enum AutomationElementMode elem_mode
;
11257 IUIAutomationCondition
*cond
, *cond2
;
11258 IUIAutomationNotCondition
*not_cond
;
11259 enum TreeScope scope
;
11260 PROPERTYID prop_id
;
11264 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, NULL
);
11265 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11268 * CreateCacheRequest returns an IUIAutomationCacheRequest with the
11269 * default cache request values set.
11272 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, &cache_req
);
11273 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11274 ok(!!cache_req
, "cache_req == NULL\n");
11279 hr
= IUIAutomationCacheRequest_get_TreeScope(cache_req
, NULL
);
11280 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11283 hr
= IUIAutomationCacheRequest_get_TreeScope(cache_req
, &scope
);
11284 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11285 ok(scope
== TreeScope_Element
, "Unexpected scope %#x\n", scope
);
11287 /* Set it to something invalid. */
11288 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, 0);
11289 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11291 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, TreeScope_Parent
);
11292 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11294 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, TreeScope_Ancestors
);
11295 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11297 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, TreeScope_Parent
| TreeScope_Element
);
11298 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11300 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, TreeScope_Ancestors
| TreeScope_Element
);
11301 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11303 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, ~(TreeScope_SubTree
| TreeScope_Parent
| TreeScope_Ancestors
));
11304 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11306 /* Invalid values don't change anything. */
11308 hr
= IUIAutomationCacheRequest_get_TreeScope(cache_req
, &scope
);
11309 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11310 ok(scope
== TreeScope_Element
, "Unexpected scope %#x\n", scope
);
11312 /* Now set it to TreeScope_Children. */
11313 hr
= IUIAutomationCacheRequest_put_TreeScope(cache_req
, TreeScope_Children
);
11314 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11317 hr
= IUIAutomationCacheRequest_get_TreeScope(cache_req
, &scope
);
11318 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11319 todo_wine
ok(scope
== TreeScope_Children
, "Unexpected scope %#x\n", scope
);
11322 * TreeFilter tests.
11325 hr
= IUIAutomationCacheRequest_get_TreeFilter(cache_req
, NULL
);
11326 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11329 hr
= IUIAutomationCacheRequest_put_TreeFilter(cache_req
, NULL
);
11330 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11333 hr
= IUIAutomationCacheRequest_put_TreeFilter(cache_req
, (IUIAutomationCondition
*)&Object
);
11334 ok(hr
== E_FAIL
, "Unexpected hr %#lx.\n", hr
);
11336 /* Default IUIAutomationCacheRequest has the ControlView condition. */
11338 hr
= IUIAutomationCacheRequest_get_TreeFilter(cache_req
, &cond
);
11339 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11340 ok(!!cond
, "cond == NULL\n");
11342 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationNotCondition
, (void **)¬_cond
);
11343 IUIAutomationCondition_Release(cond
);
11344 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11345 ok(!!not_cond
, "not_cond == NULL\n");
11348 hr
= IUIAutomationNotCondition_GetChild(not_cond
, &cond
);
11349 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11350 ok(!!cond
, "cond == NULL\n");
11352 hr
= IUIAutomationCondition_QueryInterface(cond
, &IID_IUIAutomationPropertyCondition
, (void **)&prop_cond
);
11353 IUIAutomationCondition_Release(cond
);
11354 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11355 ok(!!prop_cond
, "prop_cond == NULL\n");
11357 hr
= IUIAutomationPropertyCondition_get_PropertyId(prop_cond
, &prop_id
);
11358 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11359 ok(prop_id
== UIA_IsControlElementPropertyId
, "Unexpected prop_id %d.\n", prop_id
);
11362 hr
= IUIAutomationPropertyCondition_get_PropertyValue(prop_cond
, &v
);
11363 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11364 ok(check_variant_bool(&v
, FALSE
), "Unexpected BOOL %#x\n", V_BOOL(&v
));
11367 hr
= IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond
, &prop_flags
);
11368 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11369 ok(prop_flags
== PropertyConditionFlags_None
, "Unexpected flags %#x.\n", prop_flags
);
11371 IUIAutomationPropertyCondition_Release(prop_cond
);
11372 IUIAutomationNotCondition_Release(not_cond
);
11374 /* Set a new TreeFilter condition. */
11376 hr
= IUIAutomation_CreateTrueCondition(uia_iface
, &cond
);
11377 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11378 ok(!!cond
, "cond == NULL\n");
11380 hr
= IUIAutomationCacheRequest_put_TreeFilter(cache_req
, cond
);
11381 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11383 hr
= IUIAutomationCacheRequest_get_TreeFilter(cache_req
, &cond2
);
11384 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11385 ok(!!cond2
, "cond2 == NULL\n");
11386 ok(iface_cmp((IUnknown
*)cond
, (IUnknown
*)cond2
), "cond != cond2\n");
11387 IUIAutomationCondition_Release(cond
);
11388 IUIAutomationCondition_Release(cond2
);
11391 * AutomationElementMode tests.
11393 hr
= IUIAutomationCacheRequest_get_AutomationElementMode(cache_req
, NULL
);
11394 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11397 hr
= IUIAutomationCacheRequest_get_AutomationElementMode(cache_req
, &elem_mode
);
11398 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11399 ok(elem_mode
== AutomationElementMode_Full
, "Unexpected element mode %#x\n", elem_mode
);
11401 /* Invalid value - maximum is AutomationElementMode_Full, 0x01. */
11402 hr
= IUIAutomationCacheRequest_put_AutomationElementMode(cache_req
, 0x02);
11403 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11405 hr
= IUIAutomationCacheRequest_put_AutomationElementMode(cache_req
, AutomationElementMode_None
);
11406 todo_wine
ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11409 hr
= IUIAutomationCacheRequest_get_AutomationElementMode(cache_req
, &elem_mode
);
11410 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11411 todo_wine
ok(elem_mode
== AutomationElementMode_None
, "Unexpected element mode %#x\n", elem_mode
);
11414 * AddProperty tests.
11416 hr
= IUIAutomationCacheRequest_AddProperty(cache_req
, UIA_IsContentElementPropertyId
);
11417 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11419 /* Invalid property ID. */
11420 hr
= IUIAutomationCacheRequest_AddProperty(cache_req
, 1);
11421 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11423 IUIAutomationCacheRequest_Release(cache_req
);
11426 static const struct prov_method_sequence get_elem_cache_seq
[] = {
11427 { &Provider
, PROV_GET_PROPERTY_VALUE
},
11428 NODE_CREATE_SEQ(&Provider_child
),
11432 static const struct prov_method_sequence get_cached_prop_val_seq
[] = {
11433 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
11437 static const struct prov_method_sequence get_cached_prop_val_seq2
[] = {
11438 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
11439 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11443 static const struct prov_method_sequence get_cached_prop_val_seq3
[] = {
11444 { &Provider
, PROV_GET_PROPERTY_VALUE
},
11445 NODE_CREATE_SEQ(&Provider_child
),
11446 { &Provider
, PROV_GET_PROPERTY_VALUE
},
11447 NODE_CREATE_SEQ(&Provider_child
),
11448 NODE_CREATE_SEQ(&Provider_child2
),
11449 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11450 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
11451 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ControlTypePropertyId */
11455 static void test_Element_cache_methods(IUIAutomation
*uia_iface
)
11457 HWND hwnd
= create_test_hwnd("test_Element_cache_methods class");
11458 IUIAutomationElement
*element
, *element2
, *element3
;
11459 IUIAutomationCacheRequest
*cache_req
;
11460 IUIAutomationElementArray
*elem_arr
;
11461 int tmp_rt_id
[2], i
, len
;
11466 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, TRUE
);
11467 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
11468 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
11469 provider_add_child(&Provider
, &Provider_child
);
11471 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
11472 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11475 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, &cache_req
);
11476 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11477 ok(!!cache_req
, "cache_req == NULL\n");
11480 * Run these tests on Provider_child, it doesn't have an HWND so it will
11481 * get UIA_RuntimeIdPropertyId from GetRuntimeId.
11483 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_LabeledByPropertyId
, TRUE
, &v
);
11484 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11485 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
11486 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
11487 ok_method_sequence(get_elem_cache_seq
, "get_elem_cache_seq");
11489 IUIAutomationElement_Release(element
);
11490 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
11492 hr
= IUnknown_QueryInterface(V_UNKNOWN(&v
), &IID_IUIAutomationElement
, (void **)&element
);
11493 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11494 ok(!!element
, "element == NULL\n");
11498 * Passing in an invalid COM interface for IUIAutomationCacheRequest will
11499 * cause an access violation on Windows.
11503 IUIAutomationElement_BuildUpdatedCache(element
, (IUIAutomationCacheRequest
*)&Object
, &element2
);
11506 hr
= IUIAutomationElement_BuildUpdatedCache(element
, cache_req
, NULL
);
11507 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11509 element2
= (void *)0xdeadbeef;
11510 hr
= IUIAutomationElement_BuildUpdatedCache(element
, NULL
, &element2
);
11511 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
11512 ok(!element2
, "element2 != NULL\n");
11515 * Test cached property values. The default IUIAutomationCacheRequest
11516 * always caches UIA_RuntimeIdPropertyId.
11519 hr
= IUIAutomationElement_BuildUpdatedCache(element
, cache_req
, &element2
);
11520 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11521 ok(!!element2
, "element2 == NULL\n");
11522 ok_method_sequence(get_cached_prop_val_seq
, "get_cached_prop_val_seq");
11524 /* RuntimeId is currently unset, so we'll get the NotSupported value. */
11525 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_RuntimeIdPropertyId
, TRUE
, &v
);
11526 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11527 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
11528 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
11531 /* Attempting to get a cached value for a non-cached property. */
11532 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_IsControlElementPropertyId
, TRUE
, &v
);
11533 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
11534 ok(V_VT(&v
) == VT_EMPTY
, "Unexpected vt %d\n", V_VT(&v
));
11537 IUIAutomationElement_Release(element2
);
11539 /* RuntimeId is now set. */
11540 Provider_child
.runtime_id
[0] = Provider_child
.runtime_id
[1] = 0xdeadbeef;
11542 hr
= IUIAutomationElement_BuildUpdatedCache(element
, cache_req
, &element2
);
11543 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11544 ok(!!element2
, "element2 == NULL\n");
11545 ok_method_sequence(get_cached_prop_val_seq
, "get_cached_prop_val_seq");
11547 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_RuntimeIdPropertyId
, TRUE
, &v
);
11548 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11549 ok(V_VT(&v
) == (VT_I4
| VT_ARRAY
), "Unexpected vt %d\n", V_VT(&v
));
11550 check_runtime_id(Provider_child
.runtime_id
, ARRAY_SIZE(Provider_child
.runtime_id
), V_ARRAY(&v
));
11552 IUIAutomationElement_Release(element2
);
11555 * Add UIA_IsControlElementPropertyId to the list of cached property
11558 hr
= IUIAutomationCacheRequest_AddProperty(cache_req
, UIA_IsControlElementPropertyId
);
11559 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11561 Provider_child
.runtime_id
[0] = Provider_child
.runtime_id
[1] = 0xdeadb33f;
11563 hr
= IUIAutomationElement_BuildUpdatedCache(element
, cache_req
, &element2
);
11564 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11565 ok(!!element2
, "element2 == NULL\n");
11566 ok_method_sequence(get_cached_prop_val_seq2
, "get_cached_prop_val_seq2");
11568 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_RuntimeIdPropertyId
, TRUE
, &v
);
11569 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11570 ok(V_VT(&v
) == (VT_I4
| VT_ARRAY
), "Unexpected vt %d\n", V_VT(&v
));
11571 check_runtime_id(Provider_child
.runtime_id
, ARRAY_SIZE(Provider_child
.runtime_id
), V_ARRAY(&v
));
11574 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_IsControlElementPropertyId
, TRUE
, &v
);
11575 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11576 ok(check_variant_bool(&v
, TRUE
), "V_BOOL(&v) = %#x\n", V_BOOL(&v
));
11579 IUIAutomationElement_Release(element2
);
11580 IUIAutomationCacheRequest_Release(cache_req
);
11582 IUIAutomationElement_Release(element
);
11583 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
11585 /* Test cached UIAutomationType_Element properties. */
11586 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, TRUE
);
11589 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, &cache_req
);
11590 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11591 ok(!!cache_req
, "cache_req == NULL\n");
11593 /* UIAutomationType_Element property. */
11594 hr
= IUIAutomationCacheRequest_AddProperty(cache_req
, UIA_LabeledByPropertyId
);
11595 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11597 /* UIAutomationType_ElementArray property. */
11598 hr
= IUIAutomationCacheRequest_AddProperty(cache_req
, UIA_ControllerForPropertyId
);
11599 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11602 hr
= IUIAutomationElement_BuildUpdatedCache(element
, cache_req
, &element2
);
11603 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11604 ok(!!element2
, "element2 == NULL\n");
11605 ok(Provider_child
.ref
== 3, "Unexpected refcnt %ld\n", Provider_child
.ref
);
11606 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
11608 tmp_rt_id
[0] = UIA_RUNTIME_ID_PREFIX
;
11609 tmp_rt_id
[1] = HandleToULong(hwnd
);
11610 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_RuntimeIdPropertyId
, TRUE
, &v
);
11611 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11612 ok(V_VT(&v
) == (VT_I4
| VT_ARRAY
), "Unexpected vt %d\n", V_VT(&v
));
11613 check_runtime_id(tmp_rt_id
, ARRAY_SIZE(tmp_rt_id
), V_ARRAY(&v
));
11616 /* Cached IUIAutomationElement. */
11617 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_LabeledByPropertyId
, TRUE
, &v
);
11618 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11619 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
11622 hr
= IUnknown_QueryInterface(V_UNKNOWN(&v
), &IID_IUIAutomationElement
, (void **)&element3
);
11623 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11624 ok(!!element3
, "element3 == NULL\n");
11627 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element3
, UIA_IsControlElementPropertyId
, TRUE
, &v
);
11628 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11629 ok(check_variant_bool(&v
, TRUE
), "V_BOOL(&v) = %#x\n", V_BOOL(&v
));
11630 IUIAutomationElement_Release(element3
);
11633 /* Cached IUIAutomationElementArray. */
11634 hr
= IUIAutomationElement_GetCachedPropertyValueEx(element2
, UIA_ControllerForPropertyId
, TRUE
, &v
);
11635 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11636 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
11638 hr
= IUnknown_QueryInterface(V_UNKNOWN(&v
), &IID_IUIAutomationElementArray
, (void **)&elem_arr
);
11639 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
11640 ok(!!elem_arr
, "elem_arr == NULL\n");
11643 hr
= IUIAutomationElementArray_get_Length(elem_arr
, &len
);
11644 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
11645 ok(len
== ARRAY_SIZE(uia_unk_arr_prop_val
), "Unexpected length %d\n", len
);
11647 for (i
= 0; i
< ARRAY_SIZE(uia_unk_arr_prop_val
); i
++)
11649 hr
= IUIAutomationElementArray_GetElement(elem_arr
, i
, &element3
);
11650 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
11651 ok(!!element3
, "element3 == NULL\n");
11653 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element3
, UIA_ControlTypePropertyId
, TRUE
, &v
);
11654 ok(hr
== S_OK
, "elem[%d] Unexpected hr %#lx\n", i
, hr
);
11655 ok(V_VT(&v
) == VT_I4
, "elem[%d] Unexpected VT %d\n", i
, V_VT(&v
));
11656 ok(V_I4(&v
) == uia_i4_prop_val
, "elem[%d] Unexpected I4 %#lx\n", i
, V_I4(&v
));
11658 IUIAutomationElement_Release(element3
);
11662 IUIAutomationElementArray_Release(elem_arr
);
11663 IUIAutomationCacheRequest_Release(cache_req
);
11666 * Reference isn't released until the element holding the cache is
11669 ok(Provider_child
.ref
== 3, "Unexpected refcnt %ld\n", Provider_child
.ref
);
11670 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
11672 IUIAutomationElement_Release(element2
);
11673 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
11674 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
11675 ok_method_sequence(get_cached_prop_val_seq3
, "get_cached_prop_val_seq3");
11677 IUIAutomationElement_Release(element
);
11678 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
11679 IUnknown_Release(unk_ns
);
11681 DestroyWindow(hwnd
);
11682 UnregisterClassA("test_Element_cache_methods class", NULL
);
11685 static const struct prov_method_sequence element_find_start_seq
[] = {
11686 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_LabeledByPropertyId */
11687 NODE_CREATE_SEQ(&Provider
),
11692 * Identical to find_seq7, except default cache request used by FindAll
11693 * doesn't cache UIA_RuntimeIdPropertyId.
11695 static const struct prov_method_sequence element_find_seq1
[] = {
11696 { &Provider
, FRAG_GET_RUNTIME_ID
},
11697 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11698 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11699 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
11700 NODE_CREATE_SEQ(&Provider_child
),
11701 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11702 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
11703 NODE_CREATE_SEQ(&Provider_child_child
),
11704 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11705 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11706 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
11707 NODE_CREATE_SEQ(&Provider_child_child2
),
11708 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11709 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11710 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
11711 { &Provider_child_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
11712 NODE_CREATE_SEQ(&Provider_child
),
11713 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
11714 NODE_CREATE_SEQ(&Provider_child2
),
11715 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11716 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11717 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
11718 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
11719 NODE_CREATE_SEQ(&Provider
),
11720 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
11721 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
11722 /* Only done on Win10v1507 and below. */
11723 { &Provider
, FRAG_NAVIGATE
, METHOD_OPTIONAL
}, /* NavigateDirection_Parent */
11724 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
11725 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
11726 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
11727 { &Provider_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
11732 * Identical to find_seq11, except default cache request used by FindFirst
11733 * doesn't cache UIA_RuntimeIdPropertyId.
11735 static const struct prov_method_sequence element_find_seq2
[] = {
11736 { &Provider
, FRAG_GET_RUNTIME_ID
},
11737 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11738 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
11739 NODE_CREATE_SEQ(&Provider_child
),
11740 { &Provider_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11741 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
11742 NODE_CREATE_SEQ(&Provider_child_child
),
11743 { &Provider_child_child
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11744 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
11745 { &Provider_child_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
11746 NODE_CREATE_SEQ(&Provider_child_child2
),
11747 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsContentElementPropertyId */
11748 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_IsControlElementPropertyId */
11749 { &Provider_child_child2
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId */
11753 struct exp_elem_desc
{
11754 struct Provider
*elem_prov
;
11755 struct node_provider_desc prov_desc
;
11757 ULONG exp_release_refcnt
;
11760 static void set_elem_desc(struct exp_elem_desc
*desc
, struct Provider
*prov
, HWND hwnd
, DWORD pid
, ULONG exp_refcnt
,
11761 ULONG exp_release_refcnt
)
11763 desc
->elem_prov
= prov
;
11764 init_node_provider_desc(&desc
->prov_desc
, pid
, hwnd
);
11765 desc
->exp_refcnt
= exp_refcnt
;
11766 desc
->exp_release_refcnt
= exp_release_refcnt
;
11769 #define test_uia_element_arr( elem_arr, exp_elems, exp_elems_count ) \
11770 test_uia_element_arr_( (elem_arr), (exp_elems), (exp_elems_count), __FILE__, __LINE__)
11771 static void test_uia_element_arr_(IUIAutomationElementArray
*elem_arr
, struct exp_elem_desc
*exp_elems
, int exp_elems_count
,
11772 const char *file
, int line
)
11777 hr
= IUIAutomationElementArray_get_Length(elem_arr
, &arr_length
);
11778 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11779 ok_(file
, line
)(hr
== S_OK
, "IUIAutomationElementArray_get_Length: Unexpected hr %#lx\n", hr
);
11780 ok_(file
, line
)(arr_length
== exp_elems_count
, "Unexpected arr_length %d.\n", arr_length
);
11782 for (i
= 0; i
< arr_length
; i
++)
11784 struct exp_elem_desc
*desc
= &exp_elems
[i
];
11785 IUIAutomationElement
*element
;
11788 ok_(file
, line
)(desc
->elem_prov
->ref
== desc
->exp_refcnt
, "elem[%d]: Unexpected refcnt %ld\n", i
, exp_elems
[i
].elem_prov
->ref
);
11792 hr
= IUIAutomationElementArray_GetElement(elem_arr
, i
, &element
);
11793 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11794 ok(!!element
, "element == NULL\n");
11796 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
11797 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
11798 test_node_provider_desc_(&exp_elems
[i
].prov_desc
, V_BSTR(&v
), file
, line
);
11800 IUIAutomationElement_Release(element
);
11803 IUIAutomationElementArray_Release(elem_arr
);
11805 for (i
= 0; i
< arr_length
; i
++)
11807 struct exp_elem_desc
*desc
= &exp_elems
[i
];
11809 ok_(file
, line
)(desc
->elem_prov
->ref
== desc
->exp_release_refcnt
, "elem[%d]: Unexpected refcnt %ld\n", i
, exp_elems
[i
].elem_prov
->ref
);
11813 static void test_Element_Find(IUIAutomation
*uia_iface
)
11815 HWND hwnd
= create_test_hwnd("test_Element_Find class");
11816 IUIAutomationCondition
*condition
, *condition2
;
11817 struct Provider_prop_override prop_override
;
11818 struct exp_elem_desc exp_elems
[7] = { 0 };
11819 IUIAutomationElement
*element
, *element2
;
11820 IUIAutomationElementArray
*element_arr
;
11821 IUIAutomationCacheRequest
*cache_req
;
11825 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, TRUE
);
11828 * The COM API has no equivalent to UiaNodeFromProvider, so the only way
11829 * we can get an initial element is with ElementFromHandle. This means our
11830 * element representing Provider will have an HWND associated, which
11831 * doesn't match our old UiaFind tests. To work around this, make Provider
11832 * return itself for the UIA_LabeledByPropertyId to get an element without
11833 * an HWND associated.
11836 V_VT(&v
) = VT_UNKNOWN
;
11837 V_UNKNOWN(&v
) = (IUnknown
*)&Provider
.IRawElementProviderSimple_iface
;
11838 set_property_override(&prop_override
, UIA_LabeledByPropertyId
, &v
);
11839 set_provider_prop_override(&Provider
, &prop_override
, 1);
11840 Provider
.hwnd
= NULL
;
11842 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_LabeledByPropertyId
, TRUE
, &v
);
11843 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11844 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
11845 ok(Provider
.ref
== 3, "Unexpected refcnt %ld\n", Provider
.ref
);
11847 hr
= IUnknown_QueryInterface(V_UNKNOWN(&v
), &IID_IUIAutomationElement
, (void **)&element2
);
11848 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11849 ok(!!element2
, "element2 == NULL\n");
11851 ok_method_sequence(element_find_start_seq
, "element_find_start_seq");
11852 set_provider_prop_override(&Provider
, NULL
, 0);
11854 IUIAutomationElement_Release(element
);
11855 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
11857 element
= element2
;
11860 initialize_provider_tree(TRUE
);
11861 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
11862 provider_add_child(&Provider
, &Provider_child
);
11863 provider_add_child(&Provider
, &Provider_child2
);
11864 provider_add_child(&Provider_child
, &Provider_child_child
);
11865 provider_add_child(&Provider_child
, &Provider_child_child2
);
11866 provider_add_child(&Provider_child2
, &Provider_child2_child
);
11867 provider_add_child(&Provider_child2_child
, &Provider_child2_child_child
);
11870 * In order to match the tests from test_UiaFind(), we need to create a
11871 * custom IUIAutomationCacheRequest with a ConditionType_True treeview.
11872 * The default cache request also caches the RuntimeId property.
11875 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, &cache_req
);
11876 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11877 ok(!!cache_req
, "cache_req == NULL\n");
11879 /* Set view condition to ConditionType_True. */
11881 hr
= IUIAutomation_CreateTrueCondition(uia_iface
, &condition
);
11882 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11883 ok(!!condition
, "condition == NULL\n");
11885 hr
= IUIAutomationCacheRequest_put_TreeFilter(cache_req
, condition
);
11886 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11889 * Equivalent to: Maximum find depth of -1, find first is FALSE, exclude
11892 hr
= IUIAutomationElement_FindAllBuildCache(element
, TreeScope_SubTree
, condition
, cache_req
, &element_arr
);
11893 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11895 set_elem_desc(&exp_elems
[0], &Provider
, NULL
, GetCurrentProcessId(), 2, 2);
11896 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider", TRUE
);
11897 set_elem_desc(&exp_elems
[1], &Provider_child
, NULL
, GetCurrentProcessId(), 2, 1);
11898 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child", TRUE
);
11899 set_elem_desc(&exp_elems
[2], &Provider_child_child
, NULL
, GetCurrentProcessId(), 2, 1);
11900 add_provider_desc(&exp_elems
[2].prov_desc
, L
"Main", L
"Provider_child_child", TRUE
);
11901 set_elem_desc(&exp_elems
[3], &Provider_child_child2
, NULL
, GetCurrentProcessId(), 2, 1);
11902 add_provider_desc(&exp_elems
[3].prov_desc
, L
"Main", L
"Provider_child_child2", TRUE
);
11903 set_elem_desc(&exp_elems
[4], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
11904 add_provider_desc(&exp_elems
[4].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
11905 set_elem_desc(&exp_elems
[5], &Provider_child2_child
, NULL
, GetCurrentProcessId(), 2, 1);
11906 add_provider_desc(&exp_elems
[5].prov_desc
, L
"Main", L
"Provider_child2_child", TRUE
);
11907 set_elem_desc(&exp_elems
[6], &Provider_child2_child_child
, NULL
, GetCurrentProcessId(), 2, 1);
11908 add_provider_desc(&exp_elems
[6].prov_desc
, L
"Main", L
"Provider_child2_child_child", TRUE
);
11910 test_uia_element_arr(element_arr
, exp_elems
, 7);
11911 ok_method_sequence(find_seq1
, "find_seq1");
11914 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
11917 hr
= IUIAutomationElement_FindAllBuildCache(element
, TreeScope_Element
| TreeScope_Children
, condition
, cache_req
, &element_arr
);
11918 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11920 set_elem_desc(&exp_elems
[0], &Provider
, NULL
, GetCurrentProcessId(), 2, 2);
11921 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider", TRUE
);
11922 set_elem_desc(&exp_elems
[1], &Provider_child
, NULL
, GetCurrentProcessId(), 2, 1);
11923 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child", TRUE
);
11924 set_elem_desc(&exp_elems
[2], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
11925 add_provider_desc(&exp_elems
[2].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
11927 test_uia_element_arr(element_arr
, exp_elems
, 3);
11928 ok_method_sequence(find_seq2
, "find_seq2");
11931 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
11934 hr
= IUIAutomationElement_FindAllBuildCache(element
, TreeScope_Children
, condition
, cache_req
, &element_arr
);
11935 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11937 set_elem_desc(&exp_elems
[0], &Provider_child
, NULL
, GetCurrentProcessId(), 2, 1);
11938 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider_child", TRUE
);
11939 set_elem_desc(&exp_elems
[1], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
11940 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
11942 test_uia_element_arr(element_arr
, exp_elems
, 2);
11943 ok_method_sequence(find_seq3
, "find_seq3");
11946 * Equivalent to: Maximum find depth of 1, find first is TRUE, exclude
11947 * root is TRUE. element2 now represents Provider_child.
11949 hr
= IUIAutomationElement_FindFirstBuildCache(element
, TreeScope_Children
, condition
, cache_req
, &element2
);
11950 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11951 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
11953 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element2
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
11954 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
11955 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
11956 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child", TRUE
);
11959 ok_method_sequence(find_seq4
, "find_seq4");
11962 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
11963 * root is FALSE. Provider_child doesn't have a runtime id for UI
11964 * Automation to use as a way to check if it has navigated back to the
11965 * node that began the search, so it will get siblings.
11967 hr
= IUIAutomationElement_FindAllBuildCache(element2
, TreeScope_Element
, condition
, cache_req
, &element_arr
);
11968 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11970 set_elem_desc(&exp_elems
[0], &Provider_child
, NULL
, GetCurrentProcessId(), 2, 2);
11971 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider_child", TRUE
);
11972 set_elem_desc(&exp_elems
[1], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
11973 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
11975 test_uia_element_arr(element_arr
, exp_elems
, 2);
11976 ok_method_sequence(find_seq5
, "find_seq5");
11979 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
11980 * root is FALSE. Provider_child now has a runtime ID, so we don't get
11983 Provider_child
.runtime_id
[0] = Provider_child
.runtime_id
[1] = 0xdeadbeef;
11984 hr
= IUIAutomationElement_FindAllBuildCache(element2
, TreeScope_Element
, condition
, cache_req
, &element_arr
);
11985 IUIAutomationElement_Release(element2
);
11986 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11988 set_elem_desc(&exp_elems
[0], &Provider_child
, NULL
, GetCurrentProcessId(), 2, 1);
11989 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider_child", TRUE
);
11991 test_uia_element_arr(element_arr
, exp_elems
, 1);
11992 ok_method_sequence(find_seq6
, "find_seq6");
11993 initialize_provider_tree(FALSE
);
11995 IUIAutomationCondition_Release(condition
);
11997 /* condition is now UIA_IsContentElementPropertyId == FALSE. */
11999 variant_init_bool(&v
, FALSE
);
12000 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_IsContentElementPropertyId
, v
, &condition
);
12001 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12002 ok(!!condition
, "condition == NULL\n");
12004 /* Set view condition to this property condition. */
12005 hr
= IUIAutomationCacheRequest_put_TreeFilter(cache_req
, condition
);
12006 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12008 /* condition2 is UIA_IsControlElementPropertyId == TRUE. */
12010 variant_init_bool(&v
, TRUE
);
12011 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_IsControlElementPropertyId
, v
, &condition2
);
12012 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12013 ok(!!condition2
, "condition2 == NULL\n");
12015 /* Override UIA_IsContentElementPropertyId, set it to FALSE. */
12016 variant_init_bool(&v
, FALSE
);
12017 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
12018 set_provider_prop_override(&Provider
, &prop_override
, 1);
12019 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
12020 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
12021 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
12024 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
12025 * root is FALSE. The cache request view condition is used to determine
12026 * tree depth, if an element matches the cache request view condition,
12027 * depth is incremented. Since Provider_child does not, Provider_child_child,
12028 * Provider_child_child2, and Provider_child2 are all considered to be at
12031 hr
= IUIAutomationElement_FindAllBuildCache(element
, TreeScope_Element
| TreeScope_Children
, condition2
, cache_req
, &element_arr
);
12032 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12034 set_elem_desc(&exp_elems
[0], &Provider
, NULL
, GetCurrentProcessId(), 2, 2);
12035 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider", TRUE
);
12036 set_elem_desc(&exp_elems
[1], &Provider_child_child
, NULL
, GetCurrentProcessId(), 2, 1);
12037 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child_child", TRUE
);
12038 set_elem_desc(&exp_elems
[2], &Provider_child_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12039 add_provider_desc(&exp_elems
[2].prov_desc
, L
"Main", L
"Provider_child_child2", TRUE
);
12040 set_elem_desc(&exp_elems
[3], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12041 add_provider_desc(&exp_elems
[3].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
12043 test_uia_element_arr(element_arr
, exp_elems
, 4);
12044 ok_method_sequence(find_seq7
, "find_seq7");
12045 initialize_provider_tree(FALSE
);
12048 * Same test as before, except now Provider has a runtime ID.
12050 Provider
.runtime_id
[0] = Provider
.runtime_id
[1] = 0xdeadbeef;
12051 variant_init_bool(&v
, FALSE
);
12052 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
12053 set_provider_prop_override(&Provider
, &prop_override
, 1);
12054 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
12055 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
12056 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
12058 hr
= IUIAutomationElement_FindAllBuildCache(element
, TreeScope_Element
| TreeScope_Children
, condition2
, cache_req
, &element_arr
);
12059 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12061 set_elem_desc(&exp_elems
[0], &Provider
, NULL
, GetCurrentProcessId(), 2, 2);
12062 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider", TRUE
);
12063 set_elem_desc(&exp_elems
[1], &Provider_child_child
, NULL
, GetCurrentProcessId(), 2, 1);
12064 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child_child", TRUE
);
12065 set_elem_desc(&exp_elems
[2], &Provider_child_child2
, NULL
, GetCurrentProcessId(), 2, 2);
12066 add_provider_desc(&exp_elems
[2].prov_desc
, L
"Main", L
"Provider_child_child2", TRUE
);
12067 set_elem_desc(&exp_elems
[3], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12068 add_provider_desc(&exp_elems
[3].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
12070 /* element2 now represents Provider_child_child2. */
12071 hr
= IUIAutomationElementArray_GetElement(element_arr
, 2, &element2
);
12072 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12074 test_uia_element_arr(element_arr
, exp_elems
, 4);
12075 ok_method_sequence(find_seq8
, "find_seq8");
12076 initialize_provider_tree(FALSE
);
12078 variant_init_bool(&v
, FALSE
);
12079 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
12080 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
12081 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
12082 set_provider_prop_override(&Provider_child2_child
, &prop_override
, 1);
12085 * Equivalent to: Maximum find depth of 1, find first is FALSE,
12086 * exclude root is FALSE. Starting at Provider_child_child2, find
12087 * will be able to traverse the tree in the same order as it would
12088 * if we had started at the tree root Provider, retrieving
12089 * Provider_child2 as a sibling and Provider_child2_child as a node
12092 hr
= IUIAutomationElement_FindAllBuildCache(element2
, TreeScope_Element
| TreeScope_Children
, condition2
, cache_req
, &element_arr
);
12093 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12094 IUIAutomationElement_Release(element2
);
12096 set_elem_desc(&exp_elems
[0], &Provider_child_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12097 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider_child_child2", TRUE
);
12098 set_elem_desc(&exp_elems
[1], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12099 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
12100 set_elem_desc(&exp_elems
[2], &Provider_child2_child
, NULL
, GetCurrentProcessId(), 2, 1);
12101 add_provider_desc(&exp_elems
[2].prov_desc
, L
"Main", L
"Provider_child2_child", TRUE
);
12103 test_uia_element_arr(element_arr
, exp_elems
, 3);
12104 ok_method_sequence(find_seq9
, "find_seq9");
12105 initialize_provider_tree(FALSE
);
12108 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
12109 * root is TRUE. Exclude root applies to the first node that matches the
12110 * view condition, and not the node that is passed into UiaFind(). Since
12111 * Provider doesn't match our view condition here, Provider_child will be
12114 variant_init_bool(&v
, FALSE
);
12115 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
12116 set_provider_prop_override(&Provider_child
, &prop_override
, 1);
12117 set_provider_prop_override(&Provider_child2
, &prop_override
, 1);
12118 hr
= IUIAutomationElement_FindAllBuildCache(element
, TreeScope_Children
, condition2
, cache_req
, &element_arr
);
12119 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12121 set_elem_desc(&exp_elems
[0], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12122 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
12124 test_uia_element_arr(element_arr
, exp_elems
, 1);
12125 ok_method_sequence(find_seq10
, "find_seq10");
12126 initialize_provider_tree(FALSE
);
12128 variant_init_bool(&v
, FALSE
);
12129 set_property_override(&prop_override
, UIA_IsContentElementPropertyId
, &v
);
12130 set_provider_prop_override(&Provider_child_child2
, &prop_override
, 1);
12133 * Equivalent to: Maximum find depth of -1, find first is TRUE, exclude
12134 * root is FALSE. Provider_child_child2 is the only element in the tree
12135 * to match our condition.
12137 hr
= IUIAutomationElement_FindFirstBuildCache(element
, TreeScope_SubTree
, condition
, cache_req
, &element2
);
12138 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12139 ok(Provider_child_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
12141 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element2
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
12142 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12143 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
12144 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child_child2", TRUE
);
12147 IUIAutomationElement_Release(element2
);
12148 ok_method_sequence(find_seq11
, "find_seq11");
12149 initialize_provider_tree(FALSE
);
12151 IUIAutomationCondition_Release(condition
);
12152 IUIAutomationCondition_Release(condition2
);
12153 IUIAutomationCacheRequest_Release(cache_req
);
12156 * Equivalent to: Maximum find depth of 1, find first is FALSE,
12157 * exclude root is FALSE. FindAll() uses the default
12158 * IUIAutomationCacheRequest, which uses the ControlView condition
12159 * as its view condition. Since Provider_child doesn't match this view
12160 * condition, it isn't a child of Provider in this treeview. No property
12161 * values are cached by the default internal cache request, so we need to
12162 * use a separate method sequence.
12164 variant_init_bool(&v
, FALSE
);
12165 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
12166 set_provider_prop_override(&Provider_child
, &prop_override
, 1);
12168 /* condition is now UIA_IsContentElementPropertyId == TRUE. */
12169 variant_init_bool(&v
, TRUE
);
12170 hr
= IUIAutomation_CreatePropertyCondition(uia_iface
, UIA_IsContentElementPropertyId
, v
, &condition
);
12171 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12172 ok(!!condition
, "cond == NULL\n");
12174 hr
= IUIAutomationElement_FindAll(element
, TreeScope_Element
| TreeScope_Children
, condition
, &element_arr
);
12175 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12177 set_elem_desc(&exp_elems
[0], &Provider
, NULL
, GetCurrentProcessId(), 2, 2);
12178 add_provider_desc(&exp_elems
[0].prov_desc
, L
"Main", L
"Provider", TRUE
);
12179 set_elem_desc(&exp_elems
[1], &Provider_child_child
, NULL
, GetCurrentProcessId(), 2, 1);
12180 add_provider_desc(&exp_elems
[1].prov_desc
, L
"Main", L
"Provider_child_child", TRUE
);
12181 set_elem_desc(&exp_elems
[2], &Provider_child_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12182 add_provider_desc(&exp_elems
[2].prov_desc
, L
"Main", L
"Provider_child_child2", TRUE
);
12183 set_elem_desc(&exp_elems
[3], &Provider_child2
, NULL
, GetCurrentProcessId(), 2, 1);
12184 add_provider_desc(&exp_elems
[3].prov_desc
, L
"Main", L
"Provider_child2", TRUE
);
12186 test_uia_element_arr(element_arr
, exp_elems
, 4);
12187 ok_method_sequence(element_find_seq1
, "element_find_seq1");
12188 initialize_provider_tree(FALSE
);
12191 * Equivalent to: Maximum find depth of -1, find first is TRUE,
12192 * exclude root is FALSE. FindFirst() also uses the default cache request.
12193 * Provider_child_child2 will be the first provider in the tree to match
12194 * this view condition, so it will be returned.
12196 variant_init_bool(&v
, FALSE
);
12197 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
12198 set_provider_prop_override(&Provider
, &prop_override
, 1);
12199 set_provider_prop_override(&Provider_child
, &prop_override
, 1);
12200 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
12202 hr
= IUIAutomationElement_FindFirst(element
, TreeScope_SubTree
, condition
, &element2
);
12203 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12204 ok(Provider_child_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child_child2
.ref
);
12206 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element2
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
12207 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12208 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), NULL
);
12209 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_child_child2", TRUE
);
12212 IUIAutomationElement_Release(element2
);
12213 ok_method_sequence(element_find_seq2
, "element_find_seq2");
12214 initialize_provider_tree(TRUE
);
12216 IUIAutomationCondition_Release(condition
);
12217 IUIAutomationElement_Release(element
);
12218 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
12220 DestroyWindow(hwnd
);
12221 UnregisterClassA("test_Element_Find class", NULL
);
12224 static const struct prov_method_sequence treewalker_seq1
[] = {
12225 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
12226 NODE_CREATE_SEQ(&Provider_child
),
12230 static const struct prov_method_sequence treewalker_seq2
[] = {
12231 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_FirstChild */
12232 NODE_CREATE_SEQ(&Provider_child
),
12233 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
12237 static const struct prov_method_sequence treewalker_seq3
[] = {
12238 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_LastChild */
12239 NODE_CREATE_SEQ(&Provider_child2
),
12243 static const struct prov_method_sequence treewalker_seq4
[] = {
12244 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_LastChild */
12245 NODE_CREATE_SEQ(&Provider_child2
),
12246 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
12250 static const struct prov_method_sequence treewalker_seq5
[] = {
12251 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
12252 NODE_CREATE_SEQ(&Provider_child2
),
12256 static const struct prov_method_sequence treewalker_seq6
[] = {
12257 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
12258 NODE_CREATE_SEQ(&Provider_child2
),
12259 { &Provider_child2
, FRAG_GET_RUNTIME_ID
},
12263 static const struct prov_method_sequence treewalker_seq7
[] = {
12264 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_PreviousSibling */
12265 NODE_CREATE_SEQ(&Provider_child
),
12269 static const struct prov_method_sequence treewalker_seq8
[] = {
12270 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_PreviousSibling */
12271 NODE_CREATE_SEQ(&Provider_child
),
12272 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
12276 static const struct prov_method_sequence treewalker_seq9
[] = {
12277 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
12278 NODE_CREATE_SEQ(&Provider
),
12282 static const struct prov_method_sequence treewalker_seq10
[] = {
12283 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
12284 NODE_CREATE_SEQ(&Provider
),
12285 { &Provider
, FRAG_GET_RUNTIME_ID
},
12289 static void test_CUIAutomation_TreeWalker_ifaces(IUIAutomation
*uia_iface
)
12291 HWND hwnd
= create_test_hwnd("test_CUIAutomation_TreeWalker_ifaces class");
12292 IUIAutomationElement
*element
, *element2
, *element3
;
12293 IUIAutomationCacheRequest
*cache_req
;
12294 IUIAutomationCondition
*cond
, *cond2
;
12295 IUIAutomationTreeWalker
*walker
;
12299 hr
= IUIAutomation_CreateTrueCondition(uia_iface
, &cond
);
12300 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12301 ok(!!cond
, "cond == NULL\n");
12303 /* NULL input argument tests. */
12304 walker
= (void *)0xdeadbeef;
12305 hr
= IUIAutomation_CreateTreeWalker(uia_iface
, NULL
, &walker
);
12306 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12307 ok(!walker
, "walker != NULL\n");
12309 hr
= IUIAutomation_CreateTreeWalker(uia_iface
, cond
, NULL
);
12310 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12312 /* Actually create TreeWalker. */
12314 hr
= IUIAutomation_CreateTreeWalker(uia_iface
, cond
, &walker
);
12315 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12316 ok(!!walker
, "walker == NULL\n");
12318 hr
= IUIAutomationTreeWalker_get_Condition(walker
, &cond2
);
12319 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12320 ok(!!cond2
, "cond2 == NULL\n");
12322 ok(iface_cmp((IUnknown
*)cond
, (IUnknown
*)cond2
), "cond != cond2\n");
12323 IUIAutomationCondition_Release(cond
);
12324 IUIAutomationCondition_Release(cond2
);
12327 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, &cache_req
);
12328 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12329 ok(!!cache_req
, "cache_req == NULL\n");
12331 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, TRUE
);
12332 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12333 initialize_provider(&Provider_child2
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12334 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
12335 provider_add_child(&Provider
, &Provider_child
);
12336 provider_add_child(&Provider
, &Provider_child2
);
12338 /* NULL input argument tests. */
12339 hr
= IUIAutomationTreeWalker_GetFirstChildElement(walker
, element
, NULL
);
12340 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12342 element2
= (void *)0xdeadbeef;
12343 hr
= IUIAutomationTreeWalker_GetFirstChildElement(walker
, NULL
, &element2
);
12344 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12345 ok(!element2
, "element2 != NULL\n");
12347 /* NavigateDirection_FirstChild. */
12349 hr
= IUIAutomationTreeWalker_GetFirstChildElement(walker
, element
, &element2
);
12350 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12351 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12352 ok(!!element2
, "element2 == NULL\n");
12353 ok_method_sequence(treewalker_seq1
, "treewalker_seq1");
12355 IUIAutomationElement_Release(element2
);
12356 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12359 hr
= IUIAutomationTreeWalker_GetFirstChildElementBuildCache(walker
, element
, cache_req
, &element2
);
12360 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12361 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12362 ok(!!element2
, "element2 == NULL\n");
12363 ok_method_sequence(treewalker_seq2
, "treewalker_seq2");
12365 /* NavigateDirection_NextSibling. */
12367 hr
= IUIAutomationTreeWalker_GetNextSiblingElement(walker
, element2
, &element3
);
12368 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12369 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12370 ok(!!element3
, "element3 == NULL\n");
12371 ok_method_sequence(treewalker_seq5
, "treewalker_seq5");
12372 IUIAutomationElement_Release(element3
);
12373 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12376 hr
= IUIAutomationTreeWalker_GetNextSiblingElementBuildCache(walker
, element2
, cache_req
, &element3
);
12377 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12378 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12379 ok(!!element3
, "element3 == NULL\n");
12380 ok_method_sequence(treewalker_seq6
, "treewalker_seq6");
12381 IUIAutomationElement_Release(element3
);
12382 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12384 IUIAutomationElement_Release(element2
);
12385 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12387 /* NavigateDirection_LastChild. */
12389 hr
= IUIAutomationTreeWalker_GetLastChildElement(walker
, element
, &element2
);
12390 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12391 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12392 ok(!!element2
, "element2 == NULL\n");
12393 ok_method_sequence(treewalker_seq3
, "treewalker_seq3");
12395 IUIAutomationElement_Release(element2
);
12396 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12399 hr
= IUIAutomationTreeWalker_GetLastChildElementBuildCache(walker
, element
, cache_req
, &element2
);
12400 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12401 ok(Provider_child2
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12402 ok(!!element2
, "element2 == NULL\n");
12403 ok_method_sequence(treewalker_seq4
, "treewalker_seq4");
12405 /* NavigateDirection_PreviousSibling. */
12407 hr
= IUIAutomationTreeWalker_GetPreviousSiblingElement(walker
, element2
, &element3
);
12408 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12409 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12410 ok(!!element3
, "element3 == NULL\n");
12411 ok_method_sequence(treewalker_seq7
, "treewalker_seq7");
12412 IUIAutomationElement_Release(element3
);
12413 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12416 hr
= IUIAutomationTreeWalker_GetPreviousSiblingElementBuildCache(walker
, element2
, cache_req
, &element3
);
12417 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12418 ok(Provider_child
.ref
== 2, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12419 ok(!!element3
, "element3 == NULL\n");
12420 ok_method_sequence(treewalker_seq8
, "treewalker_seq8");
12421 IUIAutomationElement_Release(element3
);
12422 ok(Provider_child
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child
.ref
);
12424 /* NavigateDirection_Parent. */
12426 Provider
.hwnd
= NULL
;
12427 hr
= IUIAutomationTreeWalker_GetParentElement(walker
, element2
, &element3
);
12428 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12429 ok(Provider
.ref
== 3, "Unexpected refcnt %ld\n", Provider
.ref
);
12430 ok(!!element3
, "element3 == NULL\n");
12431 ok_method_sequence(treewalker_seq9
, "treewalker_seq9");
12432 IUIAutomationElement_Release(element3
);
12433 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
12436 hr
= IUIAutomationTreeWalker_GetParentElementBuildCache(walker
, element2
, cache_req
, &element3
);
12437 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12438 ok(Provider
.ref
== 3, "Unexpected refcnt %ld\n", Provider
.ref
);
12439 ok(!!element3
, "element3 == NULL\n");
12440 ok_method_sequence(treewalker_seq10
, "treewalker_seq10");
12441 IUIAutomationElement_Release(element3
);
12442 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
12444 IUIAutomationElement_Release(element2
);
12445 ok(Provider_child2
.ref
== 1, "Unexpected refcnt %ld\n", Provider_child2
.ref
);
12447 IUIAutomationElement_Release(element
);
12448 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
12450 IUIAutomationCacheRequest_Release(cache_req
);
12451 IUIAutomationTreeWalker_Release(walker
);
12453 DestroyWindow(hwnd
);
12454 UnregisterClassA("test_CUIAutomation_TreeWalker_ifaces class", NULL
);
12457 static void set_clientside_providers_for_hwnd(struct Provider
*proxy_prov
, struct Provider
*nc_prov
,
12458 struct Provider
*hwnd_prov
, HWND hwnd
)
12462 initialize_provider(proxy_prov
, ProviderOptions_ClientSideProvider
, hwnd
, TRUE
);
12463 proxy_prov
->frag_root
= &proxy_prov
->IRawElementProviderFragmentRoot_iface
;
12464 proxy_prov
->ignore_hwnd_prop
= TRUE
;
12467 initialize_provider(hwnd_prov
, ProviderOptions_ClientSideProvider
, hwnd
, TRUE
);
12468 initialize_provider(nc_prov
, ProviderOptions_NonClientAreaProvider
| ProviderOptions_ClientSideProvider
, hwnd
, TRUE
);
12469 hwnd_prov
->frag_root
= &hwnd_prov
->IRawElementProviderFragmentRoot_iface
;
12470 nc_prov
->frag_root
= &nc_prov
->IRawElementProviderFragmentRoot_iface
;
12471 nc_prov
->ignore_hwnd_prop
= TRUE
;
12474 static void test_GetRootElement(IUIAutomation
*uia_iface
)
12476 IUIAutomationElement
*element
;
12480 hr
= IUIAutomation_GetRootElement(uia_iface
, NULL
);
12481 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12483 UiaRegisterProviderCallback(test_uia_provider_callback
);
12485 set_clientside_providers_for_hwnd(&Provider_proxy
, &Provider_nc
, &Provider_hwnd
, GetDesktopWindow());
12486 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
12487 proxy_prov
= &Provider_proxy
.IRawElementProviderSimple_iface
;
12488 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
12490 /* Retrieve an element representing the desktop HWND. */
12491 method_sequences_enabled
= FALSE
;
12492 SET_EXPECT(prov_callback_base_hwnd
);
12493 SET_EXPECT(prov_callback_nonclient
);
12494 SET_EXPECT(prov_callback_proxy
);
12495 hr
= IUIAutomation_GetRootElement(uia_iface
, &element
);
12496 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12497 ok(!!element
, "Node == NULL.\n");
12498 ok(Provider_proxy
.ref
== 2, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
12499 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
12500 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
12501 CHECK_CALLED(prov_callback_base_hwnd
);
12502 CHECK_CALLED(prov_callback_nonclient
);
12503 CHECK_CALLED(prov_callback_proxy
);
12505 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
12506 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12507 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), GetDesktopWindow());
12508 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_proxy", TRUE
);
12509 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
12510 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
12513 IUIAutomationElement_Release(element
);
12514 ok(Provider_proxy
.ref
== 1, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
12515 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
12516 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
12518 initialize_provider(&Provider_hwnd
, ProviderOptions_ClientSideProvider
, NULL
, TRUE
);
12519 initialize_provider(&Provider_nc
, ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
, NULL
,
12521 initialize_provider(&Provider_proxy
, ProviderOptions_ClientSideProvider
, NULL
, TRUE
);
12522 base_hwnd_prov
= proxy_prov
= nc_prov
= NULL
;
12524 method_sequences_enabled
= TRUE
;
12525 UiaRegisterProviderCallback(NULL
);
12528 #define test_get_focused_elem( uia_iface, cache_req, exp_hr, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, \
12529 nc_cback_count, win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, \
12530 base_hwnd_cback_todo, nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo ) \
12531 test_get_focused_elem_( (uia_iface), (cache_req), (exp_hr), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), \
12532 (nc_cback_count), (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), \
12533 (base_hwnd_cback_todo), (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
12534 static void test_get_focused_elem_(IUIAutomation
*uia_iface
, IUIAutomationCacheRequest
*cache_req
, HRESULT exp_hr
,
12535 struct node_provider_desc
*exp_node_desc
, int proxy_cback_count
, int base_hwnd_cback_count
, int nc_cback_count
,
12536 int win_get_obj_count
, int child_win_get_obj_count
, BOOL proxy_cback_todo
, BOOL base_hwnd_cback_todo
,
12537 BOOL nc_cback_todo
, BOOL win_get_obj_todo
, BOOL child_win_get_obj_todo
, const char *file
, int line
)
12539 IUIAutomationElement
*element
= NULL
;
12543 SET_EXPECT_MULTI(prov_callback_base_hwnd
, base_hwnd_cback_count
);
12544 SET_EXPECT_MULTI(prov_callback_nonclient
, nc_cback_count
);
12545 SET_EXPECT_MULTI(prov_callback_proxy
, proxy_cback_count
);
12546 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, win_get_obj_count
);
12547 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot
, child_win_get_obj_count
);
12549 hr
= IUIAutomation_GetFocusedElementBuildCache(uia_iface
, cache_req
, &element
);
12551 hr
= IUIAutomation_GetFocusedElement(uia_iface
, &element
);
12552 ok_(file
, line
)(hr
== exp_hr
, "Unexpected hr %#lx.\n", hr
);
12553 todo_wine_if(base_hwnd_cback_todo
) CHECK_CALLED_MULTI(prov_callback_base_hwnd
, base_hwnd_cback_count
);
12554 todo_wine_if(proxy_cback_todo
) CHECK_CALLED_MULTI(prov_callback_proxy
, proxy_cback_count
);
12555 todo_wine_if(nc_cback_todo
) CHECK_CALLED_MULTI(prov_callback_nonclient
, nc_cback_count
);
12556 todo_wine_if(win_get_obj_todo
) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot
, win_get_obj_count
);
12557 todo_wine_if(child_win_get_obj_todo
) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot
, child_win_get_obj_count
);
12559 if (exp_node_desc
->prov_count
)
12561 ok_(file
, line
)(!!element
, "element == NULL\n");
12563 hr
= IUIAutomationElement_GetCurrentPropertyValueEx(element
, UIA_ProviderDescriptionPropertyId
, TRUE
, &v
);
12564 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12565 test_node_provider_desc_(exp_node_desc
, V_BSTR(&v
), file
, line
);
12568 IUIAutomationElement_Release(element
);
12571 ok_(file
, line
)(!element
, "element != NULL\n");
12574 static void test_GetFocusedElement(IUIAutomation
*uia_iface
)
12576 struct Provider_prop_override prop_override
;
12577 struct node_provider_desc exp_node_desc
;
12578 IUIAutomationCacheRequest
*cache_req
;
12579 IUIAutomationElement
*element
;
12580 HWND hwnd
, hwnd_child
;
12584 hwnd
= create_test_hwnd("test_GetFocusedElement class");
12585 hwnd_child
= create_child_test_hwnd("test_GetFocusedElement child class", hwnd
);
12586 UiaRegisterProviderCallback(test_uia_provider_callback
);
12589 hr
= IUIAutomation_CreateCacheRequest(uia_iface
, &cache_req
);
12590 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12591 ok(!!cache_req
, "cache_req == NULL\n");
12594 * Set clientside providers for our test windows and the desktop. Same
12595 * tests as UiaNodeFromFocus, just with COM methods.
12597 set_clientside_providers_for_hwnd(&Provider_proxy
, &Provider_nc
, &Provider_hwnd
, GetDesktopWindow());
12598 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
12599 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
12600 proxy_prov
= &Provider_proxy
.IRawElementProviderSimple_iface
;
12602 set_clientside_providers_for_hwnd(NULL
, &Provider_nc2
, &Provider_hwnd2
, hwnd
);
12603 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, hwnd
, TRUE
);
12604 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
12605 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
12606 Provider
.ignore_hwnd_prop
= TRUE
;
12608 set_clientside_providers_for_hwnd(NULL
, &Provider_nc3
, &Provider_hwnd3
, hwnd_child
);
12609 initialize_provider(&Provider2
, ProviderOptions_ServerSideProvider
, hwnd_child
, TRUE
);
12610 Provider2
.frag_root
= &Provider2
.IRawElementProviderFragmentRoot_iface
;
12611 child_win_prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
12612 Provider2
.ignore_hwnd_prop
= TRUE
;
12614 /* NULL input argument tests. */
12615 hr
= IUIAutomation_GetFocusedElement(uia_iface
, NULL
);
12616 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12618 hr
= IUIAutomation_GetFocusedElementBuildCache(uia_iface
, cache_req
, NULL
);
12619 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12621 element
= (void *)0xdeadbeef;
12622 hr
= IUIAutomation_GetFocusedElementBuildCache(uia_iface
, NULL
, &element
);
12623 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12624 ok(!element
, "element != NULL\n");
12627 * None of the providers for the desktop node return a provider from
12628 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
12631 method_sequences_enabled
= FALSE
;
12632 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), GetDesktopWindow());
12633 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider_proxy", TRUE
);
12634 add_provider_desc(&exp_node_desc
, L
"Nonclient", L
"Provider_nc", FALSE
);
12635 add_provider_desc(&exp_node_desc
, L
"Hwnd", L
"Provider_hwnd", FALSE
);
12637 test_get_focused_elem(uia_iface
, NULL
, S_OK
, &exp_node_desc
, 1, 1, 1, 0, 0, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
);
12638 test_get_focused_elem(uia_iface
, cache_req
, S_OK
, &exp_node_desc
, 1, 1, 1, 0, 0, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
);
12640 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
12641 Provider_hwnd
.focus_prov
= &Provider_hwnd2
.IRawElementProviderFragment_iface
;
12643 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), hwnd
);
12644 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider", TRUE
);
12645 add_provider_desc(&exp_node_desc
, L
"Nonclient", L
"Provider_nc2", FALSE
);
12646 add_provider_desc(&exp_node_desc
, L
"Hwnd", L
"Provider_hwnd2", FALSE
);
12648 test_get_focused_elem(uia_iface
, NULL
, S_OK
, &exp_node_desc
, 2, 1, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
12649 test_get_focused_elem(uia_iface
, cache_req
, S_OK
, &exp_node_desc
, 2, 1, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
12652 * Provider_proxy returns Provider from GetFocus. The provider that
12653 * creates the node will not have GetFocus called on it to avoid returning
12654 * the same provider twice. Similarly, on nodes other than the desktop
12655 * node, the HWND provider will not have GetFocus called on it.
12657 Provider_hwnd
.focus_prov
= NULL
;
12658 Provider_proxy
.focus_prov
= &Provider
.IRawElementProviderFragment_iface
;
12659 Provider
.focus_prov
= Provider_hwnd2
.focus_prov
= &Provider2
.IRawElementProviderFragment_iface
;
12661 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), hwnd
);
12662 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider", TRUE
);
12663 add_provider_desc(&exp_node_desc
, L
"Nonclient", L
"Provider_nc2", FALSE
);
12664 add_provider_desc(&exp_node_desc
, L
"Hwnd", L
"Provider_hwnd2", FALSE
);
12666 test_get_focused_elem(uia_iface
, NULL
, S_OK
, &exp_node_desc
, 2, 2, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
12667 test_get_focused_elem(uia_iface
, cache_req
, S_OK
, &exp_node_desc
, 2, 2, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
12670 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
12671 * Provider2, Provider_nc3 returns Provider_child.
12673 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12674 Provider_proxy
.focus_prov
= Provider_hwnd
.focus_prov
= NULL
;
12675 Provider_nc
.focus_prov
= &Provider_nc2
.IRawElementProviderFragment_iface
;
12676 Provider
.focus_prov
= &Provider2
.IRawElementProviderFragment_iface
;
12677 Provider_nc3
.focus_prov
= &Provider_child
.IRawElementProviderFragment_iface
;
12679 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), NULL
);
12680 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider_child", TRUE
);
12682 test_get_focused_elem(uia_iface
, NULL
, S_OK
, &exp_node_desc
, 2, 3, 2, 2, 1, TRUE
, FALSE
, FALSE
, TRUE
, FALSE
);
12683 test_get_focused_elem(uia_iface
, cache_req
, S_OK
, &exp_node_desc
, 2, 3, 2, 2, 1, TRUE
, FALSE
, FALSE
, TRUE
, FALSE
);
12686 * Provider_proxy returns Provider_child_child from GetFocus. The focus
12687 * provider is normalized against the cache request view condition.
12688 * Provider_child_child and its ancestors don't match the cache request
12689 * view condition, so we'll get no provider.
12691 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12692 initialize_provider(&Provider_child_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12693 provider_add_child(&Provider
, &Provider_child
);
12694 provider_add_child(&Provider_child
, &Provider_child_child
);
12695 Provider_proxy
.focus_prov
= &Provider_child_child
.IRawElementProviderFragment_iface
;
12696 Provider_nc
.focus_prov
= Provider_hwnd
.focus_prov
= NULL
;
12698 variant_init_bool(&v
, FALSE
);
12699 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
12700 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
12701 set_provider_prop_override(&Provider_child
, &prop_override
, 1);
12702 set_provider_prop_override(&Provider
, &prop_override
, 1);
12705 * GetFocusedElement returns UIA_E_ELEMENTNOTAVAILABLE when no provider
12706 * matches our view condition, GetFocusedElementBuildCache returns E_FAIL.
12708 init_node_provider_desc(&exp_node_desc
, 0, NULL
);
12709 test_get_focused_elem(uia_iface
, NULL
, UIA_E_ELEMENTNOTAVAILABLE
,
12710 &exp_node_desc
, 2, 2, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
12711 test_get_focused_elem(uia_iface
, cache_req
, E_FAIL
,
12712 &exp_node_desc
, 2, 2, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
12714 /* This time, Provider_child matches our view condition. */
12715 set_provider_prop_override(&Provider_child
, NULL
, 0);
12717 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), NULL
);
12718 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider_child", TRUE
);
12720 test_get_focused_elem(uia_iface
, NULL
, S_OK
, &exp_node_desc
, 1, 1, 1, 0, 0, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
);
12722 method_sequences_enabled
= TRUE
;
12723 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12724 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12725 initialize_provider(&Provider_child_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
12727 base_hwnd_prov
= nc_prov
= proxy_prov
= prov_root
= NULL
;
12728 IUIAutomationCacheRequest_Release(cache_req
);
12729 UiaRegisterProviderCallback(NULL
);
12730 DestroyWindow(hwnd
);
12731 UnregisterClassA("test_GetFocusedElement class", NULL
);
12732 UnregisterClassA("test_GetFocusedElement child class", NULL
);
12735 struct uia_com_classes
{
12740 static const struct uia_com_classes com_classes
[] = {
12741 { &CLSID_CUIAutomation
, &IID_IUnknown
},
12742 { &CLSID_CUIAutomation
, &IID_IUIAutomation
},
12743 { &CLSID_CUIAutomation8
, &IID_IUnknown
},
12744 { &CLSID_CUIAutomation8
, &IID_IUIAutomation
},
12745 { &CLSID_CUIAutomation8
, &IID_IUIAutomation2
},
12746 { &CLSID_CUIAutomation8
, &IID_IUIAutomation3
},
12747 { &CLSID_CUIAutomation8
, &IID_IUIAutomation4
},
12748 { &CLSID_CUIAutomation8
, &IID_IUIAutomation5
},
12749 { &CLSID_CUIAutomation8
, &IID_IUIAutomation6
},
12752 static void test_CUIAutomation(void)
12754 BOOL has_cui8
= TRUE
, tmp_b
;
12755 IUIAutomation
*uia_iface
;
12756 IUnknown
*unk1
, *unk2
;
12761 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
12763 for (i
= 0; i
< ARRAY_SIZE(com_classes
); i
++)
12765 IUnknown
*iface
= NULL
;
12767 hr
= CoCreateInstance(com_classes
[i
].clsid
, NULL
, CLSCTX_INPROC_SERVER
, com_classes
[i
].iid
,
12770 if ((com_classes
[i
].clsid
== &CLSID_CUIAutomation8
) && (hr
== REGDB_E_CLASSNOTREG
))
12772 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
12776 else if ((com_classes
[i
].clsid
== &CLSID_CUIAutomation8
) && (hr
== E_NOINTERFACE
) &&
12777 (com_classes
[i
].iid
!= &IID_IUIAutomation2
) && (com_classes
[i
].iid
!= &IID_IUIAutomation
) &&
12778 (com_classes
[i
].iid
!= &IID_IUnknown
))
12780 win_skip("No object for clsid %s, iid %s, skipping further tests.\n", debugstr_guid(com_classes
[i
].clsid
),
12781 debugstr_guid(com_classes
[i
].iid
));
12785 ok(hr
== S_OK
, "Failed to create interface for clsid %s, iid %s, hr %#lx\n",
12786 debugstr_guid(com_classes
[i
].clsid
), debugstr_guid(com_classes
[i
].iid
), hr
);
12787 ok(!!iface
, "iface == NULL\n");
12788 IUnknown_Release(iface
);
12792 hr
= CoCreateInstance(&CLSID_CUIAutomation8
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUIAutomation
,
12793 (void **)&uia_iface
);
12795 hr
= CoCreateInstance(&CLSID_CUIAutomation
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUIAutomation
,
12796 (void **)&uia_iface
);
12797 ok(hr
== S_OK
, "Failed to create IUIAutomation interface, hr %#lx\n", hr
);
12798 ok(!!uia_iface
, "uia_iface == NULL\n");
12800 /* Reserved value retrieval methods. */
12801 hr
= UiaGetReservedNotSupportedValue(&unk1
);
12802 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12804 hr
= IUIAutomation_get_ReservedNotSupportedValue(uia_iface
, &unk2
);
12805 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12806 ok(unk1
== unk2
, "unk1 != unk2\n");
12808 V_VT(&v
) = VT_UNKNOWN
;
12809 V_UNKNOWN(&v
) = unk1
;
12810 hr
= IUIAutomation_CheckNotSupported(uia_iface
, v
, &tmp_b
);
12811 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12812 ok(tmp_b
== TRUE
, "tmp_b != TRUE\n");
12814 IUnknown_Release(unk1
);
12815 IUnknown_Release(unk2
);
12817 hr
= UiaGetReservedMixedAttributeValue(&unk1
);
12818 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12820 hr
= IUIAutomation_get_ReservedMixedAttributeValue(uia_iface
, &unk2
);
12821 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12822 ok(unk1
== unk2
, "unk1 != unk2\n");
12824 V_VT(&v
) = VT_UNKNOWN
;
12825 V_UNKNOWN(&v
) = unk1
;
12826 hr
= IUIAutomation_CheckNotSupported(uia_iface
, v
, &tmp_b
);
12827 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12828 ok(tmp_b
== FALSE
, "tmp_b != FALSE\n");
12830 IUnknown_Release(unk1
);
12831 IUnknown_Release(unk2
);
12833 test_CUIAutomation_condition_ifaces(uia_iface
);
12834 test_CUIAutomation_value_conversion(uia_iface
);
12835 test_CUIAutomation_cache_request_iface(uia_iface
);
12836 test_CUIAutomation_TreeWalker_ifaces(uia_iface
);
12837 test_ElementFromHandle(uia_iface
, has_cui8
);
12838 test_Element_GetPropertyValue(uia_iface
);
12839 test_Element_cache_methods(uia_iface
);
12840 test_Element_Find(uia_iface
);
12841 test_GetRootElement(uia_iface
);
12842 test_GetFocusedElement(uia_iface
);
12844 IUIAutomation_Release(uia_iface
);
12848 static const struct prov_method_sequence default_hwnd_prov_props_seq
[] = {
12849 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
12850 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Windows 7. */
12851 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NativeWindowHandlePropertyId */
12852 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Windows 7. */
12853 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NamePropertyId */
12854 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Windows 7. */
12855 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_NamePropertyId */
12856 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Windows 7. */
12857 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ClassNamePropertyId */
12858 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Windows 7. */
12859 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ClassNamePropertyId */
12860 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_OPTIONAL
}, /* Only done on Windows 7. */
12861 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProcessIdPropertyId */
12862 { &Provider
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
12863 { &Provider_nc
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProcessIdPropertyId */
12864 { &Provider_nc
, PROV_GET_PROVIDER_OPTIONS
, METHOD_TODO
},
12868 #define test_node_hwnd_provider( node, hwnd ) \
12869 test_node_hwnd_provider_( (node), (hwnd), __FILE__, __LINE__)
12870 static void test_node_hwnd_provider_(HUIANODE node
, HWND hwnd
, const char *file
, int line
)
12872 WCHAR buf
[1024] = { 0 };
12877 winetest_push_context("UIA_NativeWindowHandlePropertyId");
12878 hr
= UiaGetPropertyValue(node
, UIA_NativeWindowHandlePropertyId
, &v
);
12879 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12880 ok_(file
, line
)(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
12881 ok_(file
, line
)(V_I4(&v
) == HandleToUlong(hwnd
), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v
), HandleToUlong(hwnd
));
12883 winetest_pop_context();
12885 winetest_push_context("UIA_NamePropertyId");
12886 SendMessageW(hwnd
, WM_GETTEXT
, ARRAY_SIZE(buf
), (LPARAM
)buf
);
12887 hr
= UiaGetPropertyValue(node
, UIA_NamePropertyId
, &v
);
12888 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12889 ok_(file
, line
)(V_VT(&v
) == VT_BSTR
, "Unexpected VT %d\n", V_VT(&v
));
12890 ok(!lstrcmpW(V_BSTR(&v
), buf
), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v
)));
12892 winetest_pop_context();
12894 winetest_push_context("UIA_ClassNamePropertyId");
12895 memset(buf
, 0, sizeof(buf
));
12896 GetClassNameW(hwnd
, buf
, ARRAY_SIZE(buf
));
12897 hr
= UiaGetPropertyValue(node
, UIA_ClassNamePropertyId
, &v
);
12898 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12899 ok_(file
, line
)(V_VT(&v
) == VT_BSTR
, "Unexpected VT %d\n", V_VT(&v
));
12900 ok(!lstrcmpW(V_BSTR(&v
), buf
), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v
)));
12902 winetest_pop_context();
12904 GetWindowThreadProcessId(hwnd
, &pid
);
12905 winetest_push_context("UIA_ProcessIdPropertyId");
12906 hr
= UiaGetPropertyValue(node
, UIA_ProcessIdPropertyId
, &v
);
12907 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
12908 ok_(file
, line
)(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
12909 ok_(file
, line
)(V_I4(&v
) == pid
, "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v
), pid
);
12911 winetest_pop_context();
12917 PARENT_HWND_DESKTOP
,
12920 struct uia_hwnd_control_type_test
{
12923 int exp_control_type
;
12924 int parent_hwnd_type
;
12927 static const struct uia_hwnd_control_type_test hwnd_control_type_test
[] = {
12928 { WS_OVERLAPPEDWINDOW
, 0, UIA_WindowControlTypeId
, PARENT_HWND_NULL
},
12929 /* Top-level window (parent is desktop window) is always a window control. */
12930 { WS_CHILD
, 0, UIA_WindowControlTypeId
, PARENT_HWND_DESKTOP
},
12931 /* Not a top-level window, considered a pane. */
12932 { WS_CHILD
, 0, UIA_PaneControlTypeId
, PARENT_HWND_HWND
},
12933 /* Not a top-level window, but WS_EX_APPWINDOW is always considered a window. */
12934 { WS_CHILD
, WS_EX_APPWINDOW
, UIA_WindowControlTypeId
, PARENT_HWND_HWND
},
12936 * WS_POPUP is always a pane regardless of being a top level window,
12937 * unless WS_CAPTION is set.
12939 { WS_CAPTION
| WS_POPUP
, 0, UIA_WindowControlTypeId
, PARENT_HWND_DESKTOP
},
12940 { WS_BORDER
| WS_POPUP
, 0, UIA_PaneControlTypeId
, PARENT_HWND_DESKTOP
},
12941 { WS_POPUP
, 0, UIA_PaneControlTypeId
, PARENT_HWND_DESKTOP
},
12943 * Top level window with WS_EX_TOOLWINDOW and without WS_CAPTION is
12944 * considered a pane.
12946 { WS_CHILD
, WS_EX_TOOLWINDOW
, UIA_PaneControlTypeId
, PARENT_HWND_DESKTOP
},
12947 { WS_CHILD
| WS_CAPTION
, WS_EX_TOOLWINDOW
, UIA_WindowControlTypeId
, PARENT_HWND_DESKTOP
},
12950 static void create_base_hwnd_test_node(HWND hwnd
, BOOL child_hwnd
, struct Provider
*main
, struct Provider
*nc
,
12951 HUIANODE
*ret_node
)
12953 ULONG main_ref
, nc_ref
;
12956 initialize_provider(nc
, ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
, hwnd
, TRUE
);
12957 initialize_provider(main
, ProviderOptions_ClientSideProvider
, hwnd
, TRUE
);
12958 nc
->ignore_hwnd_prop
= main
->ignore_hwnd_prop
= TRUE
;
12959 main_ref
= main
->ref
;
12964 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
12965 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
12966 prov_root
= &main
->IRawElementProviderSimple_iface
;
12970 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
12971 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
12972 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot
);
12973 child_win_prov_root
= &main
->IRawElementProviderSimple_iface
;
12976 hr
= UiaNodeFromProvider(&nc
->IRawElementProviderSimple_iface
, ret_node
);
12977 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12978 ok(main
->ref
== (main_ref
+ 1), "Unexpected refcnt %ld\n", main
->ref
);
12979 ok(nc
->ref
== (nc_ref
+ 1), "Unexpected refcnt %ld\n", nc
->ref
);
12982 /* Called while trying to get override provider. */
12983 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
12984 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
12987 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
12988 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
12989 Provider
.ret_invalid_prop_type
= Provider_nc
.ret_invalid_prop_type
= TRUE
;
12992 #define test_node_hwnd_provider_navigation( node, dir, exp_dest_hwnd ) \
12993 test_node_hwnd_provider_navigation_( (node), (dir), (exp_dest_hwnd), __FILE__, __LINE__)
12994 static void test_node_hwnd_provider_navigation_(HUIANODE node
, int nav_dir
, HWND exp_dest_hwnd
, const char *file
,
12997 struct UiaCacheRequest cache_req
= { NULL
, TreeScope_Element
, NULL
, 0, NULL
, 0, AutomationElementMode_Full
};
12998 const WCHAR
*exp_tree_struct
= exp_dest_hwnd
? L
"P)" : L
"";
12999 SAFEARRAY
*out_req
= NULL
;
13000 BSTR tree_struct
= NULL
;
13001 LONG idx
[2] = { 0 };
13007 hr
= UiaNavigate(node
, nav_dir
, (struct UiaCondition
*)&UiaTrueCondition
, &cache_req
, &out_req
, &tree_struct
);
13008 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13009 ok_(file
, line
)(!!out_req
, "out_req == NULL\n");
13010 ok_(file
, line
)(!!tree_struct
, "tree_struct == NULL\n");
13011 if (!exp_dest_hwnd
)
13014 for (i
= 0; i
< 2; i
++)
13016 hr
= SafeArrayGetLBound(out_req
, 1 + i
, &idx
[i
]);
13017 ok_(file
, line
)(hr
== S_OK
, "SafeArrayGetLBound unexpected hr %#lx\n", hr
);
13020 hr
= SafeArrayGetElement(out_req
, idx
, &v
);
13021 ok_(file
, line
)(hr
== S_OK
, "SafeArrayGetElement unexpected hr %#lx\n", hr
);
13023 hr
= UiaHUiaNodeFromVariant(&v
, &tmp_node
);
13024 ok_(file
, line
)(hr
== S_OK
, "UiaHUiaNodeFromVariant unexpected hr %#lx\n", hr
);
13025 ok_(file
, line
)(!!tmp_node
, "tmp_node == NULL\n");
13028 hr
= UiaGetPropertyValue(tmp_node
, UIA_NativeWindowHandlePropertyId
, &v
);
13029 ok_(file
, line
)(hr
== S_OK
, "UiaGetPropertyValue unexpected hr %#lx\n", hr
);
13030 ok_(file
, line
)(V_VT(&v
) == VT_I4
, "V_VT(&v) = %d\n", V_VT(&v
));
13031 ok_(file
, line
)(V_I4(&v
) == HandleToUlong(exp_dest_hwnd
), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v
),
13032 HandleToUlong(exp_dest_hwnd
));
13034 UiaNodeRelease(tmp_node
);
13037 ok_(file
, line
)(!wcscmp(tree_struct
, exp_tree_struct
), "unexpected tree structure %s\n", debugstr_w(tree_struct
));
13038 SafeArrayDestroy(out_req
);
13039 SysFreeString(tree_struct
);
13042 static void test_default_clientside_providers(void)
13044 struct UiaRect uia_rect
= { 0 };
13045 HWND hwnd
, hwnd_child
, hwnd2
;
13053 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
13054 hwnd
= create_test_hwnd("test_default_clientside_providers class");
13055 hwnd_child
= create_child_test_hwnd("test_default_clientside_providers child class", hwnd
);
13056 method_sequences_enabled
= FALSE
;
13058 hr
= UiaGetReservedNotSupportedValue(&unk_ns
);
13059 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13062 * Test default BaseHwnd provider. Unlike the other default providers, the
13063 * default BaseHwnd IRawElementProviderSimple is not available to test
13064 * directly. To isolate the BaseHwnd provider, we set the node's nonclient
13065 * provider to Provider_nc, and its Main provider to Provider. These
13066 * providers will return nothing so that we can isolate properties coming
13067 * from the BaseHwnd provider.
13069 create_base_hwnd_test_node(hwnd
, FALSE
, &Provider
, &Provider_nc
, &node
);
13071 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
13072 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13073 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
13074 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
13075 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", L
"Provider", FALSE
);
13076 check_node_provider_desc_todo(V_BSTR(&v
), L
"Hwnd", NULL
, TRUE
);
13079 method_sequences_enabled
= TRUE
;
13080 Provider
.ret_invalid_prop_type
= Provider_nc
.ret_invalid_prop_type
= TRUE
;
13081 test_node_hwnd_provider(node
, hwnd
);
13082 ok_method_sequence(default_hwnd_prov_props_seq
, "default_hwnd_prov_props_seq");
13083 method_sequences_enabled
= FALSE
;
13085 /* Get the bounding rectangle from the default BaseHwnd provider. */
13086 GetWindowRect(hwnd
, &rect
);
13087 set_uia_rect(&uia_rect
, rect
.left
, rect
.top
, (rect
.right
- rect
.left
), (rect
.bottom
- rect
.top
));
13088 hr
= UiaGetPropertyValue(node
, UIA_BoundingRectanglePropertyId
, &v
);
13089 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13090 check_uia_rect_val(&v
, &uia_rect
);
13093 /* Minimized top-level HWNDs don't return a bounding rectangle. */
13094 ShowWindow(hwnd
, SW_MINIMIZE
);
13095 hr
= UiaGetPropertyValue(node
, UIA_BoundingRectanglePropertyId
, &v
);
13096 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13097 ok(V_VT(&v
) == VT_UNKNOWN
, "Unexpected vt %d\n", V_VT(&v
));
13098 ok(V_UNKNOWN(&v
) == unk_ns
, "unexpected IUnknown %p\n", V_UNKNOWN(&v
));
13101 UiaNodeRelease(node
);
13102 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
13103 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
13105 /* Create a child window node. */
13106 create_base_hwnd_test_node(hwnd_child
, TRUE
, &Provider
, &Provider_nc
, &node
);
13107 test_node_hwnd_provider(node
, hwnd_child
);
13109 /* Get the bounding rectangle from the default BaseHwnd provider. */
13110 GetWindowRect(hwnd_child
, &rect
);
13111 set_uia_rect(&uia_rect
, rect
.left
, rect
.top
, (rect
.right
- rect
.left
), (rect
.bottom
- rect
.top
));
13112 hr
= UiaGetPropertyValue(node
, UIA_BoundingRectanglePropertyId
, &v
);
13113 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13114 check_uia_rect_val(&v
, &uia_rect
);
13117 /* Minimized non top-level HWNDs return a bounding rectangle. */
13118 ShowWindow(hwnd_child
, SW_MINIMIZE
);
13119 GetWindowRect(hwnd_child
, &rect
);
13120 set_uia_rect(&uia_rect
, rect
.left
, rect
.top
, (rect
.right
- rect
.left
), (rect
.bottom
- rect
.top
));
13121 hr
= UiaGetPropertyValue(node
, UIA_BoundingRectanglePropertyId
, &v
);
13122 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13123 check_uia_rect_val(&v
, &uia_rect
);
13126 UiaNodeRelease(node
);
13127 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
13128 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
13131 for (i
= 0; i
< ARRAY_SIZE(hwnd_control_type_test
); i
++)
13133 const struct uia_hwnd_control_type_test
*test
= &hwnd_control_type_test
[i
];
13136 if (test
->parent_hwnd_type
== PARENT_HWND_HWND
)
13138 else if (test
->parent_hwnd_type
== PARENT_HWND_DESKTOP
)
13139 parent
= GetDesktopWindow();
13143 hwnd2
= CreateWindowExA(test
->style_ex
, "test_default_clientside_providers class", "Test window", test
->style
,
13144 0, 0, 100, 100, parent
, NULL
, NULL
, NULL
);
13145 initialize_provider(&Provider_nc
, ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
, hwnd2
, TRUE
);
13146 initialize_provider(&Provider
, ProviderOptions_ClientSideProvider
, hwnd2
, TRUE
);
13147 Provider_nc
.ignore_hwnd_prop
= Provider
.ignore_hwnd_prop
= TRUE
;
13148 Provider
.ret_invalid_prop_type
= Provider_nc
.ret_invalid_prop_type
= TRUE
;
13150 /* If parent is hwnd, it will be queried for an override provider. */
13151 if (test
->style
== WS_CHILD
&& (parent
== hwnd
))
13152 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
13154 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
13155 /* Only sent on Win7. */
13156 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
13157 hr
= UiaNodeFromProvider(&Provider_nc
.IRawElementProviderSimple_iface
, &node
);
13158 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13159 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
13160 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
13161 if (hwnd_control_type_test
[i
].style
== WS_CHILD
&& (parent
== hwnd
))
13162 todo_wine
CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot
, 2);
13164 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
13165 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
13167 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
13168 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13169 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
13170 ok(V_I4(&v
) == test
->exp_control_type
, "Unexpected control type %ld\n", V_I4(&v
));
13173 UiaNodeRelease(node
);
13174 DestroyWindow(hwnd2
);
13178 * Default ProviderType_BaseHwnd provider navigation tests.
13180 create_base_hwnd_test_node(hwnd
, FALSE
, &Provider
, &Provider_nc
, &node
);
13181 test_node_hwnd_provider(node
, hwnd
);
13184 * Navigate to the parent of our top-level HWND, will get a node
13185 * representing the desktop HWND.
13187 test_node_hwnd_provider_navigation(node
, NavigateDirection_Parent
, GetDesktopWindow());
13188 UiaNodeRelease(node
);
13191 * Create a node repesenting an HWND that is a top-level window, but is
13192 * owned by another window. For top-level HWNDs, parent navigation will go
13193 * to the owner instead of the parent.
13195 hwnd2
= CreateWindowA("test_default_clientside_providers class", "Test window", WS_POPUP
, 0, 0, 50, 50, hwnd
, NULL
,
13197 ok(GetAncestor(hwnd2
, GA_PARENT
) == GetDesktopWindow(), "unexpected parent hwnd");
13198 ok(GetWindow(hwnd2
, GW_OWNER
) == hwnd
, "unexpected owner hwnd");
13199 create_base_hwnd_test_node(hwnd2
, FALSE
, &Provider
, &Provider_nc
, &node
);
13200 test_node_hwnd_provider(node
, hwnd2
);
13202 /* Navigate to the parent. */
13203 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
13204 /* Only sent on Win7. */
13205 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
13206 test_node_hwnd_provider_navigation(node
, NavigateDirection_Parent
, hwnd
);
13207 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
13208 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
13210 UiaNodeRelease(node
);
13211 DestroyWindow(hwnd2
);
13214 * Create a node for our child window.
13216 initialize_provider(&Provider2
, ProviderOptions_ServerSideProvider
, hwnd
, TRUE
);
13217 Provider2
.ignore_hwnd_prop
= TRUE
;
13218 prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
13219 create_base_hwnd_test_node(hwnd_child
, TRUE
, &Provider
, &Provider_nc
, &node
);
13220 test_node_hwnd_provider(node
, hwnd_child
);
13222 /* Navigate to parent. */
13223 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
13224 /* Only sent on Win7. */
13225 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
13226 test_node_hwnd_provider_navigation(node
, NavigateDirection_Parent
, hwnd
);
13227 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
13228 called_winproc_GETOBJECT_CLIENT
= expect_winproc_GETOBJECT_CLIENT
= 0;
13230 UiaNodeRelease(node
);
13234 * Test default ProviderType_Proxy clientside provider. Provider will be
13235 * the HWND provider for this node, and Accessible will be the main
13238 initialize_provider(&Provider
, ProviderOptions_ClientSideProvider
, hwnd
, FALSE
);
13239 set_accessible_props(&Accessible
, ROLE_SYSTEM_TEXT
, STATE_SYSTEM_FOCUSABLE
, 0, L
"Accessible", 0, 0, 20, 20);
13240 set_accessible_ia2_props(&Accessible
, FALSE
, 0);
13241 acc_client
= &Accessible
.IAccessible_iface
;
13242 prov_root
= child_win_prov_root
= NULL
;
13244 SET_EXPECT(Accessible_QI_IAccIdentity
);
13245 SET_EXPECT(Accessible_get_accParent
);
13246 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
13247 /* Only sent twice on Win7. */
13248 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT
, 2);
13249 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
13250 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13251 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
13252 ok(Accessible
.ref
>= 2, "Unexpected refcnt %ld\n", Accessible
.ref
);
13253 todo_wine
CHECK_CALLED(Accessible_QI_IAccIdentity
);
13254 todo_wine
CHECK_CALLED(Accessible_get_accParent
);
13255 CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
13256 CHECK_CALLED(winproc_GETOBJECT_CLIENT
);
13258 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
13259 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13260 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd
);
13261 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider", FALSE
);
13262 check_node_provider_desc_todo(V_BSTR(&v
), L
"Nonclient", NULL
, FALSE
);
13263 check_node_provider_desc(V_BSTR(&v
), L
"Main", NULL
, TRUE
);
13266 SET_EXPECT(Accessible_get_accRole
);
13267 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
13268 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13269 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
13270 ok(V_I4(&v
) == UIA_EditControlTypeId
, "Unexpected I4 %#lx\n", V_I4(&v
));
13272 CHECK_CALLED(Accessible_get_accRole
);
13274 UiaNodeRelease(node
);
13275 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
13276 ok(Accessible
.ref
== 1, "Unexpected refcnt %ld\n", Accessible
.ref
);
13279 * Unlike UiaProviderFromIAccessible which won't create a provider for an
13280 * MSAA proxy, the default clientside proxy provider will.
13282 hwnd2
= CreateWindowA("EDIT", "", WS_VISIBLE
| WS_CHILD
| ES_PASSWORD
,
13283 0, 0, 100, 100, hwnd
, NULL
, NULL
, NULL
);
13284 initialize_provider(&Provider
, ProviderOptions_ClientSideProvider
, hwnd2
, FALSE
);
13286 /* Tries to get override provider from parent HWND. */
13287 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
13288 hr
= UiaNodeFromProvider(&Provider
.IRawElementProviderSimple_iface
, &node
);
13289 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13290 ok(Provider
.ref
== 2, "Unexpected refcnt %ld\n", Provider
.ref
);
13291 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
13293 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
13294 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13295 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), hwnd2
);
13296 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider", FALSE
);
13297 check_node_provider_desc_todo(V_BSTR(&v
), L
"Main", NULL
, FALSE
);
13298 check_node_provider_desc_todo(V_BSTR(&v
), L
"Annotation", NULL
, TRUE
);
13301 hr
= UiaGetPropertyValue(node
, UIA_ControlTypePropertyId
, &v
);
13302 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13303 ok(V_VT(&v
) == VT_I4
, "Unexpected VT %d\n", V_VT(&v
));
13304 ok(V_I4(&v
) == UIA_EditControlTypeId
, "Unexpected I4 %#lx\n", V_I4(&v
));
13307 hr
= UiaGetPropertyValue(node
, UIA_IsPasswordPropertyId
, &v
);
13308 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13309 ok(V_VT(&v
) == VT_BOOL
, "Unexpected VT %d\n", V_VT(&v
));
13310 ok(check_variant_bool(&v
, TRUE
), "V_BOOL(&v) = %#x\n", V_BOOL(&v
));
13313 UiaNodeRelease(node
);
13314 DestroyWindow(hwnd2
);
13316 set_accessible_props(&Accessible
, 0, 0, 0, NULL
, 0, 0, 0, 0);
13318 prov_root
= child_win_prov_root
= NULL
;
13320 method_sequences_enabled
= TRUE
;
13321 DestroyWindow(hwnd
);
13322 DestroyWindow(hwnd_child
);
13323 UnregisterClassA("test_default_clientside_providers class", NULL
);
13324 UnregisterClassA("test_default_clientside_providers child class", NULL
);
13326 IUnknown_Release(unk_ns
);
13330 static void test_UiaGetRootNode(void)
13336 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
13337 UiaRegisterProviderCallback(test_uia_provider_callback
);
13340 * UiaGetRootNode is the same as calling UiaNodeFromHandle with the
13341 * desktop window handle.
13343 set_clientside_providers_for_hwnd(&Provider_proxy
, &Provider_nc
, &Provider_hwnd
, GetDesktopWindow());
13344 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
13345 proxy_prov
= &Provider_proxy
.IRawElementProviderSimple_iface
;
13346 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
13348 method_sequences_enabled
= FALSE
;
13349 SET_EXPECT(prov_callback_base_hwnd
);
13350 SET_EXPECT(prov_callback_nonclient
);
13351 SET_EXPECT(prov_callback_proxy
);
13352 hr
= UiaGetRootNode(&node
);
13353 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13354 ok(!!node
, "Node == NULL.\n");
13355 ok(Provider_proxy
.ref
== 2, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
13356 ok(Provider_hwnd
.ref
== 2, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
13357 ok(Provider_nc
.ref
== 2, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
13358 CHECK_CALLED(prov_callback_base_hwnd
);
13359 CHECK_CALLED(prov_callback_nonclient
);
13360 CHECK_CALLED(prov_callback_proxy
);
13362 hr
= UiaGetPropertyValue(node
, UIA_ProviderDescriptionPropertyId
, &v
);
13363 ok(hr
== S_OK
, "Unexpected hr %#lx\n", hr
);
13364 check_node_provider_desc_prefix(V_BSTR(&v
), GetCurrentProcessId(), GetDesktopWindow());
13365 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider_proxy", TRUE
);
13366 check_node_provider_desc(V_BSTR(&v
), L
"Hwnd", L
"Provider_hwnd", FALSE
);
13367 check_node_provider_desc(V_BSTR(&v
), L
"Nonclient", L
"Provider_nc", FALSE
);
13370 ok(UiaNodeRelease(node
), "UiaNodeRelease returned FALSE\n");
13371 ok(Provider_proxy
.ref
== 1, "Unexpected refcnt %ld\n", Provider_proxy
.ref
);
13372 ok(Provider_hwnd
.ref
== 1, "Unexpected refcnt %ld\n", Provider_hwnd
.ref
);
13373 ok(Provider_nc
.ref
== 1, "Unexpected refcnt %ld\n", Provider_nc
.ref
);
13375 initialize_provider(&Provider_hwnd
, ProviderOptions_ClientSideProvider
, NULL
, TRUE
);
13376 initialize_provider(&Provider_nc
, ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
, NULL
,
13378 initialize_provider(&Provider_proxy
, ProviderOptions_ClientSideProvider
, NULL
, TRUE
);
13379 base_hwnd_prov
= proxy_prov
= nc_prov
= NULL
;
13381 method_sequences_enabled
= TRUE
;
13382 UiaRegisterProviderCallback(NULL
);
13386 #define test_node_from_focus( cache_req, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, nc_cback_count, \
13387 win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, base_hwnd_cback_todo, \
13388 nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo) \
13389 test_node_from_focus_( (cache_req), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), (nc_cback_count), \
13390 (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), (base_hwnd_cback_todo), \
13391 (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
13392 static void test_node_from_focus_(struct UiaCacheRequest
*cache_req
, struct node_provider_desc
*exp_node_desc
,
13393 int proxy_cback_count
, int base_hwnd_cback_count
, int nc_cback_count
, int win_get_obj_count
,
13394 int child_win_get_obj_count
, BOOL proxy_cback_todo
, BOOL base_hwnd_cback_todo
, BOOL nc_cback_todo
,
13395 BOOL win_get_obj_todo
, BOOL child_win_get_obj_todo
, const char *file
, int line
)
13397 const WCHAR
*exp_tree_struct
= exp_node_desc
->prov_count
? L
"P)" : L
"";
13398 LONG exp_lbound
[2], exp_elems
[2];
13399 SAFEARRAY
*out_req
= NULL
;
13400 BSTR tree_struct
= NULL
;
13403 SET_EXPECT_MULTI(prov_callback_base_hwnd
, base_hwnd_cback_count
);
13404 SET_EXPECT_MULTI(prov_callback_nonclient
, nc_cback_count
);
13405 SET_EXPECT_MULTI(prov_callback_proxy
, proxy_cback_count
);
13406 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot
, win_get_obj_count
);
13407 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot
, child_win_get_obj_count
);
13408 hr
= UiaNodeFromFocus(cache_req
, &out_req
, &tree_struct
);
13409 ok_(file
, line
)(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
13410 if (exp_node_desc
->prov_count
)
13411 ok_(file
, line
)(!!out_req
, "out_req == NULL\n");
13413 ok_(file
, line
)(!out_req
, "out_req != NULL\n");
13414 ok_(file
, line
)(!!tree_struct
, "tree_struct == NULL\n");
13415 todo_wine_if(base_hwnd_cback_todo
) CHECK_CALLED_MULTI(prov_callback_base_hwnd
, base_hwnd_cback_count
);
13416 todo_wine_if(proxy_cback_todo
) CHECK_CALLED_MULTI(prov_callback_proxy
, proxy_cback_count
);
13417 todo_wine_if(nc_cback_todo
) CHECK_CALLED_MULTI(prov_callback_nonclient
, nc_cback_count
);
13418 todo_wine_if(win_get_obj_todo
) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot
, win_get_obj_count
);
13419 todo_wine_if(child_win_get_obj_todo
) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot
, child_win_get_obj_count
);
13421 ok_(file
, line
)(!wcscmp(tree_struct
, exp_tree_struct
), "unexpected tree structure %s\n", debugstr_w(tree_struct
));
13422 if (exp_node_desc
->prov_count
)
13424 exp_lbound
[0] = exp_lbound
[1] = 0;
13426 exp_elems
[1] = 1 + cache_req
->cProperties
;
13427 test_cache_req_sa_(out_req
, exp_lbound
, exp_elems
, exp_node_desc
, file
, line
);
13430 SafeArrayDestroy(out_req
);
13431 SysFreeString(tree_struct
);
13434 static void test_UiaNodeFromFocus(void)
13436 struct Provider_prop_override prop_override
;
13437 struct node_provider_desc exp_node_desc
;
13438 struct UiaPropertyCondition prop_cond
;
13439 struct UiaCacheRequest cache_req
;
13440 struct UiaNotCondition not_cond
;
13441 HWND hwnd
, hwnd_child
;
13445 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
13447 hwnd
= create_test_hwnd("UiaNodeFromFocus class");
13448 hwnd_child
= create_child_test_hwnd("UiaNodeFromFocus child class", hwnd
);
13450 UiaRegisterProviderCallback(test_uia_provider_callback
);
13452 /* Set clientside providers for our test windows and the desktop. */
13453 set_clientside_providers_for_hwnd(&Provider_proxy
, &Provider_nc
, &Provider_hwnd
, GetDesktopWindow());
13454 base_hwnd_prov
= &Provider_hwnd
.IRawElementProviderSimple_iface
;
13455 nc_prov
= &Provider_nc
.IRawElementProviderSimple_iface
;
13456 proxy_prov
= &Provider_proxy
.IRawElementProviderSimple_iface
;
13458 set_clientside_providers_for_hwnd(NULL
, &Provider_nc2
, &Provider_hwnd2
, hwnd
);
13459 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, hwnd
, TRUE
);
13460 Provider
.frag_root
= &Provider
.IRawElementProviderFragmentRoot_iface
;
13461 prov_root
= &Provider
.IRawElementProviderSimple_iface
;
13462 Provider
.ignore_hwnd_prop
= TRUE
;
13464 set_clientside_providers_for_hwnd(NULL
, &Provider_nc3
, &Provider_hwnd3
, hwnd_child
);
13465 initialize_provider(&Provider2
, ProviderOptions_ServerSideProvider
, hwnd_child
, TRUE
);
13466 Provider2
.frag_root
= &Provider2
.IRawElementProviderFragmentRoot_iface
;
13467 child_win_prov_root
= &Provider2
.IRawElementProviderSimple_iface
;
13468 Provider2
.ignore_hwnd_prop
= TRUE
;
13471 * Nodes are normalized against the cache request view condition. Here,
13472 * we're setting it to the same as the default ControlView.
13474 variant_init_bool(&v
, FALSE
);
13475 set_property_condition(&prop_cond
, UIA_IsControlElementPropertyId
, &v
, PropertyConditionFlags_None
);
13476 set_not_condition(¬_cond
, (struct UiaCondition
*)&prop_cond
);
13477 cache_prop
= UIA_RuntimeIdPropertyId
;
13478 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_cond
, TreeScope_Element
, &cache_prop
, 1, NULL
, 0,
13479 AutomationElementMode_Full
);
13482 * None of the providers for the desktop node return a provider from
13483 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
13486 method_sequences_enabled
= FALSE
;
13487 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), GetDesktopWindow());
13488 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider_proxy", TRUE
);
13489 add_provider_desc(&exp_node_desc
, L
"Nonclient", L
"Provider_nc", FALSE
);
13490 add_provider_desc(&exp_node_desc
, L
"Hwnd", L
"Provider_hwnd", FALSE
);
13492 test_node_from_focus(&cache_req
, &exp_node_desc
, 1, 1, 1, 0, 0, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
);
13494 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
13495 Provider_hwnd
.focus_prov
= &Provider_hwnd2
.IRawElementProviderFragment_iface
;
13497 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), hwnd
);
13498 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider", TRUE
);
13499 add_provider_desc(&exp_node_desc
, L
"Nonclient", L
"Provider_nc2", FALSE
);
13500 add_provider_desc(&exp_node_desc
, L
"Hwnd", L
"Provider_hwnd2", FALSE
);
13502 test_node_from_focus(&cache_req
, &exp_node_desc
, 2, 1, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
13505 * Provider_proxy returns Provider from GetFocus. The provider that
13506 * creates the node will not have GetFocus called on it to avoid returning
13507 * the same provider twice. Similarly, on nodes other than the desktop
13508 * node, the HWND provider will not have GetFocus called on it.
13510 Provider_hwnd
.focus_prov
= NULL
;
13511 Provider_proxy
.focus_prov
= &Provider
.IRawElementProviderFragment_iface
;
13512 Provider
.focus_prov
= Provider_hwnd2
.focus_prov
= &Provider2
.IRawElementProviderFragment_iface
;
13514 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), hwnd
);
13515 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider", TRUE
);
13516 add_provider_desc(&exp_node_desc
, L
"Nonclient", L
"Provider_nc2", FALSE
);
13517 add_provider_desc(&exp_node_desc
, L
"Hwnd", L
"Provider_hwnd2", FALSE
);
13519 test_node_from_focus(&cache_req
, &exp_node_desc
, 2, 2, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
13522 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
13523 * Provider2, Provider_nc3 returns Provider_child.
13525 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
13526 Provider_proxy
.focus_prov
= Provider_hwnd
.focus_prov
= Provider_hwnd2
.focus_prov
= NULL
;
13527 Provider_nc
.focus_prov
= &Provider_nc2
.IRawElementProviderFragment_iface
;
13528 Provider
.focus_prov
= &Provider2
.IRawElementProviderFragment_iface
;
13529 Provider_nc3
.focus_prov
= &Provider_child
.IRawElementProviderFragment_iface
;
13531 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), NULL
);
13532 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider_child", TRUE
);
13534 test_node_from_focus(&cache_req
, &exp_node_desc
, 2, 3, 2, 2, 1, TRUE
, FALSE
, FALSE
, TRUE
, FALSE
);
13537 * Provider_proxy returns Provider_child_child from GetFocus. The focus
13538 * provider is normalized against the cache request view condition.
13539 * Provider_child_child and its ancestors don't match the cache request
13540 * view condition, so we'll get no provider.
13542 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
13543 initialize_provider(&Provider_child_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
13544 provider_add_child(&Provider
, &Provider_child
);
13545 provider_add_child(&Provider_child
, &Provider_child_child
);
13546 Provider_proxy
.focus_prov
= &Provider_child_child
.IRawElementProviderFragment_iface
;
13547 Provider_nc
.focus_prov
= Provider_hwnd
.focus_prov
= NULL
;
13549 variant_init_bool(&v
, FALSE
);
13550 set_property_override(&prop_override
, UIA_IsControlElementPropertyId
, &v
);
13551 set_provider_prop_override(&Provider_child_child
, &prop_override
, 1);
13552 set_provider_prop_override(&Provider_child
, &prop_override
, 1);
13553 set_provider_prop_override(&Provider
, &prop_override
, 1);
13555 init_node_provider_desc(&exp_node_desc
, 0, NULL
);
13556 test_node_from_focus(&cache_req
, &exp_node_desc
, 2, 2, 2, 1, 0, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
);
13558 /* This time, Provider_child matches our view condition. */
13559 set_provider_prop_override(&Provider_child
, NULL
, 0);
13561 init_node_provider_desc(&exp_node_desc
, GetCurrentProcessId(), NULL
);
13562 add_provider_desc(&exp_node_desc
, L
"Main", L
"Provider_child", TRUE
);
13564 test_node_from_focus(&cache_req
, &exp_node_desc
, 1, 1, 1, 0, 0, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
);
13566 method_sequences_enabled
= TRUE
;
13567 initialize_provider(&Provider
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
13568 initialize_provider(&Provider_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
13569 initialize_provider(&Provider_child_child
, ProviderOptions_ServerSideProvider
, NULL
, TRUE
);
13572 UiaRegisterProviderCallback(NULL
);
13573 DestroyWindow(hwnd
);
13574 UnregisterClassA("UiaNodeFromFocus class", NULL
);
13575 UnregisterClassA("UiaNodeFromFocus child class", NULL
);
13579 * Once a process returns a UI Automation provider with
13580 * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This
13581 * messes with tests around COM initialization, so we run these tests in
13582 * separate processes.
13584 static void launch_test_process(const char *name
, const char *test_name
)
13586 PROCESS_INFORMATION proc
;
13587 STARTUPINFOA startup
;
13588 char cmdline
[MAX_PATH
];
13590 sprintf(cmdline
, "\"%s\" uiautomation %s", name
, test_name
);
13591 memset(&startup
, 0, sizeof(startup
));
13592 startup
.cb
= sizeof(startup
);
13593 CreateProcessA(NULL
, cmdline
, NULL
, NULL
, FALSE
, 0, NULL
, NULL
, &startup
, &proc
);
13594 wait_child_process(proc
.hProcess
);
13597 START_TEST(uiautomation
)
13599 HMODULE uia_dll
= LoadLibraryA("uiautomationcore.dll");
13600 BOOL (WINAPI
*pImmDisableIME
)(DWORD
);
13601 HMODULE hModuleImm32
;
13605 /* Make sure COM isn't initialized by imm32. */
13606 hModuleImm32
= LoadLibraryA("imm32.dll");
13607 if (hModuleImm32
) {
13608 pImmDisableIME
= (void *)GetProcAddress(hModuleImm32
, "ImmDisableIME");
13609 if (pImmDisableIME
)
13612 pImmDisableIME
= NULL
;
13613 FreeLibrary(hModuleImm32
);
13616 pUiaDisconnectProvider
= (void *)GetProcAddress(uia_dll
, "UiaDisconnectProvider");
13618 argc
= winetest_get_mainargs(&argv
);
13621 if (!strcmp(argv
[2], "UiaNodeFromHandle"))
13622 test_UiaNodeFromHandle(argv
[0]);
13623 else if (!strcmp(argv
[2], "UiaNodeFromHandle_client_proc"))
13624 test_UiaNodeFromHandle_client_proc();
13625 else if (!strcmp(argv
[2], "UiaRegisterProviderCallback"))
13626 test_UiaRegisterProviderCallback();
13628 FreeLibrary(uia_dll
);
13632 test_UiaHostProviderFromHwnd();
13633 test_uia_reserved_value_ifaces();
13634 test_UiaLookupId();
13635 test_UiaNodeFromProvider();
13636 test_UiaGetPropertyValue();
13637 test_UiaGetRuntimeId();
13638 test_UiaHUiaNodeFromVariant();
13639 launch_test_process(argv
[0], "UiaNodeFromHandle");
13640 launch_test_process(argv
[0], "UiaRegisterProviderCallback");
13641 test_UiaGetUpdatedCache();
13642 test_UiaNavigate();
13644 test_CUIAutomation();
13645 test_default_clientside_providers();
13646 test_UiaGetRootNode();
13647 test_UiaNodeFromFocus();
13650 pUiaProviderFromIAccessible
= (void *)GetProcAddress(uia_dll
, "UiaProviderFromIAccessible");
13651 if (pUiaProviderFromIAccessible
)
13652 test_UiaProviderFromIAccessible();
13654 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
13656 FreeLibrary(uia_dll
);