uiautomationcore: Retrieve runtime ID on UiaReturnRawElementProvider thread to preven...
[wine.git] / dlls / uiautomationcore / tests / uiautomation.c
blob35f2f18ffcf3b953ddffabe030726265b262b226
1 /*
2 * UI Automation tests
4 * Copyright 2019 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <assert.h>
24 #include "windows.h"
25 #include "initguid.h"
26 #include "uiautomation.h"
27 #include "ocidl.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) \
45 do { \
46 ok(expect_ ##func, "unexpected call " #func "\n"); \
47 called_ ## func++; \
48 }while(0)
50 #define CHECK_EXPECT(func) \
51 do { \
52 CHECK_EXPECT2(func); \
53 expect_ ## func--; \
54 }while(0)
56 #define CHECK_CALLED(func) \
57 do { \
58 ok(called_ ## func, "expected " #func "\n"); \
59 expect_ ## func = called_ ## func = 0; \
60 }while(0)
62 #define CHECK_CALLED_MULTI(func, num) \
63 do { \
64 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
65 expect_ ## func = called_ ## func = 0; \
66 }while(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)
114 return TRUE;
116 return FALSE;
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))
122 return TRUE;
124 return FALSE;
127 static void variant_init_bool(VARIANT *v, BOOL val)
129 V_VT(v) = VT_BOOL;
130 V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE;
133 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
135 IUnknown *unk1, *unk2;
136 BOOL cmp;
138 IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
139 IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
140 cmp = unk1 == unk2;
142 IUnknown_Release(unk1);
143 IUnknown_Release(unk2);
144 return cmp;
147 static struct Accessible
149 IAccessible IAccessible_iface;
150 IAccessible2 IAccessible2_iface;
151 IOleWindow IOleWindow_iface;
152 IServiceProvider IServiceProvider_iface;
153 LONG ref;
155 IAccessible *parent;
156 HWND acc_hwnd;
157 HWND ow_hwnd;
158 INT role;
159 INT state;
160 LONG child_count;
161 LPCWSTR name;
162 LONG left, top, width, height;
163 BOOL enable_ia2;
164 LONG unique_id;
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);
176 *obj = NULL;
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))
190 *obj = iface;
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;
197 else
198 return E_NOINTERFACE;
200 IAccessible_AddRef(iface);
201 return S_OK;
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");
219 return E_NOTIMPL;
222 static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface, UINT iTInfo,
223 LCID lcid, ITypeInfo **out_tinfo)
225 ok(0, "unexpected call\n");
226 return E_NOTIMPL;
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");
233 return E_NOTIMPL;
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");
241 return E_NOTIMPL;
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);
254 else
255 CHECK_EXPECT(Accessible_get_accParent);
257 if (This->parent)
258 return IAccessible_QueryInterface(This->parent, &IID_IDispatch, (void **)out_parent);
260 *out_parent = NULL;
261 return S_FALSE;
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);
274 else
275 CHECK_EXPECT(Accessible_get_accChildCount);
277 if (This->child_count)
279 *out_count = This->child_count;
280 return S_OK;
283 return E_NOTIMPL;
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");
294 *out_child = NULL;
295 if (V_VT(&child_id) != VT_I4)
296 return E_INVALIDARG;
298 if (This == &Accessible)
300 switch (V_I4(&child_id))
302 case CHILDID_SELF:
303 return IAccessible_QueryInterface(&This->IAccessible_iface, &IID_IDispatch, (void **)out_child);
305 /* Simple element children. */
306 case 1:
307 case 3:
308 return S_FALSE;
310 case 2:
311 return IAccessible_QueryInterface(&Accessible_child.IAccessible_iface, &IID_IDispatch, (void **)out_child);
313 case 4:
314 return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
316 default:
317 break;
321 return E_NOTIMPL;
324 static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_id,
325 BSTR *out_name)
327 struct Accessible *This = impl_from_Accessible(iface);
329 *out_name = NULL;
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);
336 else
337 CHECK_EXPECT(Accessible_get_accName);
339 if (This->name)
341 *out_name = SysAllocString(This->name);
342 return S_OK;
345 return E_NOTIMPL;
348 static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface, VARIANT child_id,
349 BSTR *out_value)
351 ok(0, "unexpected call\n");
352 return E_NOTIMPL;
355 static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface, VARIANT child_id,
356 BSTR *out_description)
358 ok(0, "unexpected call\n");
359 return E_NOTIMPL;
362 static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_id,
363 VARIANT *out_role)
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);
373 else
374 CHECK_EXPECT(Accessible_get_accRole);
376 if (This->role)
378 V_VT(out_role) = VT_I4;
379 V_I4(out_role) = This->role;
380 return S_OK;
383 return E_NOTIMPL;
386 static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_id,
387 VARIANT *out_state)
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);
397 else
398 CHECK_EXPECT(Accessible_get_accState);
400 if (V_VT(&child_id) != VT_I4)
401 return E_INVALIDARG;
403 if (This == &Accessible && V_I4(&child_id) != CHILDID_SELF)
405 switch (V_I4(&child_id))
407 case 1:
408 V_VT(out_state) = VT_I4;
409 V_I4(out_state) = STATE_SYSTEM_INVISIBLE;
410 break;
412 case 3:
413 V_VT(out_state) = VT_I4;
414 V_I4(out_state) = STATE_SYSTEM_FOCUSABLE;
415 break;
417 default:
418 return E_INVALIDARG;
421 return S_OK;
424 if (This->state)
426 V_VT(out_state) = VT_I4;
427 V_I4(out_state) = This->state;
428 return S_OK;
431 return E_NOTIMPL;
434 static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface, VARIANT child_id,
435 BSTR *out_help)
437 ok(0, "unexpected call\n");
438 return E_NOTIMPL;
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");
445 return E_NOTIMPL;
448 static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VARIANT child_id,
449 BSTR *out_kbd_shortcut)
451 ok(0, "unexpected call\n");
452 return E_NOTIMPL;
455 static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pchild_id)
457 ok(0, "unexpected call\n");
458 return E_NOTIMPL;
461 static HRESULT WINAPI Accessible_get_accSelection(IAccessible *iface, VARIANT *out_selection)
463 ok(0, "unexpected call\n");
464 return E_NOTIMPL;
467 static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface, VARIANT child_id,
468 BSTR *out_default_action)
470 ok(0, "unexpected call\n");
471 return E_NOTIMPL;
474 static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, LONG select_flags,
475 VARIANT child_id)
477 ok(0, "unexpected call\n");
478 return E_NOTIMPL;
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);
492 else
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;
501 return S_OK;
504 return E_NOTIMPL;
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);
516 else
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) &&
525 This->acc_hwnd)
527 V_VT(out_var) = VT_I4;
528 V_I4(out_var) = HandleToUlong(This->acc_hwnd);
529 return S_OK;
531 return S_FALSE;
534 static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface, LONG left, LONG top,
535 VARIANT *out_child_id)
537 ok(0, "unexpected call\n");
538 return E_NOTIMPL;
541 static HRESULT WINAPI Accessible_accDoDefaultAction(IAccessible *iface, VARIANT child_id)
543 ok(0, "unexpected call\n");
544 return E_NOTIMPL;
547 static HRESULT WINAPI Accessible_put_accName(IAccessible *iface, VARIANT child_id,
548 BSTR name)
550 ok(0, "unexpected call\n");
551 return E_NOTIMPL;
554 static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface, VARIANT child_id,
555 BSTR value)
557 ok(0, "unexpected call\n");
558 return E_NOTIMPL;
561 static IAccessibleVtbl AccessibleVtbl = {
562 Accessible_QueryInterface,
563 Accessible_AddRef,
564 Accessible_Release,
565 Accessible_GetTypeInfoCount,
566 Accessible_GetTypeInfo,
567 Accessible_GetIDsOfNames,
568 Accessible_Invoke,
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,
633 lcid, rg_disp_id);
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,
665 BSTR *out_name)
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,
672 BSTR *out_value)
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,
686 VARIANT *out_role)
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,
693 VARIANT *out_state)
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,
700 BSTR *out_help)
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,
711 out_topic_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,
719 out_kbd_shortcut);
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,
739 out_default_action);
742 static HRESULT WINAPI Accessible2_accSelect(IAccessible2 *iface, LONG select_flags,
743 VARIANT child_id)
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,
762 out_var);
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,
779 BSTR name)
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,
786 BSTR value)
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");
795 return E_NOTIMPL;
798 static HRESULT WINAPI Accessible2_get_relation(IAccessible2 *iface, LONG relation_idx,
799 IAccessibleRelation **out_relation)
801 ok(0, "unexpected call\n");
802 return E_NOTIMPL;
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");
809 return E_NOTIMPL;
812 static HRESULT WINAPI Accessible2_role(IAccessible2 *iface, LONG *out_role)
814 ok(0, "unexpected call\n");
815 return E_NOTIMPL;
818 static HRESULT WINAPI Accessible2_scrollTo(IAccessible2 *iface, enum IA2ScrollType scroll_type)
820 ok(0, "unexpected call\n");
821 return E_NOTIMPL;
824 static HRESULT WINAPI Accessible2_scrollToPoint(IAccessible2 *iface,
825 enum IA2CoordinateType coordinate_type, LONG x, LONG y)
827 ok(0, "unexpected call\n");
828 return E_NOTIMPL;
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");
835 return E_NOTIMPL;
838 static HRESULT WINAPI Accessible2_get_states(IAccessible2 *iface, AccessibleStates *out_states)
840 ok(0, "unexpected call\n");
841 return E_NOTIMPL;
844 static HRESULT WINAPI Accessible2_get_extendedRole(IAccessible2 *iface, BSTR *out_extended_role)
846 ok(0, "unexpected call\n");
847 return E_NOTIMPL;
850 static HRESULT WINAPI Accessible2_get_localizedExtendedRole(IAccessible2 *iface,
851 BSTR *out_localized_extended_role)
853 ok(0, "unexpected call\n");
854 return E_NOTIMPL;
857 static HRESULT WINAPI Accessible2_get_nExtendedStates(IAccessible2 *iface, LONG *out_nExtendedStates)
859 ok(0, "unexpected call\n");
860 return E_NOTIMPL;
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");
867 return E_NOTIMPL;
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");
874 return E_NOTIMPL;
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);
883 else
884 CHECK_EXPECT(Accessible_get_uniqueID);
886 *out_unique_id = 0;
887 if (This->unique_id)
889 *out_unique_id = This->unique_id;
890 return S_OK;
893 return E_NOTIMPL;
896 static HRESULT WINAPI Accessible2_get_windowHandle(IAccessible2 *iface, HWND *out_hwnd)
898 ok(0, "unexpected call\n");
899 return E_NOTIMPL;
902 static HRESULT WINAPI Accessible2_get_indexInParent(IAccessible2 *iface, LONG *out_idx_in_parent)
904 ok(0, "unexpected call\n");
905 return E_NOTIMPL;
908 static HRESULT WINAPI Accessible2_get_locale(IAccessible2 *iface, IA2Locale *out_locale)
910 ok(0, "unexpected call\n");
911 return E_NOTIMPL;
914 static HRESULT WINAPI Accessible2_get_attributes(IAccessible2 *iface, BSTR *out_attributes)
916 ok(0, "unexpected call\n");
917 return E_NOTIMPL;
920 static const IAccessible2Vtbl Accessible2Vtbl = {
921 Accessible2_QueryInterface,
922 Accessible2_AddRef,
923 Accessible2_Release,
924 Accessible2_GetTypeInfoCount,
925 Accessible2_GetTypeInfo,
926 Accessible2_GetIDsOfNames,
927 Accessible2_Invoke,
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,
952 Accessible2_role,
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)
1002 return E_NOTIMPL;
1005 static const IOleWindowVtbl OleWindowVtbl = {
1006 OleWindow_QueryInterface,
1007 OleWindow_AddRef,
1008 OleWindow_Release,
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) &&
1042 This->enable_ia2)
1043 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1045 return E_NOTIMPL;
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 },
1059 { &OleWindowVtbl },
1060 { &ServiceProviderVtbl },
1062 NULL,
1063 0, 0,
1064 0, 0, 0, NULL,
1065 0, 0, 0, 0,
1066 FALSE, 0,
1069 static struct Accessible Accessible2 =
1071 { &AccessibleVtbl },
1072 { &Accessible2Vtbl },
1073 { &OleWindowVtbl },
1074 { &ServiceProviderVtbl },
1076 NULL,
1077 0, 0,
1078 0, 0, 0, NULL,
1079 0, 0, 0, 0,
1080 FALSE, 0,
1083 static struct Accessible Accessible_child =
1085 { &AccessibleVtbl },
1086 { &Accessible2Vtbl },
1087 { &OleWindowVtbl },
1088 { &ServiceProviderVtbl },
1090 &Accessible.IAccessible_iface,
1091 0, 0,
1092 0, 0, 0, NULL,
1093 0, 0, 0, 0,
1094 FALSE, 0,
1097 static struct Accessible Accessible_child2 =
1099 { &AccessibleVtbl },
1100 { &Accessible2Vtbl },
1101 { &OleWindowVtbl },
1102 { &ServiceProviderVtbl },
1104 &Accessible.IAccessible_iface,
1105 0, 0,
1106 0, 0, 0, NULL,
1107 0, 0, 0, 0,
1108 FALSE, 0,
1111 struct Provider_prop_override
1113 int prop_id;
1114 VARIANT val;
1117 struct Provider_value_pattern_data
1119 BOOL is_supported;
1120 BOOL is_read_only;
1123 struct Provider_legacy_accessible_pattern_data
1125 BOOL is_supported;
1126 int child_id;
1127 DWORD role;
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;
1138 LONG ref;
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;
1148 HWND hwnd;
1149 BOOL ret_invalid_prop_type;
1150 DWORD expected_tid;
1151 int runtime_id[2];
1152 DWORD last_call_tid;
1153 BOOL ignore_hwnd_prop;
1154 HWND override_hwnd;
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)
1178 SAFEARRAY *sa;
1179 LONG idx;
1181 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(uia_i4_arr_prop_val))))
1182 return NULL;
1184 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
1185 SafeArrayPutElement(sa, &idx, (void *)&uia_i4_arr_prop_val[idx]);
1187 return sa;
1190 static SAFEARRAY *create_r8_safearray(void)
1192 SAFEARRAY *sa;
1193 LONG idx;
1195 if (!(sa = SafeArrayCreateVector(VT_R8, 0, ARRAY_SIZE(uia_r8_arr_prop_val))))
1196 return NULL;
1198 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
1199 SafeArrayPutElement(sa, &idx, (void *)&uia_r8_arr_prop_val[idx]);
1201 return sa;
1204 static SAFEARRAY *create_unk_safearray(void)
1206 SAFEARRAY *sa;
1207 LONG idx;
1209 if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, ARRAY_SIZE(uia_unk_arr_prop_val))))
1210 return NULL;
1212 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
1213 SafeArrayPutElement(sa, &idx, (void *)uia_unk_arr_prop_val[idx]);
1215 return sa;
1218 enum {
1219 PROV_GET_PROVIDER_OPTIONS,
1220 PROV_GET_PATTERN_PROV,
1221 PROV_GET_PROPERTY_VALUE,
1222 PROV_GET_HOST_RAW_ELEMENT_PROVIDER,
1223 FRAG_NAVIGATE,
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",
1234 "GetPropertyValue",
1235 "get_HostRawElementProvider",
1236 "Navigate",
1237 "GetRuntimeId",
1238 "get_FragmentRoot",
1239 "get_BoundingRectangle",
1240 "GetFocus",
1241 "GetOverrideProviderForHwnd",
1244 static const char *get_prov_method_str(int method)
1246 if (method >= ARRAY_SIZE(prov_method_str))
1247 return NULL;
1248 else
1249 return prov_method_str[method];
1252 enum {
1253 METHOD_OPTIONAL = 0x01,
1254 METHOD_TODO = 0x02,
1257 struct prov_method_sequence {
1258 struct Provider *prov;
1259 int method;
1260 int flags;
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);
1300 sequence = NULL;
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)
1310 return;
1312 if (!sequence)
1314 sequence_size = 10;
1315 sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
1317 if (sequence_cnt == sequence_size)
1319 sequence_size *= 2;
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);
1340 actual = sequence;
1342 if (context)
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));
1352 expected++;
1353 actual++;
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));
1359 expected++;
1361 else if (expected->flags & METHOD_OPTIONAL)
1362 expected++;
1363 else
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));
1367 expected++;
1368 actual++;
1370 count++;
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));
1380 count++;
1381 expected++;
1384 if (expected->prov || actual->prov)
1386 if (expected->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));
1389 else
1390 ok_( file, line)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual->prov->prov_name,
1391 get_prov_method_str(actual->method));
1394 if (context)
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
1408 * formatted as:
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
1417 * "Nonclient".
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>"
1429 * An example:
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);
1437 if (!str)
1438 return FALSE;
1440 if (!out_name)
1441 return TRUE;
1443 str += wcslen(prov_type);
1444 str2 = wcschr(str, L'(');
1445 lstrcpynW(out_name, str, ((str2 - str)));
1447 return TRUE;
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)
1457 WCHAR buf[2048];
1459 if (parent_link)
1460 wsprintfW(buf, L"%s(parent link):", prov_type);
1461 else
1462 wsprintfW(buf, L"%s:", prov_type);
1464 if (!get_provider_desc(prov_desc, buf, buf))
1466 if (parent_link)
1467 wsprintfW(buf, L"%s:", prov_type);
1468 else
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));
1473 else
1475 if (parent_link)
1476 todo_wine_if(todo) ok_(file, line)(0, "expected parent link provider %s\n", debugstr_w(prov_type));
1477 else
1478 todo_wine_if(todo) ok_(file, line)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type));
1481 return;
1484 if (prov_name)
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;
1493 WCHAR buf[128];
1494 DWORD prov_pid;
1495 HWND prov_hwnd;
1496 WCHAR *end;
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:");
1506 if (str)
1507 str += wcslen(L"providerId:");
1508 else
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;
1526 WCHAR buf[1024];
1528 if (!parent_link)
1529 wsprintfW(buf, L"%s:Nested ", prov_type);
1530 else
1531 wsprintfW(buf, L"%s(parent link):Nested ", prov_type);
1532 str = wcsstr(prov_desc, buf);
1533 /* Check with and without parent-link. */
1534 if (!str)
1535 return FALSE;
1537 if (!out_desc)
1538 return TRUE;
1540 str += wcslen(buf);
1541 str2 = wcschr(str, L']');
1542 /* We want to include the ']' character, so + 2. */
1543 lstrcpynW(out_desc, str, ((str2 - str) + 2));
1545 return TRUE;
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;
1553 HRESULT hr;
1554 UINT dims;
1555 int val;
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++)
1571 idx = lbound + 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);
1587 *ppv = NULL;
1588 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
1589 *ppv = iface;
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;
1600 else
1601 return E_NOINTERFACE;
1603 IRawElementProviderSimple_AddRef(iface);
1604 return S_OK;
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();
1629 *ret_val = 0;
1630 if (This->prov_opts)
1632 *ret_val = This->prov_opts;
1633 return S_OK;
1636 return E_NOTIMPL;
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();
1649 *ret_val = NULL;
1650 switch (pattern_id)
1652 case UIA_ValuePatternId:
1653 if (This->value_pattern_data.is_supported)
1654 *ret_val = (IUnknown *)iface;
1655 break;
1657 case UIA_LegacyIAccessiblePatternId:
1658 if (This->legacy_acc_pattern_data.is_supported)
1659 *ret_val = (IUnknown *)iface;
1660 break;
1662 default:
1663 break;
1666 if (*ret_val)
1667 IUnknown_AddRef(*ret_val);
1669 return S_OK;
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)
1684 int i;
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));
1694 return S_OK;
1699 VariantInit(ret_val);
1700 switch (prop_id)
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);
1713 break;
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;
1733 else
1735 V_VT(ret_val) = VT_I4;
1736 V_I4(ret_val) = uia_i4_prop_val;
1738 break;
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;
1746 else
1748 V_VT(ret_val) = VT_R8;
1749 V_R8(ret_val) = uia_r8_prop_val;
1751 break;
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;
1772 else
1774 V_VT(ret_val) = VT_BSTR;
1775 V_BSTR(ret_val) = SysAllocString(uia_bstr_prop_str);
1777 break;
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;
1796 else
1798 V_VT(ret_val) = VT_BOOL;
1799 V_BOOL(ret_val) = VARIANT_TRUE;
1801 break;
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();
1810 else
1812 V_VT(ret_val) = VT_ARRAY | VT_I4;
1813 V_ARRAY(ret_val) = create_i4_safearray();
1815 break;
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();
1824 else
1826 V_VT(ret_val) = VT_ARRAY | VT_R8;
1827 V_ARRAY(ret_val) = create_r8_safearray();
1829 break;
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;
1837 else
1839 V_VT(ret_val) = VT_UNKNOWN;
1840 V_UNKNOWN(ret_val) = (IUnknown *)&Provider_child.IRawElementProviderSimple_iface;
1841 IUnknown_AddRef(V_UNKNOWN(ret_val));
1843 break;
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();
1855 else
1857 V_VT(ret_val) = VT_UNKNOWN | VT_ARRAY;
1858 V_ARRAY(ret_val) = create_unk_safearray();
1860 break;
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);
1869 break;
1872 default:
1873 break;
1876 return S_OK;
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();
1889 *ret_val = NULL;
1890 if (This->hwnd)
1891 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
1893 return S_OK;
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,
1912 void **ppv)
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();
1940 *ret_val = NULL;
1941 switch (direction)
1943 case NavigateDirection_Parent:
1944 *ret_val = This->parent;
1945 break;
1947 case NavigateDirection_NextSibling:
1948 *ret_val = This->next_sibling;
1949 break;
1951 case NavigateDirection_PreviousSibling:
1952 *ret_val = This->prev_sibling;
1953 break;
1955 case NavigateDirection_FirstChild:
1956 *ret_val = This->first_child;
1957 break;
1959 case NavigateDirection_LastChild:
1960 *ret_val = This->last_child;
1961 break;
1963 default:
1964 trace("Invalid navigate direction %d\n", direction);
1965 break;
1968 if (*ret_val)
1969 IRawElementProviderFragment_AddRef(*ret_val);
1971 return S_OK;
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();
1984 *ret_val = NULL;
1985 if (This->runtime_id[0] || This->runtime_id[1])
1987 SAFEARRAY *sa;
1988 LONG idx;
1990 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(This->runtime_id))))
1991 return E_FAIL;
1993 for (idx = 0; idx < ARRAY_SIZE(This->runtime_id); idx++)
1994 SafeArrayPutElement(sa, &idx, (void *)&This->runtime_id[idx]);
1996 *ret_val = sa;
1999 return S_OK;
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;
2013 return S_OK;
2016 static HRESULT WINAPI ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface,
2017 SAFEARRAY **ret_val)
2019 ok(0, "unexpected call\n");
2020 *ret_val = NULL;
2021 return E_NOTIMPL;
2024 static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *iface)
2026 ok(0, "unexpected call\n");
2027 return E_NOTIMPL;
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();
2040 *ret_val = NULL;
2041 if (This->frag_root)
2043 *ret_val = This->frag_root;
2044 IRawElementProviderFragmentRoot_AddRef(This->frag_root);
2047 return S_OK;
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,
2068 void **ppv)
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");
2090 return E_NOTIMPL;
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();
2103 *ret_val = NULL;
2104 if (Provider->focus_prov)
2106 *ret_val = Provider->focus_prov;
2107 IRawElementProviderFragment_AddRef(*ret_val);
2110 return S_OK;
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,
2127 void **ppv)
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);
2152 *ret_val = NULL;
2153 if (This->override_hwnd == hwnd)
2155 return IRawElementProviderSimple_QueryInterface(&Provider_override.IRawElementProviderSimple_iface,
2156 &IID_IRawElementProviderSimple, (void **)ret_val);
2159 return S_OK;
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,
2175 void **ppv)
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");
2196 return E_NOTIMPL;
2199 static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
2201 ok(0, "unexpected call\n");
2202 return E_NOTIMPL;
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;
2211 return S_OK;
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,
2229 void **ppv)
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");
2250 return E_NOTIMPL;
2253 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider *iface)
2255 ok(0, "unexpected call\n");
2256 return E_NOTIMPL;
2259 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val)
2261 ok(0, "unexpected call\n");
2262 return E_NOTIMPL;
2265 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider *iface,
2266 IAccessible **out_acc)
2268 ok(0, "unexpected call\n");
2269 return E_NOTIMPL;
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;
2277 return S_OK;
2280 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name)
2282 ok(0, "unexpected call\n");
2283 return E_NOTIMPL;
2286 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value)
2288 ok(0, "unexpected call\n");
2289 return E_NOTIMPL;
2292 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider *iface,
2293 BSTR *out_description)
2295 ok(0, "unexpected call\n");
2296 return E_NOTIMPL;
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;
2304 return S_OK;
2307 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
2309 ok(0, "unexpected call\n");
2310 return E_NOTIMPL;
2313 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help)
2315 ok(0, "unexpected call\n");
2316 return E_NOTIMPL;
2319 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_KeyboardShortcut(ILegacyIAccessibleProvider *iface,
2320 BSTR *out_kbd_shortcut)
2322 ok(0, "unexpected call\n");
2323 return E_NOTIMPL;
2326 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider *iface,
2327 SAFEARRAY **out_selected)
2329 ok(0, "unexpected call\n");
2330 return E_NOTIMPL;
2333 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_DefaultAction(ILegacyIAccessibleProvider *iface,
2334 BSTR *out_default_action)
2336 ok(0, "unexpected call\n");
2337 return E_NOTIMPL;
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 },
2369 "Provider",
2370 NULL, NULL,
2371 NULL, NULL,
2372 &Provider_child.IRawElementProviderFragment_iface, &Provider_child2.IRawElementProviderFragment_iface,
2373 0, 0, 0,
2376 static struct Provider Provider2 =
2378 { &ProviderSimpleVtbl },
2379 { &ProviderFragmentVtbl },
2380 { &ProviderFragmentRootVtbl },
2381 { &ProviderHwndOverrideVtbl },
2382 { &ProviderValuePatternVtbl },
2383 { &ProviderLegacyIAccessiblePatternVtbl },
2385 "Provider2",
2386 NULL, NULL,
2387 NULL, NULL,
2388 NULL, NULL,
2389 0, 0, 0,
2392 static struct Provider Provider_child =
2394 { &ProviderSimpleVtbl },
2395 { &ProviderFragmentVtbl },
2396 { &ProviderFragmentRootVtbl },
2397 { &ProviderHwndOverrideVtbl },
2398 { &ProviderValuePatternVtbl },
2399 { &ProviderLegacyIAccessiblePatternVtbl },
2401 "Provider_child",
2402 &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
2403 NULL, &Provider_child2.IRawElementProviderFragment_iface,
2404 NULL, NULL,
2405 ProviderOptions_ServerSideProvider, 0, 0,
2408 static struct Provider Provider_child2 =
2410 { &ProviderSimpleVtbl },
2411 { &ProviderFragmentVtbl },
2412 { &ProviderFragmentRootVtbl },
2413 { &ProviderHwndOverrideVtbl },
2414 { &ProviderValuePatternVtbl },
2415 { &ProviderLegacyIAccessiblePatternVtbl },
2417 "Provider_child2",
2418 &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
2419 &Provider_child.IRawElementProviderFragment_iface, NULL,
2420 NULL, NULL,
2421 ProviderOptions_ServerSideProvider, 0, 0,
2424 static struct Provider Provider_hwnd =
2426 { &ProviderSimpleVtbl },
2427 { &ProviderFragmentVtbl },
2428 { &ProviderFragmentRootVtbl },
2429 { &ProviderHwndOverrideVtbl },
2430 { &ProviderValuePatternVtbl },
2431 { &ProviderLegacyIAccessiblePatternVtbl },
2433 "Provider_hwnd",
2434 NULL, NULL,
2435 NULL, NULL,
2436 NULL, NULL,
2437 ProviderOptions_ClientSideProvider, 0, 0,
2440 static struct Provider Provider_nc =
2442 { &ProviderSimpleVtbl },
2443 { &ProviderFragmentVtbl },
2444 { &ProviderFragmentRootVtbl },
2445 { &ProviderHwndOverrideVtbl },
2446 { &ProviderValuePatternVtbl },
2447 { &ProviderLegacyIAccessiblePatternVtbl },
2449 "Provider_nc",
2450 NULL, NULL,
2451 NULL, NULL,
2452 NULL, NULL,
2453 ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider,
2454 0, 0,
2457 static struct Provider Provider_proxy =
2459 { &ProviderSimpleVtbl },
2460 { &ProviderFragmentVtbl },
2461 { &ProviderFragmentRootVtbl },
2462 { &ProviderHwndOverrideVtbl },
2463 { &ProviderValuePatternVtbl },
2464 { &ProviderLegacyIAccessiblePatternVtbl },
2466 "Provider_proxy",
2467 NULL, NULL,
2468 NULL, NULL,
2469 NULL, NULL,
2470 ProviderOptions_ClientSideProvider,
2471 0, 0,
2474 static struct Provider Provider_proxy2 =
2476 { &ProviderSimpleVtbl },
2477 { &ProviderFragmentVtbl },
2478 { &ProviderFragmentRootVtbl },
2479 { &ProviderHwndOverrideVtbl },
2480 { &ProviderValuePatternVtbl },
2481 { &ProviderLegacyIAccessiblePatternVtbl },
2483 "Provider_proxy2",
2484 NULL, NULL,
2485 NULL, NULL,
2486 NULL, NULL,
2487 ProviderOptions_ClientSideProvider,
2488 0, 0,
2491 static struct Provider Provider_override =
2493 { &ProviderSimpleVtbl },
2494 { &ProviderFragmentVtbl },
2495 { &ProviderFragmentRootVtbl },
2496 { &ProviderHwndOverrideVtbl },
2497 { &ProviderValuePatternVtbl },
2498 { &ProviderLegacyIAccessiblePatternVtbl },
2500 "Provider_override",
2501 NULL, NULL,
2502 NULL, NULL,
2503 NULL, NULL,
2504 ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider,
2505 0, 0,
2508 #define DEFINE_PROVIDER(name) \
2509 static struct Provider Provider_ ## name = \
2511 { &ProviderSimpleVtbl }, \
2512 { &ProviderFragmentVtbl }, \
2513 { &ProviderFragmentRootVtbl }, \
2514 { &ProviderHwndOverrideVtbl }, \
2515 { &ProviderValuePatternVtbl }, \
2516 { &ProviderLegacyIAccessiblePatternVtbl }, \
2517 1, \
2518 "Provider_" # name "", \
2519 NULL, NULL, \
2520 NULL, NULL, \
2521 NULL, NULL, \
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)
2542 switch (message)
2544 case WM_GETOBJECT:
2545 if (lParam == (DWORD)OBJID_CLIENT)
2547 CHECK_EXPECT(winproc_GETOBJECT_CLIENT);
2548 if (acc_client)
2549 return LresultFromObject(&IID_IAccessible, wParam, (IUnknown *)acc_client);
2551 break;
2553 else if (lParam == UiaRootObjectId)
2555 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot);
2556 if (prov_root)
2557 return UiaReturnRawElementProvider(hwnd, wParam, lParam, prov_root);
2559 break;
2562 break;
2564 default:
2565 break;
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)
2574 switch (message)
2576 case WM_GETOBJECT:
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);
2583 break;
2586 break;
2588 default:
2589 break;
2592 return DefWindowProcA(hwnd, message, wParam, lParam);
2595 static void test_UiaHostProviderFromHwnd(void)
2597 IRawElementProviderSimple *p, *p2;
2598 enum ProviderOptions prov_opt;
2599 WNDCLASSA cls;
2600 HRESULT hr;
2601 HWND hwnd;
2602 VARIANT v;
2603 int i;
2605 cls.style = 0;
2606 cls.lpfnWndProc = test_wnd_proc;
2607 cls.cbClsExtra = 0;
2608 cls.cbWndExtra = 0;
2609 cls.hInstance = GetModuleHandleA(NULL);
2610 cls.hIcon = 0;
2611 cls.hCursor = 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);
2631 p = NULL;
2632 hr = UiaHostProviderFromHwnd(hwnd, &p);
2633 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
2635 p2 = NULL;
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));
2653 VariantClear(&v);
2655 /* No patterns are implemented on the HWND Host provider. */
2656 for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++)
2658 IUnknown *unk;
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));
2683 VariantClear(&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;
2700 HRESULT hr;
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);
2719 CoUninitialize();
2721 return 0;
2724 static void test_uia_reserved_value_ifaces(void)
2726 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
2727 IStream *stream[2];
2728 IMarshal *marshal;
2729 HANDLE thread;
2730 ULONG refcnt;
2731 HRESULT hr;
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);
2755 marshal = NULL;
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);
2791 marshal = NULL;
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)
2816 MSG msg;
2817 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
2819 TranslateMessage(&msg);
2820 DispatchMessageW(&msg);
2823 CloseHandle(thread);
2825 CoUninitialize();
2828 struct msaa_role_uia_type {
2829 INT acc_role;
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 {
2901 INT acc_state;
2902 INT prop_id;
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)
2916 acc->role = role;
2917 acc->state = state;
2918 acc->child_count = child_count;
2919 acc->name = name;
2920 acc->left = left;
2921 acc->top = top;
2922 acc->width = width;
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;
2935 HRESULT hr;
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");
2949 return;
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
2969 * Windows version.
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");
2979 return;
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;
2988 acc_client = NULL;
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;
3037 acc_client = NULL;
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;
3068 acc_client = NULL;
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;
3098 acc_client = NULL;
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,
3115 INT cid, int line)
3117 ILegacyIAccessibleProvider *accprov;
3118 IAccessible *accessible;
3119 INT child_id;
3120 HRESULT hr;
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;
3142 HRESULT hr;
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
3165 * and siblings.
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);
3203 acc_client = NULL;
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);
3212 /* Do nothing. */
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);
3391 acc_client = NULL;
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);
3495 if (elfrag2)
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
3546 * comparisons.
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 };
3582 HRESULT hr;
3583 VARIANT v;
3584 int i, x;
3586 /* MSAA role to UIA control type test. */
3587 VariantInit(&v);
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;
3592 DWORD role_val;
3593 IUnknown *unk;
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);
3605 VariantClear(&v);
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));
3610 else
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);
3616 VariantClear(&v);
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));
3621 else
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);
3653 VariantClear(&v);
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);
3662 VariantClear(&v);
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,
3752 10, 10);
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);
3786 VariantInit(&v);
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)));
3791 VariantClear(&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)));
3801 VariantClear(&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;
3815 IAccessible *acc;
3816 IUnknown *unk;
3817 WNDCLASSA cls;
3818 HRESULT hr;
3819 HWND hwnd;
3820 VARIANT v;
3821 INT cid;
3823 CoInitializeEx(NULL, COINIT_MULTITHREADED);
3824 cls.style = 0;
3825 cls.lpfnWndProc = test_wnd_proc;
3826 cls.cbClsExtra = 0;
3827 cls.cbWndExtra = 0;
3828 cls.hInstance = GetModuleHandleA(NULL);
3829 cls.hIcon = 0;
3830 cls.hCursor = 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);
3881 acc_client = NULL;
3883 /* Skip tests on Win10v1507. */
3884 if (called_winproc_GETOBJECT_CLIENT)
3886 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
3887 return;
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));
3920 VariantClear(&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
3986 * compared.
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
4021 * values.
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;
4038 acc_client = NULL;
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;
4101 acc_client = NULL;
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);
4145 acc_client = NULL;
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;
4183 acc_client = NULL;
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;
4232 acc_client = NULL;
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;
4278 acc_client = NULL;
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;
4323 acc_client = NULL;
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. */
4337 acc_client = NULL;
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);
4407 acc_client = NULL;
4409 test_uia_prov_from_acc_properties();
4410 test_uia_prov_from_acc_navigation();
4411 test_uia_prov_from_acc_ia2();
4413 CoUninitialize();
4414 DestroyWindow(hwnd);
4415 UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
4416 Accessible.acc_hwnd = NULL;
4417 Accessible.ow_hwnd = NULL;
4420 struct uia_lookup_id {
4421 const GUID *guid;
4422 int 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;
4735 int id_type;
4736 const struct uia_lookup_id *ids;
4737 int ids_count;
4738 } tests[] =
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) },
4745 unsigned int i, y;
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);
4753 if (!id)
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));
4756 break;
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 },
4766 { 0 }
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 */
4779 { 0 }
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 */
4792 { 0 }
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 */
4804 { 0 }
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 */
4829 { 0 }
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 */
4854 { 0 }
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 */
4879 { 0 }
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 },
4891 { 0 }
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;
4898 HRESULT hr;
4899 VARIANT v;
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);
4941 CoUninitialize();
4943 return 0;
4946 static void test_uia_node_from_prov_com_threading(void)
4948 HANDLE thread;
4949 HUIANODE node;
4950 HRESULT hr;
4952 /* Test ProviderOptions_UseComThreading. */
4953 Provider.hwnd = NULL;
4954 prov_root = 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.
4963 if (hr == S_OK)
4965 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
4966 UiaNodeRelease(node);
4967 return;
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)
4981 MSG msg;
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;
4994 CoUninitialize();
4996 static void test_UiaNodeFromProvider(void)
4998 WNDCLASSA cls;
4999 HUIANODE node;
5000 HRESULT hr;
5001 ULONG ref;
5002 HWND hwnd;
5003 VARIANT v;
5005 cls.style = 0;
5006 cls.lpfnWndProc = test_wnd_proc;
5007 cls.cbClsExtra = 0;
5008 cls.cbWndExtra = 0;
5009 cls.hInstance = GetModuleHandleA(NULL);
5010 cls.hIcon = 0;
5011 cls.hCursor = 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);
5050 VariantClear(&v);
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);
5083 VariantClear(&v);
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;
5091 prov_root = NULL;
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);
5109 VariantClear(&v);
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
5120 * get added.
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);
5145 VariantClear(&v);
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);
5176 VariantClear(&v);
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);
5208 VariantClear(&v);
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);
5220 CoUninitialize();
5221 DestroyWindow(hwnd);
5222 UnregisterClassA("UiaNodeFromProvider class", NULL);
5223 prov_root = 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 },
5229 { 0 }
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 },
5237 { 0 }
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 },
5252 { 0 }
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 },
5274 { 0 }
5277 static const struct prov_method_sequence get_pattern_prop_seq[] = {
5278 { &Provider, PROV_GET_PATTERN_PROV },
5279 { 0 }
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 },
5285 { 0 }
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 },
5299 { 0 }
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 },
5314 { 0 }
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 },
5327 { 0 }
5330 static const struct prov_method_sequence get_empty_bounding_rect_seq[] = {
5331 { &Provider_child, FRAG_GET_BOUNDING_RECT },
5332 { 0 }
5335 static void set_uia_rect(struct UiaRect *rect, double left, double top, double width, double height)
5337 rect->left = left;
5338 rect->top = top;
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;
5348 SAFEARRAY *sa;
5349 double tmp[4];
5350 VARTYPE vt;
5351 HRESULT hr;
5352 UINT dims;
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))
5356 return;
5358 sa = V_ARRAY(v);
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)
5404 LONG idx;
5406 switch (type)
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);
5412 break;
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));
5421 else
5422 ok(check_variant_bool(v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(v));
5423 ok_method_sequence(get_prop_seq, NULL);
5424 break;
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));
5431 else
5432 ok(V_I4(v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(v));
5433 ok_method_sequence(get_prop_seq, NULL);
5434 break;
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++)
5441 ULONG val;
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);
5447 break;
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);
5453 break;
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++)
5459 double val;
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);
5465 break;
5467 case UIAutomationType_Element:
5469 HUIANODE tmp_node;
5470 HRESULT hr;
5471 VARIANT v1;
5473 if (from_com)
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);
5479 VariantClear(v);
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);
5487 else
5489 #ifdef _WIN64
5490 ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
5491 tmp_node = (HUIANODE)V_I8(v);
5492 #else
5493 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
5494 tmp_node = (HUIANODE)V_I4(v);
5495 #endif
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);
5508 break;
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);
5514 if (from_com)
5516 IUIAutomationElementArray *elem_arr = NULL;
5517 HRESULT hr;
5518 int len;
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");
5524 if (!elem_arr)
5526 VariantClear(v);
5527 break;
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;
5537 VARIANT v1;
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);
5549 VariantClear(&v1);
5552 IUIAutomationElementArray_Release(elem_arr);
5554 else
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))
5558 break;
5560 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
5562 HUIANODE tmp_node;
5563 HRESULT hr;
5564 VARIANT v1;
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);
5574 VariantClear(&v1);
5578 VariantClear(v);
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);
5582 break;
5584 default:
5585 break;
5588 VariantClear(v);
5589 V_VT(v) = VT_EMPTY;
5592 struct uia_element_property {
5593 const GUID *prop_guid;
5594 enum UIAutomationType type;
5595 BOOL skip_invalid;
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;
5659 IUnknown *unk_ns;
5660 unsigned int i;
5661 HUIANODE node;
5662 int prop_id;
5663 HRESULT hr;
5664 VARIANT v;
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;
5685 VariantClear(&v);
5686 prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid);
5687 if (!prop_id)
5689 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
5690 break;
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);
5707 else
5708 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5709 if (SUCCEEDED(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));
5714 VariantClear(&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);
5728 VariantClear(&v);
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);
5740 VariantClear(&v);
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);
5750 VariantClear(&v);
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);
5762 VariantClear(&v);
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);
5774 VariantClear(&v);
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");
5788 goto exit;
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);
5803 VariantClear(&v);
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));
5814 VariantClear(&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);
5821 exit:
5823 IUnknown_Release(unk_ns);
5824 CoUninitialize();
5827 static const struct prov_method_sequence get_runtime_id1[] = {
5828 { &Provider_child, FRAG_GET_RUNTIME_ID },
5829 { 0 }
5832 static const struct prov_method_sequence get_runtime_id2[] = {
5833 { &Provider_child, FRAG_GET_RUNTIME_ID },
5834 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
5835 { 0 }
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 },
5849 { 0 }
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 },
5862 { 0 }
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 },
5870 { 0 }
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;
5878 IUnknown *unk_ns;
5879 SAFEARRAY *sa;
5880 WNDCLASSA cls;
5881 HUIANODE node;
5882 HRESULT hr;
5883 HWND hwnd;
5884 VARIANT v;
5886 VariantInit(&v);
5887 cls.style = 0;
5888 cls.lpfnWndProc = test_wnd_proc;
5889 cls.cbClsExtra = 0;
5890 cls.cbWndExtra = 0;
5891 cls.hInstance = GetModuleHandleA(NULL);
5892 cls.hIcon = 0;
5893 cls.hCursor = 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);
5918 VariantClear(&v);
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));
5973 VariantClear(&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;
6003 sa = NULL;
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++)
6021 LONG lbound;
6023 Provider.prov_opts = root_prov_opts[i];
6024 sa = NULL;
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);
6035 if (i)
6036 ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n");
6038 rt_id[2] = tmp;
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;
6061 VariantInit(&v);
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);
6068 VariantClear(&v);
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);
6086 CoUninitialize();
6089 static const struct prov_method_sequence node_from_var_seq[] = {
6090 NODE_CREATE_SEQ(&Provider),
6091 { 0 },
6094 static void test_UiaHUiaNodeFromVariant(void)
6096 HUIANODE node, node2;
6097 ULONG node_ref;
6098 HRESULT hr;
6099 VARIANT v;
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;
6108 V_VT(&v) = VT_R8;
6109 hr = UiaHUiaNodeFromVariant(&v, &node);
6110 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6111 ok(!node, "node != NULL\n");
6113 node = NULL;
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);
6130 VariantClear(&v);
6131 IUnknown_Release((IUnknown *)node);
6133 #ifdef _WIN64
6134 node2 = (void *)0xdeadbeef;
6135 V_VT(&v) = VT_I4;
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;
6142 V_VT(&v) = VT_I8;
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");
6147 #else
6148 node2 = (void *)0xdeadbeef;
6149 V_VT(&v) = VT_I8;
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;
6156 V_VT(&v) = VT_I4;
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");
6161 #endif
6163 UiaNodeRelease(node);
6166 static const struct prov_method_sequence node_from_hwnd1[] = {
6167 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6168 { 0 }
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 */
6183 { 0 }
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 */
6195 { 0 }
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 */
6210 { 0 }
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 */
6228 { 0 }
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 */
6254 { 0 }
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 */
6274 { 0 }
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 */
6287 { 0 }
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 */
6305 { 0 }
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+. */
6315 { 0 }
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 },
6330 { 0 }
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 },
6343 { 0 }
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 },
6355 { 0 }
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 },
6365 { 0 }
6368 static void test_UiaNodeFromHandle_client_proc(void)
6370 APTTYPEQUALIFIER apt_qualifier;
6371 APTTYPE apt_type;
6372 WCHAR buf[2048];
6373 HUIANODE node;
6374 HRESULT hr;
6375 DWORD pid;
6376 HWND hwnd;
6377 VARIANT v;
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);
6399 VariantClear(&v);
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);
6412 if (SUCCEEDED(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);
6425 if (SUCCEEDED(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;
6436 WCHAR buf[2048];
6437 HRESULT hr;
6438 VARIANT v;
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);
6470 VariantClear(&v);
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
6483 * thread.
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);
6499 if (SUCCEEDED(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);
6525 VariantClear(&v);
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
6538 * versions.
6540 if (Provider_child.ref != 1)
6541 Sleep(50);
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
6546 * added to them.
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);
6573 VariantClear(&v);
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)
6580 Sleep(50);
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)
6586 Sleep(50);
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)
6608 Sleep(50);
6609 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6611 if (!pUiaDisconnectProvider)
6613 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
6614 goto exit;
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);
6644 VariantClear(&v);
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);
6669 VariantClear(&v);
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);
6688 VariantClear(&v);
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");
6750 exit:
6751 CoUninitialize();
6753 return 0;
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;
6763 APTTYPE apt_type;
6764 DWORD exit_code;
6765 WNDCLASSA cls;
6766 HANDLE thread;
6767 HRESULT hr;
6768 HWND hwnd;
6769 VARIANT v;
6771 cls.style = 0;
6772 cls.lpfnWndProc = test_wnd_proc;
6773 cls.cbClsExtra = 0;
6774 cls.cbWndExtra = 0;
6775 cls.hInstance = GetModuleHandleA(NULL);
6776 cls.hIcon = 0;
6777 cls.hCursor = 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. */
6793 prov_root = NULL;
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
6805 * won't match it.
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);
6810 if (SUCCEEDED(hr))
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);
6818 prov_root = NULL;
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);
6834 VariantClear(&v);
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);
6860 VariantClear(&v);
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);
6897 else
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);
6902 VariantClear(&v);
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);
6914 CoUninitialize();
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);
6940 VariantClear(&v);
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);
6974 VariantClear(&v);
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"))
6997 Sleep(10);
6998 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7000 todo_wine ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
7001 if (SUCCEEDED(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)
7011 MSG msg;
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)
7035 MSG msg;
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));
7046 else if (exit_code)
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");
7055 CoUninitialize();
7057 DestroyWindow(hwnd);
7058 UnregisterClassA("UiaNodeFromHandle class", NULL);
7059 prov_root = 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 */
7066 { 0 }
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 */
7076 { 0 }
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 */
7094 { 0 }
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 */
7115 { 0 }
7118 static const struct prov_method_sequence reg_prov_cb5[] = {
7119 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
7120 { 0 }
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 */
7127 { 0 }
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 */
7136 { 0 }
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 */
7147 { 0 }
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. */
7159 { 0 }
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 },
7176 { 0 }
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 */
7201 { 0 }
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 */
7233 { 0 }
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 */
7276 { 0 }
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;
7284 switch (prov_type)
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;
7292 else
7293 elprov = base_hwnd_prov;
7294 break;
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;
7307 break;
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;
7315 else
7316 elprov = nc_prov;
7317 break;
7319 default:
7320 break;
7323 if (elprov)
7325 SAFEARRAY *sa;
7326 LONG idx = 0;
7328 sa = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
7329 if (sa)
7330 SafeArrayPutElement(sa, &idx, (void *)elprov);
7332 return sa;
7335 return NULL;
7338 static void test_UiaRegisterProviderCallback(void)
7340 HWND hwnd, hwnd2;
7341 WNDCLASSA cls;
7342 HUIANODE node;
7343 HRESULT hr;
7344 VARIANT v;
7346 cls.style = 0;
7347 cls.lpfnWndProc = test_wnd_proc;
7348 cls.cbClsExtra = 0;
7349 cls.cbWndExtra = 0;
7350 cls.hInstance = GetModuleHandleA(NULL);
7351 cls.hIcon = 0;
7352 cls.hCursor = 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);
7418 VariantClear(&v);
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);
7451 VariantClear(&v);
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);
7492 VariantClear(&v);
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);
7537 VariantClear(&v);
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.
7544 * Main provider.
7545 * Nonclient provider.
7546 * Hwnd 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);
7655 VariantClear(&v);
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);
7692 VariantClear(&v);
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);
7730 VariantClear(&v);
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;
7748 req->Scope = scope;
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;
7762 cond->Value = *val;
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 {
7782 DWORD pid;
7783 HWND hwnd;
7785 const WCHAR *prov_type[MAX_NODE_PROVIDERS];
7786 const WCHAR *prov_name[MAX_NODE_PROVIDERS];
7787 BOOL parent_link[MAX_NODE_PROVIDERS];
7788 int prov_count;
7791 static void init_node_provider_desc(struct node_provider_desc *desc, DWORD pid, HWND hwnd)
7793 memset(desc, 0, sizeof(*desc));
7794 desc->pid = pid;
7795 desc->hwnd = hwnd;
7798 static void add_provider_desc(struct node_provider_desc *desc, const WCHAR *prov_type, const WCHAR *prov_name,
7799 BOOL parent_link)
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;
7804 desc->prov_count++;
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)
7811 int i;
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)
7830 HUIANODE node;
7831 HRESULT hr;
7832 VARTYPE vt;
7833 VARIANT v;
7834 UINT dims;
7835 int i;
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);
7869 VariantClear(&v);
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);
7874 VariantClear(&v);
7876 UiaNodeRelease(node);
7880 static const struct prov_method_sequence cache_req_seq1[] = {
7881 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
7882 { 0 }
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 */
7891 { 0 }
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. */
7905 { 0 }
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. */
7911 { 0 }
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 */
7920 { 0 }
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 */
7928 { 0 }
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. */
7935 { 0 }
7938 static const struct prov_method_sequence cache_req_seq8[] = {
7939 NODE_CREATE_SEQ(&Provider_child),
7940 { 0 }
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 */
7952 { 0 }
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. */
7963 { 0 }
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];
7979 SAFEARRAY *out_req;
7980 IUnknown *unk_ns;
7981 BSTR tree_struct;
7982 int prop_ids[2];
7983 HUIANODE node;
7984 HRESULT hr;
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);
8004 VariantClear(&v);
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
8022 * condition.
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);
8129 if (out_req)
8131 exp_elems[0] = 2;
8132 exp_elems[1] = 1;
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(&not_cond, (struct UiaCondition *)&UiaFalseCondition);
8235 set_cache_request(&cache_req, (struct UiaCondition *)&not_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(&not_cond, (struct UiaCondition *)&UiaTrueCondition);
8255 set_cache_request(&cache_req, (struct UiaCondition *)&not_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);
8296 VariantClear(&v);
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);
8318 VariantClear(&v);
8320 else
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;
8357 V_VT(&v) = VT_BOOL;
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);
8377 VariantClear(&v);
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;
8389 V_VT(&v) = VT_BOOL;
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);
8404 VariantClear(&v);
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. */
8414 prop_ids[1] = 1;
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;
8440 exp_elems[0] = 1;
8441 exp_elems[1] = 3;
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));
8445 idx[0] = 0;
8446 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
8448 idx[1] = 1 + 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.
8469 V_VT(&v) = VT_BOOL;
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;
8485 exp_elems[0] = 1;
8486 exp_elems[1] = 3;
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));
8490 idx[0] = 0;
8491 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
8493 idx[1] = 1 + 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
8524 * nothing.
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
8540 * request.
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);
8565 VariantClear(&v);
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);
8573 CoUninitialize();
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 */
8591 { 0 }
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 */
8598 { 0 }
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 */
8605 { 0 }
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 */
8636 { 0 }
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 */
8658 { 0 }
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 */
8665 { 0 }
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 */
8687 { 0 }
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 */
8694 { 0 }
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 */
8743 { 0 }
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 */
8764 { 0 }
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 */
8785 { 0 }
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 */
8802 { 0 }
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 */
8809 { 0 }
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 */
8829 { 0 }
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 */
8843 { 0 }
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;
8857 if (parent)
8858 prov->parent = &parent->IRawElementProviderFragment_iface;
8859 if (frag_root)
8860 prov->frag_root = &frag_root->IRawElementProviderFragmentRoot_iface;
8861 if (prev_sibling)
8862 prov->prev_sibling = &prev_sibling->IRawElementProviderFragment_iface;
8863 if (next_sibling)
8864 prov->next_sibling = &next_sibling->IRawElementProviderFragment_iface;
8865 if (first_child)
8866 prov->first_child = &first_child->IRawElementProviderFragment_iface;
8867 if (last_child)
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;
8879 SAFEARRAY *out_req;
8880 BSTR tree_struct;
8881 WNDCLASSA cls;
8882 HRESULT hr;
8883 VARIANT v;
8884 HWND hwnd;
8886 CoInitializeEx(NULL, COINIT_MULTITHREADED);
8887 cls.style = 0;
8888 cls.lpfnWndProc = test_wnd_proc;
8889 cls.cbClsExtra = 0;
8890 cls.cbWndExtra = 0;
8891 cls.hInstance = GetModuleHandleA(NULL);
8892 cls.hIcon = 0;
8893 cls.hCursor = 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,
8911 NULL, NULL, NULL);
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,
8917 NULL, NULL, NULL);
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);
8952 VariantClear(&v);
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);
9016 node2 = node3;
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);
9050 node2 = node3;
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);
9113 node2 = node3;
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);
9147 node2 = node3;
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);
9177 node2 = node3;
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);
9201 tree_struct = NULL;
9202 out_req = NULL;
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);
9230 tree_struct = NULL;
9231 out_req = NULL;
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
9265 * Provider_child2.
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);
9274 tree_struct = NULL;
9275 out_req = NULL;
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);
9345 VariantClear(&v);
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);
9353 tree_struct = NULL;
9354 out_req = NULL;
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;
9381 prov_root = 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);
9401 VariantClear(&v);
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.
9409 V_VT(&v) = VT_BOOL;
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);
9416 tree_struct = NULL;
9417 out_req = NULL;
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);
9432 tree_struct = NULL;
9433 out_req = NULL;
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);
9452 CoUninitialize();
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;
9481 prov->hwnd = hwnd;
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;
9519 else
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;
9538 HRESULT hr;
9539 VARTYPE vt;
9540 UINT dims;
9541 LONG i;
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);
9561 /* Offsets SA. */
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++)
9581 BSTR tree_struct;
9582 int offset;
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 */
9642 { 0 },
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 */
9664 { 0 },
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 */
9684 { 0 },
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 */
9693 { 0 },
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 */
9709 { 0 },
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 */
9717 { 0 },
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 */
9757 { 0 },
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 */
9798 { 0 },
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 */
9839 { 0 },
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 */
9885 { 0 },
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 */
9904 { 0 },
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;
9919 HRESULT hr;
9920 VARIANT v;
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);
9944 VariantClear(&v);
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;
9974 exp_elems[0] = 7;
9975 exp_elems[1] = 2;
9977 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9979 for (i = 0; i < exp_elems[0]; i++)
9981 exp_offset[i] = 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;
10009 exp_elems[0] = 3;
10010 exp_elems[1] = 2;
10012 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10014 for (i = 0; i < exp_elems[0]; i++)
10016 exp_offset[i] = 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;
10044 exp_elems[0] = 2;
10045 exp_elems[1] = 2;
10047 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10049 for (i = 0; i < exp_elems[0]; i++)
10051 exp_offset[i] = 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;
10077 exp_elems[0] = 1;
10078 exp_elems[1] = 2;
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++)
10093 exp_offset[i] = 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;
10122 exp_elems[0] = 2;
10123 exp_elems[1] = 2;
10125 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10127 for (i = 0; i < exp_elems[0]; i++)
10129 exp_offset[i] = 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;
10157 exp_elems[0] = 1;
10158 exp_elems[1] = 2;
10160 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10162 for (i = 0; i < exp_elems[0]; i++)
10164 exp_offset[i] = 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;
10216 exp_elems[0] = 4;
10217 exp_elems[1] = 2;
10219 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10221 for (i = 0; i < exp_elems[0]; i++)
10223 exp_offset[i] = 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;
10269 exp_elems[0] = 4;
10270 exp_elems[1] = 2;
10272 idx[0] = 2;
10273 idx[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++)
10286 exp_offset[i] = 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;
10334 exp_elems[0] = 3;
10335 exp_elems[1] = 2;
10337 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10339 for (i = 0; i < exp_elems[0]; i++)
10341 exp_offset[i] = 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
10363 * excluded.
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;
10386 exp_elems[0] = 1;
10387 exp_elems[1] = 2;
10389 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10391 for (i = 0; i < exp_elems[0]; i++)
10393 exp_offset[i] = 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
10411 * condition.
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;
10433 exp_elems[0] = 1;
10434 exp_elems[1] = 2;
10436 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10438 for (i = 0; i < exp_elems[0]; i++)
10440 exp_offset[i] = 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);
10455 CoUninitialize();
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;
10487 HRESULT hr;
10488 VARIANT v;
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);
10497 else
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);
10527 else
10528 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
10530 VariantClear(&v);
10531 ok_method_sequence(node_from_hwnd2, "create_test_element");
10532 UiaRegisterProviderCallback(NULL);
10534 return element;
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;
10542 HRESULT hr;
10544 element = create_test_element_from_hwnd(uia_iface, hwnd, FALSE);
10545 hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2);
10546 if (is_cui8)
10548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10549 ok(!!element_2, "element_2 == NULL\n");
10550 IUIAutomationElement2_Release(element_2);
10552 else
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);
10560 prov_root = 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;
10572 IUnknown *unk_ns;
10573 BSTR tmp_bstr;
10574 HRESULT hr;
10575 RECT rect;
10576 VARIANT v;
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);
10589 VariantInit(&v);
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;
10600 VariantClear(&v);
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));
10604 break;
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);
10621 if (SUCCEEDED(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));
10626 VariantClear(&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");
10645 VariantClear(&v);
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++)
10671 element2 = NULL;
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);
10682 VariantClear(&v);
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. */
10715 V_VT(&v) = VT_I4;
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.
10728 tmp_bstr = NULL;
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);
10735 tmp_bstr = 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");
10751 goto exit;
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");
10765 VariantClear(&v);
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);
10773 VariantClear(&v);
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));
10789 VariantClear(&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);
10802 exit:
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;
10816 SAFEARRAY *sa;
10817 VARTYPE vt;
10818 HRESULT hr;
10819 UINT dims;
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.
10853 sa = NULL;
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;
10875 int tmp_val;
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)
10887 *ppv = NULL;
10888 if (IsEqualIID(riid, &IID_IUnknown))
10889 *ppv = iface;
10890 else
10891 return E_NOINTERFACE;
10893 return S_OK;
10896 static ULONG WINAPI Object_AddRef(IUnknown *iface)
10898 return 2;
10901 static ULONG WINAPI Object_Release(IUnknown *iface)
10903 return 1;
10906 static IUnknownVtbl ObjectVtbl = {
10907 Object_QueryInterface,
10908 Object_AddRef,
10909 Object_Release
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;
10922 int child_count;
10923 BOOL tmp_b;
10924 HRESULT hr;
10925 VARIANT v;
10926 ULONG ref;
10928 hr = IUIAutomation_CreateTrueCondition(uia_iface, NULL);
10929 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
10931 cond = NULL;
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);
10944 tmp_b = FALSE;
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);
10953 cond = NULL;
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);
10966 tmp_b = TRUE;
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;
10976 VariantInit(&v);
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;
10984 VariantInit(&v);
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. */
10996 cond = NULL;
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);
11016 VariantClear(&v);
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");
11021 VariantClear(&v);
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
11037 * interface.
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. */
11053 cond = NULL;
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 **)&not_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);
11070 cond = NULL;
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.
11081 cond = NULL;
11082 VariantInit(&v);
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");
11095 cond = NULL;
11096 VariantInit(&v);
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");
11130 cond = NULL;
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");
11136 or_cond = NULL;
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);
11152 child_count = 0;
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);
11157 child_count = 10;
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");
11167 child_count = 0;
11168 cond_arr = NULL;
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);
11190 cond = NULL;
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 **)&not_cond);
11196 IUIAutomationCondition_Release(cond);
11197 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11198 ok(!!not_cond, "not_cond == NULL\n");
11200 cond = NULL;
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);
11214 VariantInit(&v);
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));
11218 VariantClear(&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:
11229 * if (1)
11231 hr = IUIAutomation_get_RawViewCondition(uia_iface, NULL);
11232 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11234 cond = NULL;
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");
11244 tmp_b = FALSE;
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;
11261 HRESULT hr;
11262 VARIANT v;
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.
11271 cache_req = NULL;
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");
11277 * TreeScope tests.
11279 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, NULL);
11280 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11282 scope = 0;
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. */
11307 scope = 0;
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);
11316 scope = 0;
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.
11324 cond = NULL;
11325 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, NULL);
11326 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11328 cond = NULL;
11329 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, NULL);
11330 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11332 cond = NULL;
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. */
11337 cond = NULL;
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 **)&not_cond);
11343 IUIAutomationCondition_Release(cond);
11344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11345 ok(!!not_cond, "not_cond == NULL\n");
11347 cond = NULL;
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);
11361 VariantInit(&v);
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));
11365 VariantClear(&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. */
11375 cond = NULL;
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);
11396 elem_mode = 0;
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);
11408 elem_mode = 0;
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),
11429 { 0 },
11432 static const struct prov_method_sequence get_cached_prop_val_seq[] = {
11433 { &Provider_child, FRAG_GET_RUNTIME_ID },
11434 { 0 },
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 */
11440 { 0 },
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 */
11452 { 0 },
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;
11462 IUnknown *unk_ns;
11463 HRESULT hr;
11464 VARIANT v;
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);
11474 cache_req = NULL;
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");
11495 VariantClear(&v);
11498 * Passing in an invalid COM interface for IUIAutomationCacheRequest will
11499 * cause an access violation on Windows.
11501 if (0)
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.
11518 element2 = NULL;
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));
11529 VariantClear(&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));
11535 VariantClear(&v);
11537 IUIAutomationElement_Release(element2);
11539 /* RuntimeId is now set. */
11540 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
11541 element2 = NULL;
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));
11551 VariantClear(&v);
11552 IUIAutomationElement_Release(element2);
11555 * Add UIA_IsControlElementPropertyId to the list of cached property
11556 * values.
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;
11562 element2 = NULL;
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));
11572 VariantClear(&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));
11577 VariantClear(&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);
11588 cache_req = NULL;
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);
11601 element2 = NULL;
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));
11614 VariantClear(&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));
11621 element3 = NULL;
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");
11625 VariantClear(&v);
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);
11631 VariantClear(&v);
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");
11641 VariantClear(&v);
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);
11659 VariantClear(&v);
11662 IUIAutomationElementArray_Release(elem_arr);
11663 IUIAutomationCacheRequest_Release(cache_req);
11666 * Reference isn't released until the element holding the cache is
11667 * destroyed.
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),
11688 { 0 }
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 */
11728 { 0 },
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 */
11750 { 0 },
11753 struct exp_elem_desc {
11754 struct Provider *elem_prov;
11755 struct node_provider_desc prov_desc;
11756 ULONG exp_refcnt;
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)
11774 int i, arr_length;
11775 HRESULT hr;
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;
11786 VARIANT v;
11788 ok_(file, line)(desc->elem_prov->ref == desc->exp_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
11790 VariantInit(&v);
11791 element = NULL;
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);
11799 VariantClear(&v);
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;
11822 HRESULT hr;
11823 VARIANT v;
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.
11835 VariantInit(&v);
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");
11850 VariantClear(&v);
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;
11858 element2 = NULL;
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.
11874 cache_req = NULL;
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. */
11880 condition = NULL;
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
11890 * root is FALSE.
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
11915 * is FALSE.
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
11932 * is TRUE.
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);
11957 VariantClear(&v);
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
11981 * its sibling.
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. */
11998 condition = NULL;
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. */
12009 condition2 = NULL;
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
12029 * depth 1.
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
12090 * at depth 1.
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
12112 * excluded.
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);
12145 VariantClear(&v);
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);
12210 VariantClear(&v);
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),
12227 { 0 }
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 },
12234 { 0 }
12237 static const struct prov_method_sequence treewalker_seq3[] = {
12238 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
12239 NODE_CREATE_SEQ(&Provider_child2),
12240 { 0 }
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 },
12247 { 0 }
12250 static const struct prov_method_sequence treewalker_seq5[] = {
12251 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12252 NODE_CREATE_SEQ(&Provider_child2),
12253 { 0 }
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 },
12260 { 0 }
12263 static const struct prov_method_sequence treewalker_seq7[] = {
12264 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
12265 NODE_CREATE_SEQ(&Provider_child),
12266 { 0 }
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 },
12273 { 0 }
12276 static const struct prov_method_sequence treewalker_seq9[] = {
12277 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
12278 NODE_CREATE_SEQ(&Provider),
12279 { 0 }
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 },
12286 { 0 }
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;
12296 HRESULT hr;
12298 cond = NULL;
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. */
12313 walker = NULL;
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);
12326 cache_req = NULL;
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. */
12348 element2 = NULL;
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);
12358 element2 = NULL;
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. */
12366 element3 = NULL;
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);
12375 element3 = NULL;
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. */
12388 element2 = NULL;
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);
12398 element2 = NULL;
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. */
12406 element3 = NULL;
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);
12415 element3 = NULL;
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. */
12425 element3 = NULL;
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);
12435 element3 = NULL;
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)
12460 if (proxy_prov)
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;
12477 HRESULT hr;
12478 VARIANT v;
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);
12511 VariantClear(&v);
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,
12520 TRUE);
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;
12540 HRESULT hr;
12541 VARIANT v;
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);
12548 if (cache_req)
12549 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, &element);
12550 else
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);
12566 VariantClear(&v);
12568 IUIAutomationElement_Release(element);
12570 else
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;
12581 HRESULT hr;
12582 VARIANT v;
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);
12588 cache_req = NULL;
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
12629 * desktop node.
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 {
12736 const GUID *clsid;
12737 const GUID *iid;
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;
12757 HRESULT hr;
12758 VARIANT v;
12759 int i;
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,
12768 (void **)&iface);
12770 if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG))
12772 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
12773 has_cui8 = FALSE;
12774 break;
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));
12782 break;
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);
12791 if (has_cui8)
12792 hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
12793 (void **)&uia_iface);
12794 else
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);
12845 CoUninitialize();
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 },
12865 { 0 }
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 };
12873 HRESULT hr;
12874 VARIANT v;
12875 DWORD pid;
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));
12882 VariantClear(&v);
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)));
12891 VariantClear(&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)));
12901 VariantClear(&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);
12910 VariantClear(&v);
12911 winetest_pop_context();
12914 enum {
12915 PARENT_HWND_NULL,
12916 PARENT_HWND_HWND,
12917 PARENT_HWND_DESKTOP,
12920 struct uia_hwnd_control_type_test {
12921 DWORD style;
12922 DWORD style_ex;
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;
12954 HRESULT hr;
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;
12960 nc_ref = nc->ref;
12962 if (!child_hwnd)
12964 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
12965 SET_EXPECT(winproc_GETOBJECT_CLIENT);
12966 prov_root = &main->IRawElementProviderSimple_iface;
12968 else
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);
12980 if (child_hwnd)
12982 /* Called while trying to get override provider. */
12983 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
12984 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
12986 else
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,
12995 int line)
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 };
13002 HUIANODE tmp_node;
13003 HRESULT hr;
13004 VARIANT v;
13005 int i;
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)
13012 goto exit;
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");
13026 VariantClear(&v);
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));
13033 VariantClear(&v);
13034 UiaNodeRelease(tmp_node);
13036 exit:
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;
13046 RECT rect = { 0 };
13047 IUnknown *unk_ns;
13048 HUIANODE node;
13049 HRESULT hr;
13050 VARIANT v;
13051 int i;
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);
13077 VariantClear(&v);
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);
13091 VariantClear(&v);
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));
13099 VariantClear(&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);
13115 VariantClear(&v);
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);
13124 VariantClear(&v);
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);
13130 VariantInit(&v);
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];
13134 HWND parent;
13136 if (test->parent_hwnd_type == PARENT_HWND_HWND)
13137 parent = hwnd;
13138 else if (test->parent_hwnd_type == PARENT_HWND_DESKTOP)
13139 parent = GetDesktopWindow();
13140 else
13141 parent = NULL;
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);
13153 else
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);
13163 else
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));
13171 VariantClear(&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,
13196 NULL, 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);
13231 prov_root = NULL;
13234 * Test default ProviderType_Proxy clientside provider. Provider will be
13235 * the HWND provider for this node, and Accessible will be the main
13236 * provider.
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);
13264 VariantClear(&v);
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));
13271 VariantClear(&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);
13299 VariantClear(&v);
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));
13305 VariantClear(&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));
13311 VariantClear(&v);
13313 UiaNodeRelease(node);
13314 DestroyWindow(hwnd2);
13316 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
13317 acc_client = NULL;
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);
13327 CoUninitialize();
13330 static void test_UiaGetRootNode(void)
13332 HUIANODE node;
13333 HRESULT hr;
13334 VARIANT v;
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);
13368 VariantClear(&v);
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,
13377 TRUE);
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);
13383 CoUninitialize();
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;
13401 HRESULT hr;
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");
13412 else
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;
13425 exp_elems[0] = 1;
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;
13442 int cache_prop;
13443 VARIANT v;
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(&not_cond, (struct UiaCondition *)&prop_cond);
13477 cache_prop = UIA_RuntimeIdPropertyId;
13478 set_cache_request(&cache_req, (struct UiaCondition *)&not_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
13484 * desktop node.
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);
13571 CoUninitialize();
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;
13602 char **argv;
13603 int argc;
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)
13610 pImmDisableIME(0);
13612 pImmDisableIME = NULL;
13613 FreeLibrary(hModuleImm32);
13615 if (uia_dll)
13616 pUiaDisconnectProvider = (void *)GetProcAddress(uia_dll, "UiaDisconnectProvider");
13618 argc = winetest_get_mainargs(&argv);
13619 if (argc == 3)
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);
13629 return;
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();
13643 test_UiaFind();
13644 test_CUIAutomation();
13645 test_default_clientside_providers();
13646 test_UiaGetRootNode();
13647 test_UiaNodeFromFocus();
13648 if (uia_dll)
13650 pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible");
13651 if (pUiaProviderFromIAccessible)
13652 test_UiaProviderFromIAccessible();
13653 else
13654 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
13656 FreeLibrary(uia_dll);