ReactOS 0.4.17-dev-284-g529f3c6
uiautomation.c
Go to the documentation of this file.
1/*
2 * UI Automation tests
3 *
4 * Copyright 2019 Nikolay Sivov for CodeWeavers
5 *
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.
10 *
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.
15 *
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
19 */
20
21#define COBJMACROS
22
23#include <oleauto.h>
24#include <assert.h>
25#include "windows.h"
26#include "initguid.h"
27#include "uiautomation.h"
28#include "ocidl.h"
29#include "wine/iaccessible2.h"
30
31#include "wine/test.h"
32
33static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, LONG, DWORD, IRawElementProviderSimple **);
34static HRESULT (WINAPI *pUiaDisconnectProvider)(IRawElementProviderSimple *);
35
37 int id;
38 const char *str;
39};
40
41static const struct str_id_pair uia_prop_id_strs[] = {
42 { UIA_RuntimeIdPropertyId, "UIA_RuntimeIdPropertyId", },
43 { UIA_BoundingRectanglePropertyId, "UIA_BoundingRectanglePropertyId", },
44 { UIA_ProcessIdPropertyId, "UIA_ProcessIdPropertyId", },
45 { UIA_ControlTypePropertyId, "UIA_ControlTypePropertyId", },
46 { UIA_LocalizedControlTypePropertyId, "UIA_LocalizedControlTypePropertyId", },
47 { UIA_NamePropertyId, "UIA_NamePropertyId", },
48 { UIA_AcceleratorKeyPropertyId, "UIA_AcceleratorKeyPropertyId", },
49 { UIA_AccessKeyPropertyId, "UIA_AccessKeyPropertyId", },
50 { UIA_HasKeyboardFocusPropertyId, "UIA_HasKeyboardFocusPropertyId", },
51 { UIA_IsKeyboardFocusablePropertyId, "UIA_IsKeyboardFocusablePropertyId", },
52 { UIA_IsEnabledPropertyId, "UIA_IsEnabledPropertyId", },
53 { UIA_AutomationIdPropertyId, "UIA_AutomationIdPropertyId", },
54 { UIA_ClassNamePropertyId, "UIA_ClassNamePropertyId", },
55 { UIA_HelpTextPropertyId, "UIA_HelpTextPropertyId", },
56 { UIA_ClickablePointPropertyId, "UIA_ClickablePointPropertyId", },
57 { UIA_CulturePropertyId, "UIA_CulturePropertyId", },
58 { UIA_IsControlElementPropertyId, "UIA_IsControlElementPropertyId", },
59 { UIA_IsContentElementPropertyId, "UIA_IsContentElementPropertyId", },
60 { UIA_LabeledByPropertyId, "UIA_LabeledByPropertyId", },
61 { UIA_IsPasswordPropertyId, "UIA_IsPasswordPropertyId", },
62 { UIA_NativeWindowHandlePropertyId, "UIA_NativeWindowHandlePropertyId", },
63 { UIA_ItemTypePropertyId, "UIA_ItemTypePropertyId", },
64 { UIA_IsOffscreenPropertyId, "UIA_IsOffscreenPropertyId", },
65 { UIA_OrientationPropertyId, "UIA_OrientationPropertyId", },
66 { UIA_FrameworkIdPropertyId, "UIA_FrameworkIdPropertyId", },
67 { UIA_IsRequiredForFormPropertyId, "UIA_IsRequiredForFormPropertyId", },
68 { UIA_ItemStatusPropertyId, "UIA_ItemStatusPropertyId", },
69 { UIA_IsDockPatternAvailablePropertyId, "UIA_IsDockPatternAvailablePropertyId", },
70 { UIA_IsExpandCollapsePatternAvailablePropertyId, "UIA_IsExpandCollapsePatternAvailablePropertyId", },
71 { UIA_IsGridItemPatternAvailablePropertyId, "UIA_IsGridItemPatternAvailablePropertyId", },
72 { UIA_IsGridPatternAvailablePropertyId, "UIA_IsGridPatternAvailablePropertyId", },
73 { UIA_IsInvokePatternAvailablePropertyId, "UIA_IsInvokePatternAvailablePropertyId", },
74 { UIA_IsMultipleViewPatternAvailablePropertyId, "UIA_IsMultipleViewPatternAvailablePropertyId", },
75 { UIA_IsRangeValuePatternAvailablePropertyId, "UIA_IsRangeValuePatternAvailablePropertyId", },
76 { UIA_IsScrollPatternAvailablePropertyId, "UIA_IsScrollPatternAvailablePropertyId", },
77 { UIA_IsScrollItemPatternAvailablePropertyId, "UIA_IsScrollItemPatternAvailablePropertyId", },
78 { UIA_IsSelectionItemPatternAvailablePropertyId, "UIA_IsSelectionItemPatternAvailablePropertyId", },
79 { UIA_IsSelectionPatternAvailablePropertyId, "UIA_IsSelectionPatternAvailablePropertyId", },
80 { UIA_IsTablePatternAvailablePropertyId, "UIA_IsTablePatternAvailablePropertyId", },
81 { UIA_IsTableItemPatternAvailablePropertyId, "UIA_IsTableItemPatternAvailablePropertyId", },
82 { UIA_IsTextPatternAvailablePropertyId, "UIA_IsTextPatternAvailablePropertyId", },
83 { UIA_IsTogglePatternAvailablePropertyId, "UIA_IsTogglePatternAvailablePropertyId", },
84 { UIA_IsTransformPatternAvailablePropertyId, "UIA_IsTransformPatternAvailablePropertyId", },
85 { UIA_IsValuePatternAvailablePropertyId, "UIA_IsValuePatternAvailablePropertyId", },
86 { UIA_IsWindowPatternAvailablePropertyId, "UIA_IsWindowPatternAvailablePropertyId", },
87 { UIA_ValueValuePropertyId, "UIA_ValueValuePropertyId", },
88 { UIA_ValueIsReadOnlyPropertyId, "UIA_ValueIsReadOnlyPropertyId", },
89 { UIA_RangeValueValuePropertyId, "UIA_RangeValueValuePropertyId", },
90 { UIA_RangeValueIsReadOnlyPropertyId, "UIA_RangeValueIsReadOnlyPropertyId", },
91 { UIA_RangeValueMinimumPropertyId, "UIA_RangeValueMinimumPropertyId", },
92 { UIA_RangeValueMaximumPropertyId, "UIA_RangeValueMaximumPropertyId", },
93 { UIA_RangeValueLargeChangePropertyId, "UIA_RangeValueLargeChangePropertyId", },
94 { UIA_RangeValueSmallChangePropertyId, "UIA_RangeValueSmallChangePropertyId", },
95 { UIA_ScrollHorizontalScrollPercentPropertyId, "UIA_ScrollHorizontalScrollPercentPropertyId", },
96 { UIA_ScrollHorizontalViewSizePropertyId, "UIA_ScrollHorizontalViewSizePropertyId", },
97 { UIA_ScrollVerticalScrollPercentPropertyId, "UIA_ScrollVerticalScrollPercentPropertyId", },
98 { UIA_ScrollVerticalViewSizePropertyId, "UIA_ScrollVerticalViewSizePropertyId", },
99 { UIA_ScrollHorizontallyScrollablePropertyId, "UIA_ScrollHorizontallyScrollablePropertyId", },
100 { UIA_ScrollVerticallyScrollablePropertyId, "UIA_ScrollVerticallyScrollablePropertyId", },
101 { UIA_SelectionSelectionPropertyId, "UIA_SelectionSelectionPropertyId", },
102 { UIA_SelectionCanSelectMultiplePropertyId, "UIA_SelectionCanSelectMultiplePropertyId", },
103 { UIA_SelectionIsSelectionRequiredPropertyId, "UIA_SelectionIsSelectionRequiredPropertyId", },
104 { UIA_GridRowCountPropertyId, "UIA_GridRowCountPropertyId", },
105 { UIA_GridColumnCountPropertyId, "UIA_GridColumnCountPropertyId", },
106 { UIA_GridItemRowPropertyId, "UIA_GridItemRowPropertyId", },
107 { UIA_GridItemColumnPropertyId, "UIA_GridItemColumnPropertyId", },
108 { UIA_GridItemRowSpanPropertyId, "UIA_GridItemRowSpanPropertyId", },
109 { UIA_GridItemColumnSpanPropertyId, "UIA_GridItemColumnSpanPropertyId", },
110 { UIA_GridItemContainingGridPropertyId, "UIA_GridItemContainingGridPropertyId", },
111 { UIA_DockDockPositionPropertyId, "UIA_DockDockPositionPropertyId", },
112 { UIA_ExpandCollapseExpandCollapseStatePropertyId, "UIA_ExpandCollapseExpandCollapseStatePropertyId", },
113 { UIA_MultipleViewCurrentViewPropertyId, "UIA_MultipleViewCurrentViewPropertyId", },
114 { UIA_MultipleViewSupportedViewsPropertyId, "UIA_MultipleViewSupportedViewsPropertyId", },
115 { UIA_WindowCanMaximizePropertyId, "UIA_WindowCanMaximizePropertyId", },
116 { UIA_WindowCanMinimizePropertyId, "UIA_WindowCanMinimizePropertyId", },
117 { UIA_WindowWindowVisualStatePropertyId, "UIA_WindowWindowVisualStatePropertyId", },
118 { UIA_WindowWindowInteractionStatePropertyId, "UIA_WindowWindowInteractionStatePropertyId", },
119 { UIA_WindowIsModalPropertyId, "UIA_WindowIsModalPropertyId", },
120 { UIA_WindowIsTopmostPropertyId, "UIA_WindowIsTopmostPropertyId", },
121 { UIA_SelectionItemIsSelectedPropertyId, "UIA_SelectionItemIsSelectedPropertyId", },
122 { UIA_SelectionItemSelectionContainerPropertyId, "UIA_SelectionItemSelectionContainerPropertyId", },
123 { UIA_TableRowHeadersPropertyId, "UIA_TableRowHeadersPropertyId", },
124 { UIA_TableColumnHeadersPropertyId, "UIA_TableColumnHeadersPropertyId", },
125 { UIA_TableRowOrColumnMajorPropertyId, "UIA_TableRowOrColumnMajorPropertyId", },
126 { UIA_TableItemRowHeaderItemsPropertyId, "UIA_TableItemRowHeaderItemsPropertyId", },
127 { UIA_TableItemColumnHeaderItemsPropertyId, "UIA_TableItemColumnHeaderItemsPropertyId", },
128 { UIA_ToggleToggleStatePropertyId, "UIA_ToggleToggleStatePropertyId", },
129 { UIA_TransformCanMovePropertyId, "UIA_TransformCanMovePropertyId", },
130 { UIA_TransformCanResizePropertyId, "UIA_TransformCanResizePropertyId", },
131 { UIA_TransformCanRotatePropertyId, "UIA_TransformCanRotatePropertyId", },
132 { UIA_IsLegacyIAccessiblePatternAvailablePropertyId, "UIA_IsLegacyIAccessiblePatternAvailablePropertyId", },
133 { UIA_LegacyIAccessibleChildIdPropertyId, "UIA_LegacyIAccessibleChildIdPropertyId", },
134 { UIA_LegacyIAccessibleNamePropertyId, "UIA_LegacyIAccessibleNamePropertyId", },
135 { UIA_LegacyIAccessibleValuePropertyId, "UIA_LegacyIAccessibleValuePropertyId", },
136 { UIA_LegacyIAccessibleDescriptionPropertyId, "UIA_LegacyIAccessibleDescriptionPropertyId", },
137 { UIA_LegacyIAccessibleRolePropertyId, "UIA_LegacyIAccessibleRolePropertyId", },
138 { UIA_LegacyIAccessibleStatePropertyId, "UIA_LegacyIAccessibleStatePropertyId", },
139 { UIA_LegacyIAccessibleHelpPropertyId, "UIA_LegacyIAccessibleHelpPropertyId", },
140 { UIA_LegacyIAccessibleKeyboardShortcutPropertyId, "UIA_LegacyIAccessibleKeyboardShortcutPropertyId", },
141 { UIA_LegacyIAccessibleSelectionPropertyId, "UIA_LegacyIAccessibleSelectionPropertyId", },
142 { UIA_LegacyIAccessibleDefaultActionPropertyId, "UIA_LegacyIAccessibleDefaultActionPropertyId", },
143 { UIA_AriaRolePropertyId, "UIA_AriaRolePropertyId", },
144 { UIA_AriaPropertiesPropertyId, "UIA_AriaPropertiesPropertyId", },
145 { UIA_IsDataValidForFormPropertyId, "UIA_IsDataValidForFormPropertyId", },
146 { UIA_ControllerForPropertyId, "UIA_ControllerForPropertyId", },
147 { UIA_DescribedByPropertyId, "UIA_DescribedByPropertyId", },
148 { UIA_FlowsToPropertyId, "UIA_FlowsToPropertyId", },
149 { UIA_ProviderDescriptionPropertyId, "UIA_ProviderDescriptionPropertyId", },
150 { UIA_IsItemContainerPatternAvailablePropertyId, "UIA_IsItemContainerPatternAvailablePropertyId", },
151 { UIA_IsVirtualizedItemPatternAvailablePropertyId, "UIA_IsVirtualizedItemPatternAvailablePropertyId", },
152 { UIA_IsSynchronizedInputPatternAvailablePropertyId, "UIA_IsSynchronizedInputPatternAvailablePropertyId", },
153 { UIA_OptimizeForVisualContentPropertyId, "UIA_OptimizeForVisualContentPropertyId", },
154 { UIA_IsObjectModelPatternAvailablePropertyId, "UIA_IsObjectModelPatternAvailablePropertyId", },
155 { UIA_AnnotationAnnotationTypeIdPropertyId, "UIA_AnnotationAnnotationTypeIdPropertyId", },
156 { UIA_AnnotationAnnotationTypeNamePropertyId, "UIA_AnnotationAnnotationTypeNamePropertyId", },
157 { UIA_AnnotationAuthorPropertyId, "UIA_AnnotationAuthorPropertyId", },
158 { UIA_AnnotationDateTimePropertyId, "UIA_AnnotationDateTimePropertyId", },
159 { UIA_AnnotationTargetPropertyId, "UIA_AnnotationTargetPropertyId", },
160 { UIA_IsAnnotationPatternAvailablePropertyId, "UIA_IsAnnotationPatternAvailablePropertyId", },
161 { UIA_IsTextPattern2AvailablePropertyId, "UIA_IsTextPattern2AvailablePropertyId", },
162 { UIA_StylesStyleIdPropertyId, "UIA_StylesStyleIdPropertyId", },
163 { UIA_StylesStyleNamePropertyId, "UIA_StylesStyleNamePropertyId", },
164 { UIA_StylesFillColorPropertyId, "UIA_StylesFillColorPropertyId", },
165 { UIA_StylesFillPatternStylePropertyId, "UIA_StylesFillPatternStylePropertyId", },
166 { UIA_StylesShapePropertyId, "UIA_StylesShapePropertyId", },
167 { UIA_StylesFillPatternColorPropertyId, "UIA_StylesFillPatternColorPropertyId", },
168 { UIA_StylesExtendedPropertiesPropertyId, "UIA_StylesExtendedPropertiesPropertyId", },
169 { UIA_IsStylesPatternAvailablePropertyId, "UIA_IsStylesPatternAvailablePropertyId", },
170 { UIA_IsSpreadsheetPatternAvailablePropertyId, "UIA_IsSpreadsheetPatternAvailablePropertyId", },
171 { UIA_SpreadsheetItemFormulaPropertyId, "UIA_SpreadsheetItemFormulaPropertyId", },
172 { UIA_SpreadsheetItemAnnotationObjectsPropertyId, "UIA_SpreadsheetItemAnnotationObjectsPropertyId", },
173 { UIA_SpreadsheetItemAnnotationTypesPropertyId, "UIA_SpreadsheetItemAnnotationTypesPropertyId", },
174 { UIA_IsSpreadsheetItemPatternAvailablePropertyId, "UIA_IsSpreadsheetItemPatternAvailablePropertyId", },
175 { UIA_Transform2CanZoomPropertyId, "UIA_Transform2CanZoomPropertyId", },
176 { UIA_IsTransformPattern2AvailablePropertyId, "UIA_IsTransformPattern2AvailablePropertyId", },
177 { UIA_LiveSettingPropertyId, "UIA_LiveSettingPropertyId", },
178 { UIA_IsTextChildPatternAvailablePropertyId, "UIA_IsTextChildPatternAvailablePropertyId", },
179 { UIA_IsDragPatternAvailablePropertyId, "UIA_IsDragPatternAvailablePropertyId", },
180 { UIA_DragIsGrabbedPropertyId, "UIA_DragIsGrabbedPropertyId", },
181 { UIA_DragDropEffectPropertyId, "UIA_DragDropEffectPropertyId", },
182 { UIA_DragDropEffectsPropertyId, "UIA_DragDropEffectsPropertyId", },
183 { UIA_IsDropTargetPatternAvailablePropertyId, "UIA_IsDropTargetPatternAvailablePropertyId", },
184 { UIA_DropTargetDropTargetEffectPropertyId, "UIA_DropTargetDropTargetEffectPropertyId", },
185 { UIA_DropTargetDropTargetEffectsPropertyId, "UIA_DropTargetDropTargetEffectsPropertyId", },
186 { UIA_DragGrabbedItemsPropertyId, "UIA_DragGrabbedItemsPropertyId", },
187 { UIA_Transform2ZoomLevelPropertyId, "UIA_Transform2ZoomLevelPropertyId", },
188 { UIA_Transform2ZoomMinimumPropertyId, "UIA_Transform2ZoomMinimumPropertyId", },
189 { UIA_Transform2ZoomMaximumPropertyId, "UIA_Transform2ZoomMaximumPropertyId", },
190 { UIA_FlowsFromPropertyId, "UIA_FlowsFromPropertyId", },
191 { UIA_IsTextEditPatternAvailablePropertyId, "UIA_IsTextEditPatternAvailablePropertyId", },
192 { UIA_IsPeripheralPropertyId, "UIA_IsPeripheralPropertyId", },
193 { UIA_IsCustomNavigationPatternAvailablePropertyId, "UIA_IsCustomNavigationPatternAvailablePropertyId", },
194 { UIA_PositionInSetPropertyId, "UIA_PositionInSetPropertyId", },
195 { UIA_SizeOfSetPropertyId, "UIA_SizeOfSetPropertyId", },
196 { UIA_LevelPropertyId, "UIA_LevelPropertyId", },
197 { UIA_AnnotationTypesPropertyId, "UIA_AnnotationTypesPropertyId", },
198 { UIA_AnnotationObjectsPropertyId, "UIA_AnnotationObjectsPropertyId", },
199 { UIA_LandmarkTypePropertyId, "UIA_LandmarkTypePropertyId", },
200 { UIA_LocalizedLandmarkTypePropertyId, "UIA_LocalizedLandmarkTypePropertyId", },
201 { UIA_FullDescriptionPropertyId, "UIA_FullDescriptionPropertyId", },
202 { UIA_FillColorPropertyId, "UIA_FillColorPropertyId", },
203 { UIA_OutlineColorPropertyId, "UIA_OutlineColorPropertyId", },
204 { UIA_FillTypePropertyId, "UIA_FillTypePropertyId", },
205 { UIA_VisualEffectsPropertyId, "UIA_VisualEffectsPropertyId", },
206 { UIA_OutlineThicknessPropertyId, "UIA_OutlineThicknessPropertyId", },
207 { UIA_CenterPointPropertyId, "UIA_CenterPointPropertyId", },
208 { UIA_RotationPropertyId, "UIA_RotationPropertyId", },
209 { UIA_SizePropertyId, "UIA_SizePropertyId", },
210 { UIA_IsSelectionPattern2AvailablePropertyId, "UIA_IsSelectionPattern2AvailablePropertyId", },
211 { UIA_Selection2FirstSelectedItemPropertyId, "UIA_Selection2FirstSelectedItemPropertyId", },
212 { UIA_Selection2LastSelectedItemPropertyId, "UIA_Selection2LastSelectedItemPropertyId", },
213 { UIA_Selection2CurrentSelectedItemPropertyId, "UIA_Selection2CurrentSelectedItemPropertyId", },
214 { UIA_Selection2ItemCountPropertyId, "UIA_Selection2ItemCountPropertyId", },
215 { UIA_HeadingLevelPropertyId, "UIA_HeadingLevelPropertyId", },
216 { UIA_IsDialogPropertyId, "UIA_IsDialogPropertyId", },
217};
218
219static const struct str_id_pair uia_pattern_id_strs[] = {
220 { UIA_InvokePatternId, "UIA_InvokePatternId", },
221 { UIA_SelectionPatternId, "UIA_SelectionPatternId", },
222 { UIA_ValuePatternId, "UIA_ValuePatternId", },
223 { UIA_RangeValuePatternId, "UIA_RangeValuePatternId", },
224 { UIA_ScrollPatternId, "UIA_ScrollPatternId", },
225 { UIA_ExpandCollapsePatternId, "UIA_ExpandCollapsePatternId", },
226 { UIA_GridPatternId, "UIA_GridPatternId", },
227 { UIA_GridItemPatternId, "UIA_GridItemPatternId", },
228 { UIA_MultipleViewPatternId, "UIA_MultipleViewPatternId", },
229 { UIA_WindowPatternId, "UIA_WindowPatternId", },
230 { UIA_SelectionItemPatternId, "UIA_SelectionItemPatternId", },
231 { UIA_DockPatternId, "UIA_DockPatternId", },
232 { UIA_TablePatternId, "UIA_TablePatternId", },
233 { UIA_TableItemPatternId, "UIA_TableItemPatternId", },
234 { UIA_TextPatternId, "UIA_TextPatternId", },
235 { UIA_TogglePatternId, "UIA_TogglePatternId", },
236 { UIA_TransformPatternId, "UIA_TransformPatternId", },
237 { UIA_ScrollItemPatternId, "UIA_ScrollItemPatternId", },
238 { UIA_LegacyIAccessiblePatternId, "UIA_LegacyIAccessiblePatternId", },
239 { UIA_ItemContainerPatternId, "UIA_ItemContainerPatternId", },
240 { UIA_VirtualizedItemPatternId, "UIA_VirtualizedItemPatternId", },
241 { UIA_SynchronizedInputPatternId, "UIA_SynchronizedInputPatternId", },
242 { UIA_ObjectModelPatternId, "UIA_ObjectModelPatternId", },
243 { UIA_AnnotationPatternId, "UIA_AnnotationPatternId", },
244 { UIA_TextPattern2Id, "UIA_TextPattern2Id", },
245 { UIA_StylesPatternId, "UIA_StylesPatternId", },
246 { UIA_SpreadsheetPatternId, "UIA_SpreadsheetPatternId", },
247 { UIA_SpreadsheetItemPatternId, "UIA_SpreadsheetItemPatternId", },
248 { UIA_TransformPattern2Id, "UIA_TransformPattern2Id", },
249 { UIA_TextChildPatternId, "UIA_TextChildPatternId", },
250 { UIA_DragPatternId, "UIA_DragPatternId", },
251 { UIA_DropTargetPatternId, "UIA_DropTargetPatternId", },
252 { UIA_TextEditPatternId, "UIA_TextEditPatternId", },
253 { UIA_CustomNavigationPatternId, "UIA_CustomNavigationPatternId", },
254};
255
256static const struct str_id_pair uia_nav_dir_strs[] = {
257 { NavigateDirection_Parent, "NavigateDirection_Parent" },
258 { NavigateDirection_NextSibling, "NavigateDirection_NextSibling" },
259 { NavigateDirection_PreviousSibling, "NavigateDirection_PreviousSibling" },
260 { NavigateDirection_FirstChild, "NavigateDirection_FirstChild" },
261 { NavigateDirection_LastChild, "NavigateDirection_LastChild" },
262};
263
264static const struct str_id_pair uia_event_id_strs[] = {
265 { UIA_ToolTipOpenedEventId, "UIA_ToolTipOpenedEventId" },
266 { UIA_ToolTipClosedEventId, "UIA_ToolTipClosedEventId", },
267 { UIA_StructureChangedEventId, "UIA_StructureChangedEventId", },
268 { UIA_MenuOpenedEventId, "UIA_MenuOpenedEventId", },
269 { UIA_AutomationPropertyChangedEventId, "UIA_AutomationPropertyChangedEventId", },
270 { UIA_AutomationFocusChangedEventId, "UIA_AutomationFocusChangedEventId", },
271 { UIA_AsyncContentLoadedEventId, "UIA_AsyncContentLoadedEventId", },
272 { UIA_MenuClosedEventId, "UIA_MenuClosedEventId", },
273 { UIA_LayoutInvalidatedEventId, "UIA_LayoutInvalidatedEventId", },
274 { UIA_Invoke_InvokedEventId, "UIA_Invoke_InvokedEventId", },
275 { UIA_SelectionItem_ElementAddedToSelectionEventId, "UIA_SelectionItem_ElementAddedToSelectionEventId", },
276 { UIA_SelectionItem_ElementRemovedFromSelectionEventId, "UIA_SelectionItem_ElementRemovedFromSelectionEventId", },
277 { UIA_SelectionItem_ElementSelectedEventId, "UIA_SelectionItem_ElementSelectedEventId", },
278 { UIA_Selection_InvalidatedEventId, "UIA_Selection_InvalidatedEventId", },
279 { UIA_Text_TextSelectionChangedEventId, "UIA_Text_TextSelectionChangedEventId", },
280 { UIA_Text_TextChangedEventId, "UIA_Text_TextChangedEventId", },
281 { UIA_Window_WindowOpenedEventId, "UIA_Window_WindowOpenedEventId", },
282 { UIA_Window_WindowClosedEventId, "UIA_Window_WindowClosedEventId", },
283 { UIA_MenuModeStartEventId, "UIA_MenuModeStartEventId", },
284 { UIA_MenuModeEndEventId, "UIA_MenuModeEndEventId", },
285 { UIA_InputReachedTargetEventId, "UIA_InputReachedTargetEventId", },
286 { UIA_InputReachedOtherElementEventId, "UIA_InputReachedOtherElementEventId", },
287 { UIA_InputDiscardedEventId, "UIA_InputDiscardedEventId", },
288 { UIA_SystemAlertEventId, "UIA_SystemAlertEventId", },
289 { UIA_LiveRegionChangedEventId, "UIA_LiveRegionChangedEventId", },
290 { UIA_HostedFragmentRootsInvalidatedEventId, "UIA_HostedFragmentRootsInvalidatedEventId", },
291 { UIA_Drag_DragStartEventId, "UIA_Drag_DragStartEventId", },
292 { UIA_Drag_DragCancelEventId, "UIA_Drag_DragCancelEventId", },
293 { UIA_Drag_DragCompleteEventId, "UIA_Drag_DragCompleteEventId", },
294 { UIA_DropTarget_DragEnterEventId, "UIA_DropTarget_DragEnterEventId", },
295 { UIA_DropTarget_DragLeaveEventId, "UIA_DropTarget_DragLeaveEventId", },
296 { UIA_DropTarget_DroppedEventId, "UIA_DropTarget_DroppedEventId", },
297 { UIA_TextEdit_TextChangedEventId, "UIA_TextEdit_TextChangedEventId", },
298 { UIA_TextEdit_ConversionTargetChangedEventId, "UIA_TextEdit_ConversionTargetChangedEventId", },
299 { UIA_ChangesEventId, "UIA_ChangesEventId", },
300 { UIA_NotificationEventId, "UIA_NotificationEventId", },
301};
302
303static int __cdecl str_id_pair_compare(const void *a, const void *b)
304{
305 const int *id = a;
306 const struct str_id_pair *pair = b;
307
308 return ((*id) > pair->id) - ((*id) < pair->id);
309}
310
311#define get_str_for_id(id, id_pair) \
312 get_str_from_id_pair( (id), (id_pair), (ARRAY_SIZE(id_pair)) )
313static const char *get_str_from_id_pair(int id, const struct str_id_pair *id_pair, int id_pair_size)
314{
315 const struct str_id_pair *pair;
316
317 if (!(pair = bsearch(&id, id_pair, id_pair_size, sizeof(*pair), str_id_pair_compare)))
318 return "";
319 else
320 return pair->str;
321}
322
323
324#define PROV_METHOD_TRACE(prov, method) \
325 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method "\n", GetCurrentProcessId(), GetCurrentThreadId(), (prov)->prov_name);
326
327#define PROV_METHOD_TRACE2(prov, method, arg, str_table) \
328 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method ": %d (%s)\n", GetCurrentProcessId(), GetCurrentThreadId(), (prov)->prov_name, \
329 arg, get_str_for_id(arg, str_table)); \
330
331#define ACC_METHOD_TRACE(acc, method) \
332 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method "\n", GetCurrentProcessId(), GetCurrentThreadId(), (acc)->interface_name);
333
334#define ACC_METHOD_TRACE2(acc, cid, method) \
335 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method ": %s\n", GetCurrentProcessId(), GetCurrentThreadId(), \
336 (acc)->interface_name, debugstr_variant((cid)));
337
338#define DEFINE_EXPECT(func) \
339 static int expect_ ## func = 0, called_ ## func = 0
340
341#define SET_EXPECT(func) \
342 do { called_ ## func = 0; expect_ ## func = 1; } while(0)
343
344#define SET_EXPECT_MULTI(func, num) \
345 do { called_ ## func = 0; expect_ ## func = num; } while(0)
346
347#define CHECK_EXPECT2(func) \
348 do { \
349 ok(expect_ ##func, "unexpected call " #func "\n"); \
350 called_ ## func++; \
351 }while(0)
352
353#define CHECK_EXPECT(func) \
354 do { \
355 CHECK_EXPECT2(func); \
356 expect_ ## func--; \
357 }while(0)
358
359#define CALLED_COUNT(func) \
360 called_ ## func
361
362#define CHECK_CALLED(func) \
363 do { \
364 ok(called_ ## func, "expected " #func "\n"); \
365 expect_ ## func = called_ ## func = 0; \
366 }while(0)
367
368#define CHECK_CALLED_MULTI(func, num) \
369 do { \
370 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
371 expect_ ## func = called_ ## func = 0; \
372 }while(0)
373
374#define CHECK_CALLED_AT_LEAST(func, num) \
375 do { \
376 ok(called_ ## func >= num, "expected " #func " at least %d time(s) (got %d)\n", num, called_ ## func); \
377 expect_ ## func = called_ ## func = 0; \
378 }while(0)
379
380#define CHECK_CALLED_AT_MOST(func, num) \
381 do { \
382 ok(called_ ## func <= num, "expected " #func " at most %d time(s) (got %d)\n", num, called_ ## func); \
383 expect_ ## func = called_ ## func = 0; \
384 }while(0)
385
386#define NAVDIR_INTERNAL_HWND 10
387#define UIA_RUNTIME_ID_PREFIX 42
388
389DEFINE_EXPECT(winproc_GETOBJECT_CLIENT);
390DEFINE_EXPECT(prov_callback_base_hwnd);
391DEFINE_EXPECT(prov_callback_nonclient);
392DEFINE_EXPECT(prov_callback_proxy);
393DEFINE_EXPECT(prov_callback_parent_proxy);
397DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot);
398DEFINE_EXPECT(child_winproc_GETOBJECT_UiaRoot);
402
404{
405 if (V_VT(v) == VT_I4 && V_I4(v) == val)
406 return TRUE;
407
408 return FALSE;
409}
410
412{
413 if (V_VT(v) == VT_BOOL && V_BOOL(v) == (val ? VARIANT_TRUE : VARIANT_FALSE))
414 return TRUE;
415
416 return FALSE;
417}
418
420{
421 V_VT(v) = VT_BOOL;
422 V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE;
423}
424
425static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
426{
427 IUnknown *unk1, *unk2;
428 BOOL cmp;
429
430 IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
431 IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
432 cmp = unk1 == unk2;
433
434 IUnknown_Release(unk1);
435 IUnknown_Release(unk2);
436 return cmp;
437}
438
439#define test_implements_interface( unk, iid, exp_implemented ) \
440 test_implements_interface_( ((IUnknown *)(unk)), (iid), (exp_implemented), __FILE__, __LINE__)
441static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_implemented, const char *file, int line)
442{
443 IUnknown *unk2 = NULL;
444 HRESULT hr;
445
446 hr = IUnknown_QueryInterface(unk, iid, (void **)&unk2);
447 ok_(file, line)(hr == (exp_implemented ? S_OK : E_NOINTERFACE), "Unexpected hr %#lx\n", hr);
448 ok_(file, line)(!!unk2 == exp_implemented, "Unexpected iface %p\n", unk2);
449 if (unk2)
450 IUnknown_Release(unk2);
451}
452
453#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
454 check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
455static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file,
456 int line);
457
458#define DEFINE_ACC_METHOD_EXPECT(method) \
459 int expect_ ## method , called_ ## method
460
461#define DEFINE_ACC_METHOD_EXPECTS \
462 DEFINE_ACC_METHOD_EXPECT(QI_IAccIdentity); \
463 DEFINE_ACC_METHOD_EXPECT(get_accParent); \
464 DEFINE_ACC_METHOD_EXPECT(get_accChildCount); \
465 DEFINE_ACC_METHOD_EXPECT(get_accChild); \
466 DEFINE_ACC_METHOD_EXPECT(get_accName); \
467 DEFINE_ACC_METHOD_EXPECT(get_accValue); \
468 DEFINE_ACC_METHOD_EXPECT(get_accDescription); \
469 DEFINE_ACC_METHOD_EXPECT(get_accRole); \
470 DEFINE_ACC_METHOD_EXPECT(get_accState); \
471 DEFINE_ACC_METHOD_EXPECT(get_accHelp); \
472 DEFINE_ACC_METHOD_EXPECT(get_accHelpTopic); \
473 DEFINE_ACC_METHOD_EXPECT(get_accKeyboardShortcut); \
474 DEFINE_ACC_METHOD_EXPECT(get_accFocus); \
475 DEFINE_ACC_METHOD_EXPECT(get_accSelection); \
476 DEFINE_ACC_METHOD_EXPECT(get_accDefaultAction); \
477 DEFINE_ACC_METHOD_EXPECT(accSelect); \
478 DEFINE_ACC_METHOD_EXPECT(accLocation); \
479 DEFINE_ACC_METHOD_EXPECT(accNavigate); \
480 DEFINE_ACC_METHOD_EXPECT(accHitTest); \
481 DEFINE_ACC_METHOD_EXPECT(accDoDefaultAction); \
482 DEFINE_ACC_METHOD_EXPECT(put_accName); \
483 DEFINE_ACC_METHOD_EXPECT(put_accValue); \
484 DEFINE_ACC_METHOD_EXPECT(get_nRelations); \
485 DEFINE_ACC_METHOD_EXPECT(get_relation); \
486 DEFINE_ACC_METHOD_EXPECT(get_relations); \
487 DEFINE_ACC_METHOD_EXPECT(role); \
488 DEFINE_ACC_METHOD_EXPECT(scrollTo); \
489 DEFINE_ACC_METHOD_EXPECT(scrollToPoint); \
490 DEFINE_ACC_METHOD_EXPECT(get_groupPosition); \
491 DEFINE_ACC_METHOD_EXPECT(get_states); \
492 DEFINE_ACC_METHOD_EXPECT(get_extendedRole); \
493 DEFINE_ACC_METHOD_EXPECT(get_localizedExtendedRole); \
494 DEFINE_ACC_METHOD_EXPECT(get_nExtendedStates); \
495 DEFINE_ACC_METHOD_EXPECT(get_extendedStates); \
496 DEFINE_ACC_METHOD_EXPECT(get_localizedExtendedStates); \
497 DEFINE_ACC_METHOD_EXPECT(get_uniqueID); \
498 DEFINE_ACC_METHOD_EXPECT(get_windowHandle); \
499 DEFINE_ACC_METHOD_EXPECT(get_indexInParent); \
500 DEFINE_ACC_METHOD_EXPECT(get_locale); \
501 DEFINE_ACC_METHOD_EXPECT(get_attributes) \
502
503static DWORD msg_wait_for_all_events(HANDLE *event_handles, int event_handle_count, DWORD timeout_val)
504{
505 int events_handled = 0;
506 DWORD wait_res;
507
508 while ((wait_res = MsgWaitForMultipleObjects(event_handle_count, (const HANDLE *)event_handles, FALSE, timeout_val,
509 QS_ALLINPUT)) <= (WAIT_OBJECT_0 + event_handle_count))
510 {
511 if (wait_res == (WAIT_OBJECT_0 + event_handle_count))
512 {
513 MSG msg;
514
515 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
516 {
519 }
520 }
521 else
522 events_handled++;
523
524 if (events_handled == event_handle_count)
525 break;
526 }
527
528 return wait_res;
529}
530
531static struct Accessible
532{
538
539 const char *interface_name;
540
555
556#define SET_ACC_METHOD_EXPECT(acc, method) \
557 do { (acc)->called_ ## method = 0; (acc)->expect_ ## method = 1; } while(0)
558
559#define SET_ACC_METHOD_EXPECT_MULTI(acc, method, num) \
560 do { (acc)->called_ ## method = 0; (acc)->expect_ ## method = num; } while(0)
561
562#define CHECK_ACC_METHOD_EXPECT2(acc, method) \
563 do { \
564 ok((acc)->expect_ ##method, "unexpected call %s_" #method "\n", (acc)->interface_name); \
565 (acc)->called_ ## method++; \
566 }while(0)
567
568#define CHECK_ACC_METHOD_EXPECT(acc, method) \
569 do { \
570 CHECK_ACC_METHOD_EXPECT2(acc, method); \
571 (acc)->expect_ ## method--; \
572 }while(0)
573
574#define CHECK_ACC_METHOD_CALLED(acc, method) \
575 do { \
576 ok((acc)->called_ ## method, "expected %s_" #method "\n", (acc)->interface_name); \
577 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
578 }while(0)
579
580#define CHECK_ACC_METHOD_CALLED_MULTI(acc, method, num) \
581 do { \
582 ok((acc)->called_ ## method == num, "expected %s_" #method " %d times (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
583 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
584 }while(0)
585
586#define CHECK_ACC_METHOD_CALLED_AT_LEAST(acc, method, num) \
587 do { \
588 ok((acc)->called_ ## method >= num, "expected %s_" #method " at least %d time(s) (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
589 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
590 }while(0)
591
592#define CHECK_ACC_METHOD_CALLED_AT_MOST(acc, method, num) \
593 do { \
594 ok((acc)->called_ ## method <= num, "expected %s_" #method " at most %d time(s) (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
595 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
596 }while(0)
597
598static inline struct Accessible* impl_from_Accessible(IAccessible *iface)
599{
600 return CONTAINING_RECORD(iface, struct Accessible, IAccessible_iface);
601}
602
604{
605 struct Accessible *This = impl_from_Accessible(iface);
606
607 *obj = NULL;
608 if (IsEqualIID(riid, &IID_IAccIdentity))
609 {
610 CHECK_ACC_METHOD_EXPECT(This, QI_IAccIdentity);
611 ACC_METHOD_TRACE(This, QI_IAccIdentity);
612 return E_NOINTERFACE;
613 }
614
616 IsEqualIID(riid, &IID_IAccessible))
617 *obj = iface;
618 else if (IsEqualIID(riid, &IID_IOleWindow))
619 *obj = &This->IOleWindow_iface;
620 else if (IsEqualIID(riid, &IID_IServiceProvider))
621 *obj = &This->IServiceProvider_iface;
622 else if (IsEqualIID(riid, &IID_IAccessible2) && This->enable_ia2)
623 *obj = &This->IAccessible2_iface;
624 else
625 return E_NOINTERFACE;
626
627 IAccessible_AddRef(iface);
628 return S_OK;
629}
630
632{
633 struct Accessible *This = impl_from_Accessible(iface);
634 return InterlockedIncrement(&This->ref);
635}
636
638{
639 struct Accessible *This = impl_from_Accessible(iface);
640 return InterlockedDecrement(&This->ref);
641}
642
644{
645 ok(0, "unexpected call\n");
646 return E_NOTIMPL;
647}
648
650 LCID lcid, ITypeInfo **out_tinfo)
651{
652 ok(0, "unexpected call\n");
653 return E_NOTIMPL;
654}
655
657 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
658{
659 ok(0, "unexpected call\n");
660 return E_NOTIMPL;
661}
662
663static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID disp_id_member,
664 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
665 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
666{
667 ok(0, "unexpected call\n");
668 return E_NOTIMPL;
669}
670
672{
673 struct Accessible *This = impl_from_Accessible(iface);
674
675 CHECK_ACC_METHOD_EXPECT(This, get_accParent);
676 ACC_METHOD_TRACE(This, get_accParent);
677 if (This->parent)
678 return IAccessible_QueryInterface(This->parent, &IID_IDispatch, (void **)out_parent);
679
680 *out_parent = NULL;
681 return S_FALSE;
682}
683
685{
686 struct Accessible *This = impl_from_Accessible(iface);
687
688 CHECK_ACC_METHOD_EXPECT(This, get_accChildCount);
689 ACC_METHOD_TRACE(This, get_accChildCount);
690 if (This->child_count)
691 {
692 *out_count = This->child_count;
693 return S_OK;
694 }
695
696 return E_NOTIMPL;
697}
698
700 IDispatch **out_child)
701{
702 struct Accessible *This = impl_from_Accessible(iface);
703
704 CHECK_ACC_METHOD_EXPECT(This, get_accChild);
705 ACC_METHOD_TRACE2(This, &child_id, get_accChild);
706
707 *out_child = NULL;
708 if (V_VT(&child_id) != VT_I4)
709 return E_INVALIDARG;
710
711 if (This == &Accessible)
712 {
713 switch (V_I4(&child_id))
714 {
715 case CHILDID_SELF:
716 return IAccessible_QueryInterface(&This->IAccessible_iface, &IID_IDispatch, (void **)out_child);
717
718 /* Simple element children. */
719 case 1:
720 case 3:
721 return S_FALSE;
722
723 case 2:
724 return IAccessible_QueryInterface(&Accessible_child.IAccessible_iface, &IID_IDispatch, (void **)out_child);
725
726 case 4:
727 return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
728
729 case 7:
730 return IAccessible_QueryInterface(&Accessible.IAccessible_iface, &IID_IDispatch, (void **)out_child);
731
732 default:
733 break;
734
735 }
736 }
737 return E_NOTIMPL;
738}
739
741 BSTR *out_name)
742{
743 struct Accessible *This = impl_from_Accessible(iface);
744
745 CHECK_ACC_METHOD_EXPECT(This, get_accName);
746 ACC_METHOD_TRACE2(This, &child_id, get_accName);
747
748 *out_name = NULL;
749 if (This->name)
750 {
751 *out_name = SysAllocString(This->name);
752 return S_OK;
753 }
754
755 return E_NOTIMPL;
756}
757
759 BSTR *out_value)
760{
761 struct Accessible *This = impl_from_Accessible(iface);
762 CHECK_ACC_METHOD_EXPECT(This, get_accValue);
763 ACC_METHOD_TRACE2(This, &child_id, get_accValue);
764 return E_NOTIMPL;
765}
766
768 BSTR *out_description)
769{
770 struct Accessible *This = impl_from_Accessible(iface);
771 CHECK_ACC_METHOD_EXPECT(This, get_accDescription);
772 ACC_METHOD_TRACE2(This, &child_id, get_accDescription);
773 return E_NOTIMPL;
774}
775
777 VARIANT *out_role)
778{
779 struct Accessible *This = impl_from_Accessible(iface);
780
781 CHECK_ACC_METHOD_EXPECT(This, get_accRole);
782 ACC_METHOD_TRACE2(This, &child_id, get_accRole);
783
784 if (This->role)
785 {
786 V_VT(out_role) = VT_I4;
787 V_I4(out_role) = This->role;
788 return S_OK;
789 }
790
791 return E_NOTIMPL;
792}
793
795 VARIANT *out_state)
796{
797 struct Accessible *This = impl_from_Accessible(iface);
798
799 CHECK_ACC_METHOD_EXPECT(This, get_accState);
800 ACC_METHOD_TRACE2(This, &child_id, get_accState);
801
802 if (V_VT(&child_id) != VT_I4)
803 return E_INVALIDARG;
804
805 if (This == &Accessible && V_I4(&child_id) != CHILDID_SELF)
806 {
807 switch (V_I4(&child_id))
808 {
809 case 1:
810 V_VT(out_state) = VT_I4;
811 V_I4(out_state) = STATE_SYSTEM_INVISIBLE;
812 break;
813
814 case 3:
815 V_VT(out_state) = VT_I4;
816 V_I4(out_state) = STATE_SYSTEM_FOCUSABLE;
817 break;
818
819 default:
820 return E_INVALIDARG;
821 }
822
823 return S_OK;
824 }
825
826 if (This->state)
827 {
828 V_VT(out_state) = VT_I4;
829 V_I4(out_state) = This->state;
830 return S_OK;
831 }
832
833 return E_NOTIMPL;
834}
835
837 BSTR *out_help)
838{
839 struct Accessible *This = impl_from_Accessible(iface);
840 CHECK_ACC_METHOD_EXPECT(This, get_accHelp);
841 ACC_METHOD_TRACE2(This, &child_id, get_accHelp);
842 return E_NOTIMPL;
843}
844
846 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
847{
848 struct Accessible *This = impl_from_Accessible(iface);
849 CHECK_ACC_METHOD_EXPECT(This, get_accHelpTopic);
850 ACC_METHOD_TRACE2(This, &child_id, get_accHelpTopic);
851 return E_NOTIMPL;
852}
853
855 BSTR *out_kbd_shortcut)
856{
857 struct Accessible *This = impl_from_Accessible(iface);
858 CHECK_ACC_METHOD_EXPECT(This, get_accKeyboardShortcut);
859 ACC_METHOD_TRACE2(This, &child_id, get_accKeyboardShortcut);
860 return E_NOTIMPL;
861}
862
864{
865 struct Accessible *This = impl_from_Accessible(iface);
866
867 CHECK_ACC_METHOD_EXPECT(This, get_accFocus);
868 ACC_METHOD_TRACE(This, get_accFocus);
869
870 VariantInit(pchild_id);
871 if (This->focus_acc)
872 {
873 HRESULT hr;
874
875 hr = IAccessible_QueryInterface(This->focus_acc, &IID_IDispatch, (void **)&V_DISPATCH(pchild_id));
876 if (SUCCEEDED(hr))
877 V_VT(pchild_id) = VT_DISPATCH;
878
879 return hr;
880 }
881 else if (This->focus_child_id >= 0)
882 {
883 V_VT(pchild_id) = VT_I4;
884 V_I4(pchild_id) = This->focus_child_id;
885 return S_OK;
886 }
887
888 return E_NOTIMPL;
889}
890
892{
893 struct Accessible *This = impl_from_Accessible(iface);
894 CHECK_ACC_METHOD_EXPECT(This, get_accSelection);
895 ACC_METHOD_TRACE(This, get_accSelection);
896 return E_NOTIMPL;
897}
898
900 BSTR *out_default_action)
901{
902 struct Accessible *This = impl_from_Accessible(iface);
903 CHECK_ACC_METHOD_EXPECT(This, get_accDefaultAction);
904 ACC_METHOD_TRACE2(This, &child_id, get_accDefaultAction);
905 return E_NOTIMPL;
906}
907
909 VARIANT child_id)
910{
911 struct Accessible *This = impl_from_Accessible(iface);
912 CHECK_ACC_METHOD_EXPECT(This, accSelect);
913 ACC_METHOD_TRACE2(This, &child_id, accSelect);
914 return E_NOTIMPL;
915}
916
918 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
919{
920 struct Accessible *This = impl_from_Accessible(iface);
921
922 CHECK_ACC_METHOD_EXPECT(This, accLocation);
923 ACC_METHOD_TRACE2(This, &child_id, accLocation);
924
925 if (This->width && This->height)
926 {
927 *out_left = This->left;
928 *out_top = This->top;
929 *out_width = This->width;
930 *out_height = This->height;
931 return S_OK;
932 }
933
934 return E_NOTIMPL;
935}
936
938 VARIANT child_id_start, VARIANT *out_var)
939{
940 struct Accessible *This = impl_from_Accessible(iface);
941
942 CHECK_ACC_METHOD_EXPECT(This, accNavigate);
943 ACC_METHOD_TRACE2(This, &child_id_start, accNavigate);
944
945 VariantInit(out_var);
946
947 /*
948 * This is an undocumented way for UI Automation to get an HWND for
949 * IAccessible's contained in a Direct Annotation wrapper object.
950 */
951 if ((nav_direction == NAVDIR_INTERNAL_HWND) && check_variant_i4(&child_id_start, CHILDID_SELF) &&
952 This->acc_hwnd)
953 {
954 V_VT(out_var) = VT_I4;
955 V_I4(out_var) = HandleToUlong(This->acc_hwnd);
956 return S_OK;
957 }
958 return S_FALSE;
959}
960
962 VARIANT *out_child_id)
963{
964 struct Accessible *This = impl_from_Accessible(iface);
965 CHECK_ACC_METHOD_EXPECT(This, accHitTest);
966 ACC_METHOD_TRACE(This, accHitTest);
967 return E_NOTIMPL;
968}
969
971{
972 struct Accessible *This = impl_from_Accessible(iface);
973 CHECK_ACC_METHOD_EXPECT(This, accDoDefaultAction);
974 ACC_METHOD_TRACE2(This, &child_id, accDoDefaultAction);
975 return E_NOTIMPL;
976}
977
979 BSTR name)
980{
981 struct Accessible *This = impl_from_Accessible(iface);
982 CHECK_ACC_METHOD_EXPECT(This, put_accName);
983 ACC_METHOD_TRACE2(This, &child_id, put_accName);
984 return E_NOTIMPL;
985}
986
988 BSTR value)
989{
990 struct Accessible *This = impl_from_Accessible(iface);
991 CHECK_ACC_METHOD_EXPECT(This, put_accValue);
992 ACC_METHOD_TRACE2(This, &child_id, put_accValue);
993 return E_NOTIMPL;
994}
995
996static IAccessibleVtbl AccessibleVtbl = {
1025};
1026
1027static inline struct Accessible* impl_from_Accessible2(IAccessible2 *iface)
1028{
1029 return CONTAINING_RECORD(iface, struct Accessible, IAccessible2_iface);
1030}
1031
1033{
1034 struct Accessible *This = impl_from_Accessible2(iface);
1035 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1036}
1037
1039{
1040 struct Accessible *This = impl_from_Accessible2(iface);
1041 return IAccessible_AddRef(&This->IAccessible_iface);
1042}
1043
1045{
1046 struct Accessible *This = impl_from_Accessible2(iface);
1047 return IAccessible_Release(&This->IAccessible_iface);
1048}
1049
1051{
1052 struct Accessible *This = impl_from_Accessible2(iface);
1053 return IAccessible_GetTypeInfoCount(&This->IAccessible_iface, pctinfo);
1054}
1055
1057 LCID lcid, ITypeInfo **out_tinfo)
1058{
1059 struct Accessible *This = impl_from_Accessible2(iface);
1060 return IAccessible_GetTypeInfo(&This->IAccessible_iface, iTInfo, lcid, out_tinfo);
1061}
1062
1064 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
1065{
1066 struct Accessible *This = impl_from_Accessible2(iface);
1067 return IAccessible_GetIDsOfNames(&This->IAccessible_iface, riid, rg_names, name_count,
1068 lcid, rg_disp_id);
1069}
1070
1072 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
1073 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
1074{
1075 struct Accessible *This = impl_from_Accessible2(iface);
1076 return IAccessible_Invoke(&This->IAccessible_iface, disp_id_member, riid, lcid, flags,
1077 disp_params, var_result, excep_info, arg_err);
1078}
1079
1081{
1082 struct Accessible *This = impl_from_Accessible2(iface);
1083 return IAccessible_get_accParent(&This->IAccessible_iface, out_parent);
1084}
1085
1087{
1088 struct Accessible *This = impl_from_Accessible2(iface);
1089 return IAccessible_get_accChildCount(&This->IAccessible_iface, out_count);
1090}
1091
1093 IDispatch **out_child)
1094{
1095 struct Accessible *This = impl_from_Accessible2(iface);
1096 return IAccessible_get_accChild(&This->IAccessible_iface, child_id, out_child);
1097}
1098
1100 BSTR *out_name)
1101{
1102 struct Accessible *This = impl_from_Accessible2(iface);
1103 return IAccessible_get_accName(&This->IAccessible_iface, child_id, out_name);
1104}
1105
1107 BSTR *out_value)
1108{
1109 struct Accessible *This = impl_from_Accessible2(iface);
1110 return IAccessible_get_accValue(&This->IAccessible_iface, child_id, out_value);
1111}
1112
1114 BSTR *out_description)
1115{
1116 struct Accessible *This = impl_from_Accessible2(iface);
1117 return IAccessible_get_accDescription(&This->IAccessible_iface, child_id, out_description);
1118}
1119
1121 VARIANT *out_role)
1122{
1123 struct Accessible *This = impl_from_Accessible2(iface);
1124 return IAccessible_get_accRole(&This->IAccessible_iface, child_id, out_role);
1125}
1126
1128 VARIANT *out_state)
1129{
1130 struct Accessible *This = impl_from_Accessible2(iface);
1131 return IAccessible_get_accState(&This->IAccessible_iface, child_id, out_state);
1132}
1133
1135 BSTR *out_help)
1136{
1137 struct Accessible *This = impl_from_Accessible2(iface);
1138 return IAccessible_get_accHelp(&This->IAccessible_iface, child_id, out_help);
1139}
1140
1142 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
1143{
1144 struct Accessible *This = impl_from_Accessible2(iface);
1145 return IAccessible_get_accHelpTopic(&This->IAccessible_iface, out_help_file, child_id,
1146 out_topic_id);
1147}
1148
1150 BSTR *out_kbd_shortcut)
1151{
1152 struct Accessible *This = impl_from_Accessible2(iface);
1153 return IAccessible_get_accKeyboardShortcut(&This->IAccessible_iface, child_id,
1154 out_kbd_shortcut);
1155}
1156
1158{
1159 struct Accessible *This = impl_from_Accessible2(iface);
1160 return IAccessible_get_accFocus(&This->IAccessible_iface, pchild_id);
1161}
1162
1164{
1165 struct Accessible *This = impl_from_Accessible2(iface);
1166 return IAccessible_get_accSelection(&This->IAccessible_iface, out_selection);
1167}
1168
1170 BSTR *out_default_action)
1171{
1172 struct Accessible *This = impl_from_Accessible2(iface);
1173 return IAccessible_get_accDefaultAction(&This->IAccessible_iface, child_id,
1174 out_default_action);
1175}
1176
1178 VARIANT child_id)
1179{
1180 struct Accessible *This = impl_from_Accessible2(iface);
1181 return IAccessible_accSelect(&This->IAccessible_iface, select_flags, child_id);
1182}
1183
1185 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
1186{
1187 struct Accessible *This = impl_from_Accessible2(iface);
1188 return IAccessible_accLocation(&This->IAccessible_iface, out_left, out_top, out_width,
1189 out_height, child_id);
1190}
1191
1193 VARIANT child_id_start, VARIANT *out_var)
1194{
1195 struct Accessible *This = impl_from_Accessible2(iface);
1196 return IAccessible_accNavigate(&This->IAccessible_iface, nav_direction, child_id_start,
1197 out_var);
1198}
1199
1201 VARIANT *out_child_id)
1202{
1203 struct Accessible *This = impl_from_Accessible2(iface);
1204 return IAccessible_accHitTest(&This->IAccessible_iface, left, top, out_child_id);
1205}
1206
1208{
1209 struct Accessible *This = impl_from_Accessible2(iface);
1210 return IAccessible_accDoDefaultAction(&This->IAccessible_iface, child_id);
1211}
1212
1214 BSTR name)
1215{
1216 struct Accessible *This = impl_from_Accessible2(iface);
1217 return IAccessible_put_accName(&This->IAccessible_iface, child_id, name);
1218}
1219
1221 BSTR value)
1222{
1223 struct Accessible *This = impl_from_Accessible2(iface);
1224 return IAccessible_put_accValue(&This->IAccessible_iface, child_id, value);
1225}
1226
1228{
1229 struct Accessible *This = impl_from_Accessible2(iface);
1230 CHECK_ACC_METHOD_EXPECT(This, get_nRelations);
1231 ACC_METHOD_TRACE(This, get_nRelations);
1232 return E_NOTIMPL;
1233}
1234
1236 IAccessibleRelation **out_relation)
1237{
1238 struct Accessible *This = impl_from_Accessible2(iface);
1239 CHECK_ACC_METHOD_EXPECT(This, get_relation);
1240 ACC_METHOD_TRACE(This, get_relation);
1241 return E_NOTIMPL;
1242}
1243
1245 IAccessibleRelation **out_relations, LONG *out_relation_count)
1246{
1247 struct Accessible *This = impl_from_Accessible2(iface);
1248 CHECK_ACC_METHOD_EXPECT(This, get_relations);
1249 ACC_METHOD_TRACE(This, get_relations);
1250 return E_NOTIMPL;
1251}
1252
1254{
1255 struct Accessible *This = impl_from_Accessible2(iface);
1258 return E_NOTIMPL;
1259}
1260
1262{
1263 struct Accessible *This = impl_from_Accessible2(iface);
1264 CHECK_ACC_METHOD_EXPECT(This, scrollTo);
1265 ACC_METHOD_TRACE(This, scrollTo);
1266 return E_NOTIMPL;
1267}
1268
1270 enum IA2CoordinateType coordinate_type, LONG x, LONG y)
1271{
1272 struct Accessible *This = impl_from_Accessible2(iface);
1273 CHECK_ACC_METHOD_EXPECT(This, scrollToPoint);
1274 ACC_METHOD_TRACE(This, scrollToPoint);
1275 return E_NOTIMPL;
1276}
1277
1279 LONG *out_similar_items_in_group, LONG *out_position_in_group)
1280{
1281 struct Accessible *This = impl_from_Accessible2(iface);
1282 CHECK_ACC_METHOD_EXPECT(This, get_groupPosition);
1283 ACC_METHOD_TRACE(This, get_groupPosition);
1284 return E_NOTIMPL;
1285}
1286
1288{
1289 struct Accessible *This = impl_from_Accessible2(iface);
1290 CHECK_ACC_METHOD_EXPECT(This, get_states);
1291 ACC_METHOD_TRACE(This, get_states);
1292 return E_NOTIMPL;
1293}
1294
1296{
1297 struct Accessible *This = impl_from_Accessible2(iface);
1298 CHECK_ACC_METHOD_EXPECT(This, get_extendedRole);
1299 ACC_METHOD_TRACE(This, get_extendedRole);
1300 return E_NOTIMPL;
1301}
1302
1304 BSTR *out_localized_extended_role)
1305{
1306 struct Accessible *This = impl_from_Accessible2(iface);
1307 CHECK_ACC_METHOD_EXPECT(This, get_localizedExtendedRole);
1308 ACC_METHOD_TRACE(This, get_localizedExtendedRole);
1309 return E_NOTIMPL;
1310}
1311
1313{
1314 struct Accessible *This = impl_from_Accessible2(iface);
1315 CHECK_ACC_METHOD_EXPECT(This, get_nExtendedStates);
1316 ACC_METHOD_TRACE(This, get_nExtendedStates);
1317 return E_NOTIMPL;
1318}
1319
1321 BSTR **out_extended_states, LONG *out_extended_states_count)
1322{
1323 struct Accessible *This = impl_from_Accessible2(iface);
1324 CHECK_ACC_METHOD_EXPECT(This, get_extendedStates);
1325 ACC_METHOD_TRACE(This, get_extendedStates);
1326 return E_NOTIMPL;
1327}
1328
1330 BSTR **out_localized_extended_states, LONG *out_localized_extended_states_count)
1331{
1332 struct Accessible *This = impl_from_Accessible2(iface);
1333 CHECK_ACC_METHOD_EXPECT(This, get_localizedExtendedStates);
1334 ACC_METHOD_TRACE(This, get_localizedExtendedStates);
1335 return E_NOTIMPL;
1336}
1337
1339{
1340 struct Accessible *This = impl_from_Accessible2(iface);
1341
1342 CHECK_ACC_METHOD_EXPECT(This, get_uniqueID);
1343 ACC_METHOD_TRACE(This, get_uniqueID);
1344
1345 *out_unique_id = 0;
1346 if (This->unique_id)
1347 {
1348 *out_unique_id = This->unique_id;
1349 return S_OK;
1350 }
1351
1352 return E_NOTIMPL;
1353}
1354
1356{
1357 struct Accessible *This = impl_from_Accessible2(iface);
1358 CHECK_ACC_METHOD_EXPECT(This, get_windowHandle);
1359 ACC_METHOD_TRACE(This, get_windowHandle);
1360 return E_NOTIMPL;
1361}
1362
1364{
1365 struct Accessible *This = impl_from_Accessible2(iface);
1366 CHECK_ACC_METHOD_EXPECT(This, get_indexInParent);
1367 ACC_METHOD_TRACE(This, get_indexInParent);
1368 return E_NOTIMPL;
1369}
1370
1372{
1373 struct Accessible *This = impl_from_Accessible2(iface);
1376 return E_NOTIMPL;
1377}
1378
1380{
1381 struct Accessible *This = impl_from_Accessible2(iface);
1384 return E_NOTIMPL;
1385}
1386
1387static const IAccessible2Vtbl Accessible2Vtbl = {
1434};
1435
1436static inline struct Accessible* impl_from_OleWindow(IOleWindow *iface)
1437{
1438 return CONTAINING_RECORD(iface, struct Accessible, IOleWindow_iface);
1439}
1440
1442{
1443 struct Accessible *This = impl_from_OleWindow(iface);
1444 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1445}
1446
1448{
1449 struct Accessible *This = impl_from_OleWindow(iface);
1450 return IAccessible_AddRef(&This->IAccessible_iface);
1451}
1452
1454{
1455 struct Accessible *This = impl_from_OleWindow(iface);
1456 return IAccessible_Release(&This->IAccessible_iface);
1457}
1458
1460{
1461 struct Accessible *This = impl_from_OleWindow(iface);
1462
1463 *hwnd = This->ow_hwnd;
1464 return *hwnd ? S_OK : E_FAIL;
1465}
1466
1468{
1469 return E_NOTIMPL;
1470}
1471
1472static const IOleWindowVtbl OleWindowVtbl = {
1478};
1479
1481{
1483}
1484
1486{
1487 struct Accessible *This = impl_from_ServiceProvider(iface);
1488 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1489}
1490
1492{
1493 struct Accessible *This = impl_from_ServiceProvider(iface);
1494 return IAccessible_AddRef(&This->IAccessible_iface);
1495}
1496
1498{
1499 struct Accessible *This = impl_from_ServiceProvider(iface);
1500 return IAccessible_Release(&This->IAccessible_iface);
1501}
1502
1504 REFIID riid, void **obj)
1505{
1506 struct Accessible *This = impl_from_ServiceProvider(iface);
1507
1508 if (IsEqualIID(riid, &IID_IAccessible2) && IsEqualIID(service_guid, &IID_IAccessible2) &&
1509 This->enable_ia2)
1510 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1511
1512 return E_NOTIMPL;
1513}
1514
1515static const IServiceProviderVtbl ServiceProviderVtbl = {
1520};
1521
1522static struct Accessible Accessible =
1523{
1524 { &AccessibleVtbl },
1525 { &Accessible2Vtbl },
1526 { &OleWindowVtbl },
1528 1,
1529 "Accessible",
1530 NULL,
1531 0, 0,
1532 0, 0, 0, NULL,
1533 0, 0, 0, 0,
1534 FALSE, 0,
1536};
1537
1539{
1540 { &AccessibleVtbl },
1541 { &Accessible2Vtbl },
1542 { &OleWindowVtbl },
1544 1,
1545 "Accessible2",
1546 NULL,
1547 0, 0,
1548 0, 0, 0, NULL,
1549 0, 0, 0, 0,
1550 FALSE, 0,
1552};
1553
1555{
1556 { &AccessibleVtbl },
1557 { &Accessible2Vtbl },
1558 { &OleWindowVtbl },
1560 1,
1561 "Accessible_child",
1563 0, 0,
1564 0, 0, 0, NULL,
1565 0, 0, 0, 0,
1566 FALSE, 0,
1568};
1569
1571{
1572 { &AccessibleVtbl },
1573 { &Accessible2Vtbl },
1574 { &OleWindowVtbl },
1576 1,
1577 "Accessible_child2",
1579 0, 0,
1580 0, 0, 0, NULL,
1581 0, 0, 0, 0,
1582 FALSE, 0,
1584};
1585
1587{
1590};
1591
1593{
1596};
1597
1599{
1603};
1604
1606{
1608
1613
1614 IRawElementProviderSimple *responder_prov;
1616};
1617
1618static struct Provider
1619{
1620 IRawElementProviderSimple IRawElementProviderSimple_iface;
1621 IRawElementProviderFragment IRawElementProviderFragment_iface;
1622 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface;
1623 IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface;
1624 IRawElementProviderAdviseEvents IRawElementProviderAdviseEvents_iface;
1625 IProxyProviderWinEventHandler IProxyProviderWinEventHandler_iface;
1626 IValueProvider IValueProvider_iface;
1627 ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface;
1629
1630 const char *prov_name;
1631 IRawElementProviderFragment *parent;
1632 IRawElementProviderFragmentRoot *frag_root;
1633 IRawElementProviderFragment *prev_sibling;
1634 IRawElementProviderFragment *next_sibling;
1635 IRawElementProviderFragment *first_child;
1636 IRawElementProviderFragment *last_child;
1650 IRawElementProviderFragment *focus_prov;
1651 IRawElementProviderFragmentRoot **embedded_frag_roots;
1660static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links);
1661static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count);
1662static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val);
1663static void initialize_provider_tree(BOOL initialize_nav_links);
1664static void provider_add_child(struct Provider *prov, struct Provider *child);
1665
1666static const WCHAR *uia_bstr_prop_str = L"uia-string";
1667static const ULONG uia_i4_prop_val = 0xdeadbeef;
1668static const ULONG uia_i4_arr_prop_val[] = { 0xfeedbeef, 0xdeadcafe, 0xfefedede };
1669static const double uia_r8_prop_val = 128.256f;
1670static const double uia_r8_arr_prop_val[] = { 2.4, 8.16, 32.64 };
1671static const IRawElementProviderSimple *uia_unk_arr_prop_val[] = { &Provider_child.IRawElementProviderSimple_iface,
1672 &Provider_child2.IRawElementProviderSimple_iface };
1674{
1675 SAFEARRAY *sa;
1676 LONG idx;
1677
1679 return NULL;
1680
1681 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
1683
1684 return sa;
1685}
1686
1688{
1689 SAFEARRAY *sa;
1690 LONG idx;
1691
1693 return NULL;
1694
1695 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
1697
1698 return sa;
1699}
1700
1702{
1703 SAFEARRAY *sa;
1704 LONG idx;
1705
1707 return NULL;
1708
1709 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
1711
1712 return sa;
1713}
1714
1715enum {
1730};
1731
1732static const char *prov_method_str[] = {
1733 "get_ProviderOptions",
1734 "GetPatternProvider",
1735 "GetPropertyValue",
1736 "get_HostRawElementProvider",
1737 "Navigate",
1738 "GetRuntimeId",
1739 "get_FragmentRoot",
1740 "get_BoundingRectangle",
1741 "GetEmbeddedFragmentRoots",
1742 "GetFocus",
1743 "GetOverrideProviderForHwnd",
1744 "AdviseEventAdded",
1745 "AdviseEventRemoved",
1746 "RespondToWinEvent",
1747};
1748
1749static const char *get_prov_method_str(int method)
1750{
1752 return NULL;
1753 else
1754 return prov_method_str[method];
1755}
1756
1757enum {
1760};
1761
1766};
1767
1770
1771/*
1772 * This sequence of method calls is always used when creating an HUIANODE from
1773 * an IRawElementProviderSimple.
1774 */
1775#define NODE_CREATE_SEQ(prov) \
1776 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1777 /* Win10v1507 and below call this. */ \
1778 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1779 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1780 { prov , PROV_GET_PROPERTY_VALUE }, \
1781 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1782 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1783
1784#define NODE_CREATE_SEQ_OPTIONAL(prov) \
1785 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1786 /* Win10v1507 and below call this. */ \
1787 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1788 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1789 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, \
1790 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1791 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1792
1793/*
1794 * This sequence of method calls is always used when creating an HUIANODE from
1795 * an IRawElementProviderSimple that returns an HWND from get_HostRawElementProvider.
1796 */
1797#define NODE_CREATE_SEQ2(prov) \
1798 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1799 /* Win10v1507 and below call this. */ \
1800 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1801 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1802 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1803 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1804
1805#define NODE_CREATE_SEQ2_OPTIONAL(prov) \
1806 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1807 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1808 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1809 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1810
1811/*
1812 * Node creation sequence with the first get_ProviderOptions call being optional.
1813 * Used for event tests since each Windows version has different amounts of
1814 * calls to get_ProviderOptions before node creation.
1815 */
1816#define NODE_CREATE_SEQ3(prov) \
1817 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1818 /* Win10v1507 and below call this. */ \
1819 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1820 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1821 { prov , PROV_GET_PROPERTY_VALUE }, \
1822 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1823 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1824
1825static void flush_method_sequence(void)
1826{
1827 free(sequence);
1828 sequence = NULL;
1830}
1831
1833static void add_method_call(struct Provider *prov, int method)
1834{
1835 struct prov_method_sequence prov_method = {0};
1836
1838 return;
1839
1841 {
1844 }
1845
1846 prov_method.prov = prov;
1847 prov_method.method = method;
1848 prov_method.flags = 0;
1849 sequence[sequence_cnt++] = prov_method;
1850}
1851
1852#define ok_method_sequence( exp, context ) \
1853 ok_method_sequence_( (exp), (context), __FILE__, __LINE__)
1854static void ok_method_sequence_(const struct prov_method_sequence *expected_list, const char *context,
1855 const char *file, int line)
1856{
1857 const struct prov_method_sequence *expected = expected_list;
1858 const struct prov_method_sequence *actual;
1859 unsigned int count = 0;
1860
1863 actual = sequence;
1864
1865 if (context)
1867
1868 while (expected->prov && actual->prov)
1869 {
1870 if (expected->prov == actual->prov && expected->method == actual->method)
1871 {
1872 if (expected->flags & METHOD_TODO)
1873 todo_wine ok_(file, line)(1, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1874 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1875 expected++;
1876 actual++;
1877 }
1878 else if (expected->flags & METHOD_TODO)
1879 {
1880 todo_wine ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1881 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1882 expected++;
1883 }
1884 else if (expected->flags & METHOD_OPTIONAL)
1885 expected++;
1886 else
1887 {
1888 ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1889 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1890 expected++;
1891 actual++;
1892 }
1893 count++;
1894 }
1895
1896 /* Handle trailing optional/todo_wine methods. */
1897 while (expected->prov && ((expected->flags & METHOD_OPTIONAL) ||
1898 ((expected->flags & METHOD_TODO) && !strcmp(winetest_platform, "wine"))))
1899 {
1900 if (expected->flags & METHOD_TODO)
1901 todo_wine ok_(file, line)(0, "%d: expected %s_%s\n", count, expected->prov->prov_name,
1902 get_prov_method_str(expected->method));
1903 count++;
1904 expected++;
1905 }
1906
1907 if (expected->prov || actual->prov)
1908 {
1909 if (expected->prov)
1910 ok_( file, line)(0, "incomplete sequence: expected %s_%s, got nothing\n", expected->prov->prov_name,
1911 get_prov_method_str(expected->method));
1912 else
1913 ok_( file, line)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual->prov->prov_name,
1914 get_prov_method_str(actual->method));
1915 }
1916
1917 if (context)
1919
1921}
1922
1924{
1925 if (prov->method_call_event_handle && (prov->method_call_event_method_id == method))
1926 SetEvent(prov->method_call_event_handle);
1927}
1928
1929/*
1930 * Parsing the string returned by UIA_ProviderDescriptionPropertyId is
1931 * the only way to know what an HUIANODE represents internally. It
1932 * returns a formatted string which always starts with:
1933 * "[pid:<process-id>,providerId:0x<hwnd-ptr> "
1934 * On Windows versions 10v1507 and below, "providerId:" is "hwnd:"
1935 *
1936 * This is followed by strings for each provider it represents. These are
1937 * formatted as:
1938 * "<prov-type>:<prov-desc> (<origin>)"
1939 * and are terminated with ";", the final provider has no ";" terminator,
1940 * instead it has "]".
1941 *
1942 * If the given provider is the one used for navigation towards a parent, it has
1943 * "(parent link)" as a suffix on "<prov-type>".
1944 *
1945 * <prov-type> is one of "Annotation", "Main", "Override", "Hwnd", or
1946 * "Nonclient".
1947 *
1948 * <prov-desc> is the string returned from calling GetPropertyValue on the
1949 * IRawElementProviderSimple being represented with a property ID of
1950 * UIA_ProviderDescriptionPropertyId.
1951 *
1952 * <origin> is the name of the module that the
1953 * IRawElementProviderSimple comes from. For unmanaged code, it's:
1954 * "unmanaged:<executable>"
1955 * and for managed code, it's:
1956 * "managed:<assembly-qualified-name>"
1957 *
1958 * An example:
1959 * [pid:1500,providerId:0x2F054C Main:Provider (unmanaged:uiautomation_test.exe); Hwnd(parent link):HWND Proxy (unmanaged:uiautomationcore.dll)]
1960 */
1961static BOOL get_provider_desc(BSTR prov_desc, const WCHAR *prov_type, WCHAR *out_name)
1962{
1963 const WCHAR *str, *str2;
1964
1965 str = wcsstr(prov_desc, prov_type);
1966 if (!str)
1967 return FALSE;
1968
1969 if (!out_name)
1970 return TRUE;
1971
1972 str += wcslen(prov_type);
1973 str2 = wcschr(str, L'(');
1974 lstrcpynW(out_name, str, ((str2 - str)));
1975
1976 return TRUE;
1977}
1978
1979#define check_node_provider_desc_todo( prov_desc, prov_type, prov_name, parent_link ) \
1980 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), TRUE, __FILE__, __LINE__)
1981#define check_node_provider_desc( prov_desc, prov_type, prov_name, parent_link ) \
1982 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), FALSE, __FILE__, __LINE__)
1983static void check_node_provider_desc_(BSTR prov_desc, const WCHAR *prov_type, const WCHAR *prov_name,
1984 BOOL parent_link, BOOL todo, const char *file, int line)
1985{
1986 WCHAR buf[2048];
1987
1988 if (parent_link)
1989 wsprintfW(buf, L"%s(parent link):", prov_type);
1990 else
1991 wsprintfW(buf, L"%s:", prov_type);
1992
1993 if (!get_provider_desc(prov_desc, buf, buf))
1994 {
1995 if (parent_link)
1996 wsprintfW(buf, L"%s:", prov_type);
1997 else
1998 wsprintfW(buf, L"%s(parent link):", prov_type);
1999
2000 if (!get_provider_desc(prov_desc, buf, buf))
2001 todo_wine_if(todo) ok_(file, line)(0, "failed to get provider string for %s\n", debugstr_w(prov_type));
2002 else
2003 {
2004 if (parent_link)
2005 todo_wine_if(todo) ok_(file, line)(0, "expected parent link provider %s\n", debugstr_w(prov_type));
2006 else
2007 todo_wine_if(todo) ok_(file, line)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type));
2008 }
2009
2010 return;
2011 }
2012
2013 if (prov_name)
2014 ok_(file, line)(!wcscmp(prov_name, buf), "unexpected provider name %s\n", debugstr_w(buf));
2015}
2016
2017#define check_node_provider_desc_prefix( prov_desc, pid, prov_id ) \
2018 check_node_provider_desc_prefix_( (prov_desc), (pid), (prov_id), __FILE__, __LINE__)
2019static void check_node_provider_desc_prefix_(BSTR prov_desc, DWORD pid, HWND prov_id, const char *file, int line)
2020{
2021 const WCHAR *str, *str2;
2022 WCHAR buf[128];
2023 DWORD prov_pid;
2024 HWND prov_hwnd;
2025 WCHAR *end;
2026
2027 str = wcsstr(prov_desc, L"pid:");
2028 str += wcslen(L"pid:");
2029 str2 = wcschr(str, L',');
2030 lstrcpynW(buf, str, (str2 - str) + 1);
2031 prov_pid = wcstoul(buf, &end, 10);
2032 ok_(file, line)(prov_pid == pid, "Unexpected pid %lu\n", prov_pid);
2033
2034 str = wcsstr(prov_desc, L"providerId:");
2035 if (str)
2036 str += wcslen(L"providerId:");
2037 else
2038 {
2039 str = wcsstr(prov_desc, L"hwnd:");
2040 str += wcslen(L"hwnd:");
2041 }
2042 str2 = wcschr(str, L' ');
2043 lstrcpynW(buf, str, (str2 - str) + 1);
2044 prov_hwnd = ULongToHandle(wcstoul(buf, &end, 16));
2045 ok_(file, line)(prov_hwnd == prov_id, "Unexpected hwnd %p\n", prov_hwnd);
2046}
2047
2048/*
2049 * For node providers that come from an HWND belonging to another process
2050 * or another thread, the provider is considered 'nested', a node in a node.
2051 */
2052static BOOL get_nested_provider_desc(BSTR prov_desc, const WCHAR *prov_type, BOOL parent_link, WCHAR *out_desc)
2053{
2054 const WCHAR *str, *str2;
2055 WCHAR buf[1024];
2056
2057 if (!parent_link)
2058 wsprintfW(buf, L"%s:Nested ", prov_type);
2059 else
2060 wsprintfW(buf, L"%s(parent link):Nested ", prov_type);
2061 str = wcsstr(prov_desc, buf);
2062 /* Check with and without parent-link. */
2063 if (!str)
2064 return FALSE;
2065
2066 if (!out_desc)
2067 return TRUE;
2068
2069 str += wcslen(buf);
2070 str2 = wcschr(str, L']');
2071 /* We want to include the ']' character, so + 2. */
2072 lstrcpynW(out_desc, str, ((str2 - str) + 2));
2073
2074 return TRUE;
2075}
2076
2077#define check_runtime_id( exp_runtime_id, exp_size, runtime_id ) \
2078 check_runtime_id_( (exp_runtime_id), (exp_size), (runtime_id), __FILE__, __LINE__)
2079static void check_runtime_id_(int *exp_runtime_id, int exp_size, SAFEARRAY *runtime_id, const char *file, int line)
2080{
2081 LONG i, idx, lbound, ubound, elems;
2082 HRESULT hr;
2083 UINT dims;
2084 int val;
2085
2086 dims = SafeArrayGetDim(runtime_id);
2087 ok_(file, line)(dims == 1, "Unexpected array dims %d\n", dims);
2088
2089 hr = SafeArrayGetLBound(runtime_id, 1, &lbound);
2090 ok_(file, line)(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
2091
2092 hr = SafeArrayGetUBound(runtime_id, 1, &ubound);
2093 ok_(file, line)(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
2094
2095 elems = (ubound - lbound) + 1;
2096 ok_(file, line)(exp_size == elems, "Unexpected runtime_id array size %#lx\n", elems);
2097
2098 for (i = 0; i < elems; i++)
2099 {
2100 idx = lbound + i;
2101 hr = SafeArrayGetElement(runtime_id, &idx, &val);
2102 ok_(file, line)(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
2103 ok_(file, line)(val == exp_runtime_id[i], "Unexpected runtime_id[%ld] %#x\n", i, val);
2104 }
2105}
2106
2107static inline struct Provider *impl_from_ProviderSimple(IRawElementProviderSimple *iface)
2108{
2110}
2111
2112HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
2113{
2114 struct Provider *This = impl_from_ProviderSimple(iface);
2115
2116 *ppv = NULL;
2117 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
2118 *ppv = iface;
2119 else if (IsEqualIID(riid, &IID_IRawElementProviderFragment))
2120 *ppv = &This->IRawElementProviderFragment_iface;
2121 else if (IsEqualIID(riid, &IID_IRawElementProviderFragmentRoot))
2122 *ppv = &This->IRawElementProviderFragmentRoot_iface;
2123 else if (IsEqualIID(riid, &IID_IRawElementProviderHwndOverride))
2124 *ppv = &This->IRawElementProviderHwndOverride_iface;
2125 else if (IsEqualIID(riid, &IID_IRawElementProviderAdviseEvents))
2126 *ppv = &This->IRawElementProviderAdviseEvents_iface;
2127 else if (IsEqualIID(riid, &IID_IValueProvider))
2128 *ppv = &This->IValueProvider_iface;
2129 else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider))
2130 *ppv = &This->ILegacyIAccessibleProvider_iface;
2131 else if (This->win_event_handler_data.is_supported && IsEqualIID(riid, &IID_IProxyProviderWinEventHandler))
2132 *ppv = &This->IProxyProviderWinEventHandler_iface;
2133 else
2134 return E_NOINTERFACE;
2135
2136 IRawElementProviderSimple_AddRef(iface);
2137 return S_OK;
2138}
2139
2140ULONG WINAPI ProviderSimple_AddRef(IRawElementProviderSimple *iface)
2141{
2142 struct Provider *This = impl_from_ProviderSimple(iface);
2143 return InterlockedIncrement(&This->ref);
2144}
2145
2146ULONG WINAPI ProviderSimple_Release(IRawElementProviderSimple *iface)
2147{
2148 struct Provider *This = impl_from_ProviderSimple(iface);
2149 return InterlockedDecrement(&This->ref);
2150}
2151
2152HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *iface,
2153 enum ProviderOptions *ret_val)
2154{
2155 struct Provider *This = impl_from_ProviderSimple(iface);
2156
2158 if (This->expected_tid)
2159 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2160 This->last_call_tid = GetCurrentThreadId();
2162 PROV_METHOD_TRACE(This, get_ProviderOptions);
2163
2164 *ret_val = 0;
2165 if (This->prov_opts)
2166 {
2167 *ret_val = This->prov_opts;
2168 return S_OK;
2169 }
2170
2171 return E_NOTIMPL;
2172}
2173
2174HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface,
2175 PATTERNID pattern_id, IUnknown **ret_val)
2176{
2177 struct Provider *This = impl_from_ProviderSimple(iface);
2178
2180 if (This->expected_tid)
2181 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2182 This->last_call_tid = GetCurrentThreadId();
2183 PROV_METHOD_TRACE2(This, GetPatternProvider, pattern_id, uia_pattern_id_strs);
2184
2185 *ret_val = NULL;
2186 switch (pattern_id)
2187 {
2188 case UIA_ValuePatternId:
2189 if (This->value_pattern_data.is_supported)
2190 *ret_val = (IUnknown *)iface;
2191 break;
2192
2193 case UIA_LegacyIAccessiblePatternId:
2194 if (This->legacy_acc_pattern_data.is_supported)
2195 *ret_val = (IUnknown *)iface;
2196 break;
2197
2198 default:
2199 break;
2200 }
2201
2202 if (*ret_val)
2203 IUnknown_AddRef(*ret_val);
2204
2206 return S_OK;
2207}
2208
2209HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface,
2210 PROPERTYID prop_id, VARIANT *ret_val)
2211{
2212 struct Provider *This = impl_from_ProviderSimple(iface);
2213
2215 if (This->expected_tid)
2216 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2217 This->last_call_tid = GetCurrentThreadId();
2219 PROV_METHOD_TRACE2(This, GetPropertyValue, prop_id, uia_prop_id_strs);
2220
2221 if (This->prop_override && This->prop_override_count)
2222 {
2223 int i;
2224
2225 for (i = 0; i < This->prop_override_count; i++)
2226 {
2227 if (This->prop_override[i].prop_id == prop_id)
2228 {
2229 *ret_val = This->prop_override[i].val;
2230 if (V_VT(ret_val) == VT_UNKNOWN)
2231 IUnknown_AddRef(V_UNKNOWN(ret_val));
2232
2233 return S_OK;
2234 }
2235 }
2236 }
2237
2238 VariantInit(ret_val);
2239 switch (prop_id)
2240 {
2241 case UIA_NativeWindowHandlePropertyId:
2242 if (This->ret_invalid_prop_type)
2243 {
2244 V_VT(ret_val) = VT_R8;
2245 V_R8(ret_val) = uia_r8_prop_val;
2246 }
2247 else if (!This->ignore_hwnd_prop)
2248 {
2249 V_VT(ret_val) = VT_I4;
2250 V_I4(ret_val) = HandleToULong(This->hwnd);
2251 }
2252 break;
2253
2254 case UIA_ProcessIdPropertyId:
2255 case UIA_ControlTypePropertyId:
2256 case UIA_CulturePropertyId:
2257 case UIA_OrientationPropertyId:
2258 case UIA_LiveSettingPropertyId:
2259 case UIA_PositionInSetPropertyId:
2260 case UIA_SizeOfSetPropertyId:
2261 case UIA_LevelPropertyId:
2262 case UIA_LandmarkTypePropertyId:
2263 case UIA_FillColorPropertyId:
2264 case UIA_FillTypePropertyId:
2265 case UIA_VisualEffectsPropertyId:
2266 case UIA_HeadingLevelPropertyId:
2267 if (This->ret_invalid_prop_type)
2268 {
2269 V_VT(ret_val) = VT_R8;
2270 V_R8(ret_val) = uia_r8_prop_val;
2271 }
2272 else
2273 {
2274 V_VT(ret_val) = VT_I4;
2275 V_I4(ret_val) = uia_i4_prop_val;
2276 }
2277 break;
2278
2279 case UIA_RotationPropertyId:
2280 if (This->ret_invalid_prop_type)
2281 {
2282 V_VT(ret_val) = VT_I4;
2283 V_I4(ret_val) = uia_i4_prop_val;
2284 }
2285 else
2286 {
2287 V_VT(ret_val) = VT_R8;
2288 V_R8(ret_val) = uia_r8_prop_val;
2289 }
2290 break;
2291
2292 case UIA_LocalizedControlTypePropertyId:
2293 case UIA_NamePropertyId:
2294 case UIA_AcceleratorKeyPropertyId:
2295 case UIA_AccessKeyPropertyId:
2296 case UIA_AutomationIdPropertyId:
2297 case UIA_ClassNamePropertyId:
2298 case UIA_HelpTextPropertyId:
2299 case UIA_ItemTypePropertyId:
2300 case UIA_FrameworkIdPropertyId:
2301 case UIA_ItemStatusPropertyId:
2302 case UIA_AriaRolePropertyId:
2303 case UIA_AriaPropertiesPropertyId:
2304 case UIA_LocalizedLandmarkTypePropertyId:
2305 case UIA_FullDescriptionPropertyId:
2306 if (This->ret_invalid_prop_type)
2307 {
2308 V_VT(ret_val) = VT_I4;
2309 V_I4(ret_val) = uia_i4_prop_val;
2310 }
2311 else
2312 {
2313 V_VT(ret_val) = VT_BSTR;
2315 }
2316 break;
2317
2318 case UIA_HasKeyboardFocusPropertyId:
2319 case UIA_IsKeyboardFocusablePropertyId:
2320 case UIA_IsEnabledPropertyId:
2321 case UIA_IsControlElementPropertyId:
2322 case UIA_IsContentElementPropertyId:
2323 case UIA_IsPasswordPropertyId:
2324 case UIA_IsOffscreenPropertyId:
2325 case UIA_IsRequiredForFormPropertyId:
2326 case UIA_IsDataValidForFormPropertyId:
2327 case UIA_OptimizeForVisualContentPropertyId:
2328 case UIA_IsPeripheralPropertyId:
2329 case UIA_IsDialogPropertyId:
2330 if (This->ret_invalid_prop_type)
2331 {
2332 V_VT(ret_val) = VT_R8;
2333 V_R8(ret_val) = uia_r8_prop_val;
2334 }
2335 else
2336 {
2337 V_VT(ret_val) = VT_BOOL;
2338 V_BOOL(ret_val) = VARIANT_TRUE;
2339 }
2340 break;
2341
2342 case UIA_AnnotationTypesPropertyId:
2343 case UIA_OutlineColorPropertyId:
2344 if (This->ret_invalid_prop_type)
2345 {
2346 V_VT(ret_val) = VT_ARRAY | VT_R8;
2347 V_ARRAY(ret_val) = create_r8_safearray();
2348 }
2349 else
2350 {
2351 V_VT(ret_val) = VT_ARRAY | VT_I4;
2352 V_ARRAY(ret_val) = create_i4_safearray();
2353 }
2354 break;
2355
2356 case UIA_OutlineThicknessPropertyId:
2357 case UIA_SizePropertyId:
2358 if (This->ret_invalid_prop_type)
2359 {
2360 V_VT(ret_val) = VT_ARRAY | VT_I4;
2361 V_ARRAY(ret_val) = create_i4_safearray();
2362 }
2363 else
2364 {
2365 V_VT(ret_val) = VT_ARRAY | VT_R8;
2366 V_ARRAY(ret_val) = create_r8_safearray();
2367 }
2368 break;
2369
2370 case UIA_LabeledByPropertyId:
2371 if (This->ret_invalid_prop_type)
2372 {
2373 V_VT(ret_val) = VT_I4;
2374 V_I4(ret_val) = uia_i4_prop_val;
2375 }
2376 else
2377 {
2378 V_VT(ret_val) = VT_UNKNOWN;
2379 V_UNKNOWN(ret_val) = (IUnknown *)&Provider_child.IRawElementProviderSimple_iface;
2380 IUnknown_AddRef(V_UNKNOWN(ret_val));
2381 }
2382 break;
2383
2384 case UIA_AnnotationObjectsPropertyId:
2385 case UIA_DescribedByPropertyId:
2386 case UIA_FlowsFromPropertyId:
2387 case UIA_FlowsToPropertyId:
2388 case UIA_ControllerForPropertyId:
2389 if (This->ret_invalid_prop_type)
2390 {
2391 V_VT(ret_val) = VT_ARRAY | VT_I4;
2392 V_ARRAY(ret_val) = create_i4_safearray();
2393 }
2394 else
2395 {
2396 V_VT(ret_val) = VT_UNKNOWN | VT_ARRAY;
2397 V_ARRAY(ret_val) = create_unk_safearray();
2398 }
2399 break;
2400
2401 case UIA_ProviderDescriptionPropertyId:
2402 {
2403#ifdef __REACTOS__
2404 WCHAR buf[1024];
2405#else
2406 WCHAR buf[1024] = {};
2407 memset(&buf, 0, sizeof(buf));
2408#endif
2409
2410 mbstowcs(buf, This->prov_name, strlen(This->prov_name));
2411 V_VT(ret_val) = VT_BSTR;
2412 V_BSTR(ret_val) = SysAllocString(buf);
2413 break;
2414 }
2415
2416 default:
2417 break;
2418 }
2419
2420 return S_OK;
2421}
2422
2424 IRawElementProviderSimple **ret_val)
2425{
2426 struct Provider *This = impl_from_ProviderSimple(iface);
2427
2429 if (This->expected_tid)
2430 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2431 This->last_call_tid = GetCurrentThreadId();
2433 PROV_METHOD_TRACE(This, get_HostRawElementProvider);
2434
2435 *ret_val = NULL;
2436 if (This->hwnd)
2437 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
2438
2439 return S_OK;
2440}
2441
2442IRawElementProviderSimpleVtbl ProviderSimpleVtbl = {
2450};
2451
2452static inline struct Provider *impl_from_ProviderFragment(IRawElementProviderFragment *iface)
2453{
2455}
2456
2457static HRESULT WINAPI ProviderFragment_QueryInterface(IRawElementProviderFragment *iface, REFIID riid,
2458 void **ppv)
2459{
2461 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2462}
2463
2464static ULONG WINAPI ProviderFragment_AddRef(IRawElementProviderFragment *iface)
2465{
2467 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2468}
2469
2470static ULONG WINAPI ProviderFragment_Release(IRawElementProviderFragment *iface)
2471{
2473 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2474}
2475
2476static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *iface,
2477 enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
2478{
2479 struct Provider *This = impl_from_ProviderFragment(iface);
2480
2482 if (This->expected_tid)
2483 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2484 This->last_call_tid = GetCurrentThreadId();
2486
2487 *ret_val = NULL;
2488 switch (direction)
2489 {
2491 *ret_val = This->parent;
2492 break;
2493
2495 *ret_val = This->next_sibling;
2496 break;
2497
2499 *ret_val = This->prev_sibling;
2500 break;
2501
2503 *ret_val = This->first_child;
2504 break;
2505
2507 *ret_val = This->last_child;
2508 break;
2509
2510 default:
2511 trace("Invalid navigate direction %d\n", direction);
2512 break;
2513 }
2514
2515 if (*ret_val)
2516 IRawElementProviderFragment_AddRef(*ret_val);
2517
2519 return S_OK;
2520}
2521
2522static HRESULT WINAPI ProviderFragment_GetRuntimeId(IRawElementProviderFragment *iface,
2523 SAFEARRAY **ret_val)
2524{
2525 struct Provider *This = impl_from_ProviderFragment(iface);
2526
2528 if (This->expected_tid)
2529 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2530 This->last_call_tid = GetCurrentThreadId();
2532 PROV_METHOD_TRACE(This, GetRuntimeId);
2533
2534 *ret_val = NULL;
2535 if (This->runtime_id[0] || This->runtime_id[1])
2536 {
2537 SAFEARRAY *sa;
2538 LONG idx;
2539
2540 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(This->runtime_id))))
2541 return E_FAIL;
2542
2543 for (idx = 0; idx < ARRAY_SIZE(This->runtime_id); idx++)
2544 SafeArrayPutElement(sa, &idx, (void *)&This->runtime_id[idx]);
2545
2546 *ret_val = sa;
2547 }
2548
2549 return S_OK;
2550}
2551
2552static HRESULT WINAPI ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment *iface,
2553 struct UiaRect *ret_val)
2554{
2555 struct Provider *This = impl_from_ProviderFragment(iface);
2556
2558 if (This->expected_tid)
2559 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2560 This->last_call_tid = GetCurrentThreadId();
2562 PROV_METHOD_TRACE(This, get_BoundingRectangle);
2563
2564 *ret_val = This->bounds_rect;
2565 return S_OK;
2566}
2567
2568static HRESULT WINAPI ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface,
2569 SAFEARRAY **ret_val)
2570{
2571 struct Provider *This = impl_from_ProviderFragment(iface);
2572
2574 if (This->expected_tid)
2575 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2576 This->last_call_tid = GetCurrentThreadId();
2578 PROV_METHOD_TRACE(This, GetEmbeddedFragmentRoots);
2579
2580 *ret_val = NULL;
2581 if (This->embedded_frag_roots && This->embedded_frag_roots_count)
2582 {
2583 SAFEARRAY *sa;
2584 LONG idx;
2585
2586 if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, This->embedded_frag_roots_count)))
2587 return E_FAIL;
2588
2589 for (idx = 0; idx < This->embedded_frag_roots_count; idx++)
2590 SafeArrayPutElement(sa, &idx, (IUnknown *)This->embedded_frag_roots[idx]);
2591
2592 *ret_val = sa;
2593 }
2594
2595 return S_OK;
2596}
2597
2598static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *iface)
2599{
2600 ok(0, "unexpected call\n");
2601 return E_NOTIMPL;
2602}
2603
2604static HRESULT WINAPI ProviderFragment_get_FragmentRoot(IRawElementProviderFragment *iface,
2605 IRawElementProviderFragmentRoot **ret_val)
2606{
2607 struct Provider *This = impl_from_ProviderFragment(iface);
2608
2610 if (This->expected_tid)
2611 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2612 This->last_call_tid = GetCurrentThreadId();
2613 PROV_METHOD_TRACE(This, get_FragmentRoot);
2614
2615 *ret_val = NULL;
2616 if (This->frag_root)
2617 {
2618 *ret_val = This->frag_root;
2619 IRawElementProviderFragmentRoot_AddRef(This->frag_root);
2620 }
2621
2623 return S_OK;
2624}
2625
2626static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl = {
2636};
2637
2638static inline struct Provider *impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot *iface)
2639{
2641}
2642
2643static HRESULT WINAPI ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot *iface, REFIID riid,
2644 void **ppv)
2645{
2647 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2648}
2649
2650static ULONG WINAPI ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot *iface)
2651{
2653 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2654}
2655
2656static ULONG WINAPI ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot *iface)
2657{
2659 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2660}
2661
2662static HRESULT WINAPI ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot *iface,
2663 double x, double y, IRawElementProviderFragment **ret_val)
2664{
2665 ok(0, "unexpected call\n");
2666 return E_NOTIMPL;
2667}
2668
2669static HRESULT WINAPI ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot *iface,
2670 IRawElementProviderFragment **ret_val)
2671{
2673
2676 ok(Provider->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2679
2680 *ret_val = NULL;
2681 if (Provider->focus_prov)
2682 {
2683 *ret_val = Provider->focus_prov;
2684 IRawElementProviderFragment_AddRef(*ret_val);
2685 }
2686
2688 return S_OK;
2689}
2690
2691static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl = {
2697};
2698
2699static inline struct Provider *impl_from_ProviderHwndOverride(IRawElementProviderHwndOverride *iface)
2700{
2702}
2703
2704static HRESULT WINAPI ProviderHwndOverride_QueryInterface(IRawElementProviderHwndOverride *iface, REFIID riid,
2705 void **ppv)
2706{
2708 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2709}
2710
2711static ULONG WINAPI ProviderHwndOverride_AddRef(IRawElementProviderHwndOverride *iface)
2712{
2714 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2715}
2716
2717static ULONG WINAPI ProviderHwndOverride_Release(IRawElementProviderHwndOverride *iface)
2718{
2720 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2721}
2722
2723static HRESULT WINAPI ProviderHwndOverride_GetOverrideProviderForHwnd(IRawElementProviderHwndOverride *iface,
2724 HWND hwnd, IRawElementProviderSimple **ret_val)
2725{
2727
2730 PROV_METHOD_TRACE(This, GetOverrideProviderForHwnd);
2731
2732 *ret_val = NULL;
2733 if (This->override_hwnd == hwnd)
2734 {
2735 return IRawElementProviderSimple_QueryInterface(&Provider_override.IRawElementProviderSimple_iface,
2736 &IID_IRawElementProviderSimple, (void **)ret_val);
2737 }
2738
2739 return S_OK;
2740}
2741
2742static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl = {
2747};
2748
2749static inline struct Provider *impl_from_ProviderAdviseEvents(IRawElementProviderAdviseEvents *iface)
2750{
2752}
2753
2754static HRESULT WINAPI ProviderAdviseEvents_QueryInterface(IRawElementProviderAdviseEvents *iface, REFIID riid,
2755 void **ppv)
2756{
2758 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2759}
2760
2761static ULONG WINAPI ProviderAdviseEvents_AddRef(IRawElementProviderAdviseEvents *iface)
2762{
2764 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2765}
2766
2767static ULONG WINAPI ProviderAdviseEvents_Release(IRawElementProviderAdviseEvents *iface)
2768{
2770 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2771}
2772
2773static HRESULT WINAPI ProviderAdviseEvents_AdviseEventAdded(IRawElementProviderAdviseEvents *iface,
2774 EVENTID event_id, SAFEARRAY *prop_ids)
2775{
2777
2779 if (This->expected_tid)
2780 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2781 This->last_call_tid = GetCurrentThreadId();
2782 This->advise_events_added_event_id = event_id;
2783 PROV_METHOD_TRACE2(This, AdviseEventAdded, event_id, uia_event_id_strs);
2784
2786 return S_OK;
2787}
2788
2789static HRESULT WINAPI ProviderAdviseEvents_AdviseEventRemoved(IRawElementProviderAdviseEvents *iface,
2790 EVENTID event_id, SAFEARRAY *prop_ids)
2791{
2793
2795 if (This->expected_tid)
2796 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2797 This->last_call_tid = GetCurrentThreadId();
2798 This->advise_events_removed_event_id = event_id;
2799 PROV_METHOD_TRACE2(This, AdviseEventRemoved, event_id, uia_event_id_strs);
2800
2802 return S_OK;
2803}
2804
2805static const IRawElementProviderAdviseEventsVtbl ProviderAdviseEventsVtbl = {
2811};
2812
2813static inline struct Provider *impl_from_ProviderWinEventHandler(IProxyProviderWinEventHandler *iface)
2814{
2816}
2817
2818static HRESULT WINAPI ProviderWinEventHandler_QueryInterface(IProxyProviderWinEventHandler *iface, REFIID riid,
2819 void **ppv)
2820{
2822 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2823}
2824
2825static ULONG WINAPI ProviderWinEventHandler_AddRef(IProxyProviderWinEventHandler *iface)
2826{
2828 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2829}
2830
2831static ULONG WINAPI ProviderWinEventHandler_Release(IProxyProviderWinEventHandler *iface)
2832{
2834 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2835}
2836
2837static HRESULT WINAPI ProviderWinEventHandler_RespondToWinEvent(IProxyProviderWinEventHandler *iface,
2838 DWORD event_id, HWND hwnd, LONG obj_id, LONG child_id, IProxyProviderWinEventSink *event_sink)
2839{
2842 HRESULT hr;
2843
2844 PROV_METHOD_TRACE(This, RespondToWinEvent);
2845 data = &This->win_event_handler_data;
2846 if ((data->exp_win_event_id != event_id) || (data->exp_win_event_hwnd != hwnd) || (data->exp_win_event_obj_id != obj_id) ||
2847 (data->exp_win_event_child_id != child_id))
2848 return S_OK;
2849
2851 if (This->expected_tid)
2852 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2853 This->last_call_tid = GetCurrentThreadId();
2854
2855 if (data->responder_prov)
2856 {
2857 /*
2858 * The IProxyProviderWinEventSink interface uses the free threaded
2859 * marshaler, so no proxy will be created in-process.
2860 */
2861 check_interface_marshal_proxy_creation((IUnknown *)event_sink, &IID_IProxyProviderWinEventSink, FALSE);
2862 hr = IProxyProviderWinEventSink_AddAutomationEvent(event_sink, data->responder_prov, data->responder_event);
2863 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2864 }
2865
2867 return S_OK;
2868}
2869
2870static const IProxyProviderWinEventHandlerVtbl ProviderWinEventHandlerVtbl = {
2875};
2876
2877static inline struct Provider *impl_from_ProviderValuePattern(IValueProvider *iface)
2878{
2879 return CONTAINING_RECORD(iface, struct Provider, IValueProvider_iface);
2880}
2881
2883 void **ppv)
2884{
2886 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2887}
2888
2889static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface)
2890{
2892 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2893}
2894
2895static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface)
2896{
2898 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2899}
2900
2902{
2903 ok(0, "unexpected call\n");
2904 return E_NOTIMPL;
2905}
2906
2907static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
2908{
2909 ok(0, "unexpected call\n");
2910 return E_NOTIMPL;
2911}
2912
2913static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val)
2914{
2916
2917 *ret_val = Provider->value_pattern_data.is_read_only;
2918
2919 return S_OK;
2920}
2921
2922static const IValueProviderVtbl ProviderValuePatternVtbl = {
2929};
2930
2931static inline struct Provider *impl_from_ProviderLegacyIAccessiblePattern(ILegacyIAccessibleProvider *iface)
2932{
2934}
2935
2937 void **ppv)
2938{
2940 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2941}
2942
2943static ULONG WINAPI ProviderLegacyIAccessiblePattern_AddRef(ILegacyIAccessibleProvider *iface)
2944{
2946 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2947}
2948
2949static ULONG WINAPI ProviderLegacyIAccessiblePattern_Release(ILegacyIAccessibleProvider *iface)
2950{
2952 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2953}
2954
2955static HRESULT WINAPI ProviderLegacyIAccessiblePattern_Select(ILegacyIAccessibleProvider *iface, LONG select_flags)
2956{
2957 ok(0, "unexpected call\n");
2958 return E_NOTIMPL;
2959}
2960
2961static HRESULT WINAPI ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider *iface)
2962{
2963 ok(0, "unexpected call\n");
2964 return E_NOTIMPL;
2965}
2966
2967static HRESULT WINAPI ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val)
2968{
2969 ok(0, "unexpected call\n");
2970 return E_NOTIMPL;
2971}
2972
2973static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider *iface,
2974 IAccessible **out_acc)
2975{
2976 ok(0, "unexpected call\n");
2977 return E_NOTIMPL;
2978}
2979
2980static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_ChildId(ILegacyIAccessibleProvider *iface, int *out_cid)
2981{
2983
2984 *out_cid = Provider->legacy_acc_pattern_data.child_id;
2985 return S_OK;
2986}
2987
2988static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name)
2989{
2990 ok(0, "unexpected call\n");
2991 return E_NOTIMPL;
2992}
2993
2994static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value)
2995{
2996 ok(0, "unexpected call\n");
2997 return E_NOTIMPL;
2998}
2999
3000static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider *iface,
3001 BSTR *out_description)
3002{
3003 ok(0, "unexpected call\n");
3004 return E_NOTIMPL;
3005}
3006
3007static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role)
3008{
3010
3011 *out_role = Provider->legacy_acc_pattern_data.role;
3012 return S_OK;
3013}
3014
3015static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
3016{
3017 ok(0, "unexpected call\n");
3018 return E_NOTIMPL;
3019}
3020
3021static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help)
3022{
3023 ok(0, "unexpected call\n");
3024 return E_NOTIMPL;
3025}
3026
3028 BSTR *out_kbd_shortcut)
3029{
3030 ok(0, "unexpected call\n");
3031 return E_NOTIMPL;
3032}
3033
3034static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider *iface,
3035 SAFEARRAY **out_selected)
3036{
3037 ok(0, "unexpected call\n");
3038 return E_NOTIMPL;
3039}
3040
3042 BSTR *out_default_action)
3043{
3044 ok(0, "unexpected call\n");
3045 return E_NOTIMPL;
3046}
3047
3048static const ILegacyIAccessibleProviderVtbl ProviderLegacyIAccessiblePatternVtbl = {
3066};
3067
3068static struct Provider Provider =
3069{
3070 { &ProviderSimpleVtbl },
3078 1,
3079 "Provider",
3080 NULL, NULL,
3081 NULL, NULL,
3082 &Provider_child.IRawElementProviderFragment_iface, &Provider_child2.IRawElementProviderFragment_iface,
3083 0, 0, 0,
3084};
3085
3086static struct Provider Provider2 =
3087{
3088 { &ProviderSimpleVtbl },
3096 1,
3097 "Provider2",
3098 NULL, NULL,
3099 NULL, NULL,
3100 NULL, NULL,
3101 0, 0, 0,
3102};
3103
3105{
3106 { &ProviderSimpleVtbl },
3114 1,
3115 "Provider_child",
3117 NULL, &Provider_child2.IRawElementProviderFragment_iface,
3118 NULL, NULL,
3120};
3121
3123{
3124 { &ProviderSimpleVtbl },
3132 1,
3133 "Provider_child2",
3135 &Provider_child.IRawElementProviderFragment_iface, NULL,
3136 NULL, NULL,
3138};
3139
3141{
3142 { &ProviderSimpleVtbl },
3150 1,
3151 "Provider_hwnd",
3152 NULL, NULL,
3153 NULL, NULL,
3154 NULL, NULL,
3156};
3157
3158static struct Provider Provider_nc =
3159{
3160 { &ProviderSimpleVtbl },
3168 1,
3169 "Provider_nc",
3170 NULL, NULL,
3171 NULL, NULL,
3172 NULL, NULL,
3174 0, 0,
3175};
3176
3178{
3179 { &ProviderSimpleVtbl },
3187 1,
3188 "Provider_proxy",
3189 NULL, NULL,
3190 NULL, NULL,
3191 NULL, NULL,
3193 0, 0,
3194};
3195
3197{
3198 { &ProviderSimpleVtbl },
3206 1,
3207 "Provider_proxy2",
3208 NULL, NULL,
3209 NULL, NULL,
3210 NULL, NULL,
3212 0, 0,
3213};
3214
3215static struct Provider Provider_override =
3216{
3217 { &ProviderSimpleVtbl },
3225 1,
3226 "Provider_override",
3227 NULL, NULL,
3228 NULL, NULL,
3229 NULL, NULL,
3231 0, 0,
3232};
3233
3234#define DEFINE_PROVIDER(name) \
3235 static struct Provider Provider_ ## name = \
3236 { \
3237 { &ProviderSimpleVtbl }, \
3238 { &ProviderFragmentVtbl }, \
3239 { &ProviderFragmentRootVtbl }, \
3240 { &ProviderHwndOverrideVtbl }, \
3241 { &ProviderAdviseEventsVtbl }, \
3242 { &ProviderWinEventHandlerVtbl }, \
3243 { &ProviderValuePatternVtbl }, \
3244 { &ProviderLegacyIAccessiblePatternVtbl }, \
3245 1, \
3246 "Provider_" # name "", \
3247 NULL, NULL, \
3248 NULL, NULL, \
3249 NULL, NULL, \
3250 ProviderOptions_ServerSideProvider, 0, 0 \
3251 }
3252
3254DEFINE_PROVIDER(hwnd_child2);
3257DEFINE_PROVIDER(child_child);
3258DEFINE_PROVIDER(child_child2);
3259DEFINE_PROVIDER(child2_child);
3260DEFINE_PROVIDER(child2_child_child);
3265
3267static IRawElementProviderSimple *prov_root;
3269{
3270 switch (message)
3271 {
3272 case WM_GETOBJECT:
3273 if (lParam == (DWORD)OBJID_CLIENT)
3274 {
3275 CHECK_EXPECT(winproc_GETOBJECT_CLIENT);
3276 if (acc_client)
3277 return LresultFromObject(&IID_IAccessible, wParam, (IUnknown *)acc_client);
3278
3279 break;
3280 }
3281 else if (lParam == UiaRootObjectId)
3282 {
3283 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot);
3284 if (prov_root)
3286
3287 break;
3288 }
3289
3290 break;
3291
3292 default:
3293 break;
3294 }
3295
3297}
3298
3299static IRawElementProviderSimple *child_win_prov_root;
3301{
3302 switch (message)
3303 {
3304 case WM_GETOBJECT:
3305 if (lParam == UiaRootObjectId)
3306 {
3307 CHECK_EXPECT(child_winproc_GETOBJECT_UiaRoot);
3310
3311 break;
3312 }
3313
3314 break;
3315
3316 default:
3317 break;
3318 }
3319
3321}
3322
3324{
3325 IRawElementProviderSimple *p, *p2;
3326 enum ProviderOptions prov_opt;
3327 WNDCLASSA cls;
3328 HRESULT hr;
3329 HWND hwnd;
3330 VARIANT v;
3331 int i;
3332
3333 cls.style = 0;
3335 cls.cbClsExtra = 0;
3336 cls.cbWndExtra = 0;
3338 cls.hIcon = 0;
3339 cls.hCursor = NULL;
3340 cls.hbrBackground = NULL;
3341 cls.lpszMenuName = NULL;
3342 cls.lpszClassName = "HostProviderFromHwnd class";
3343
3344 RegisterClassA(&cls);
3345
3346 hwnd = CreateWindowExA(0, "HostProviderFromHwnd class", "Test window 1",
3348 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
3349 ok(hwnd != NULL, "Failed to create a test window.\n");
3350
3351 p = (void *)0xdeadbeef;
3353 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3354 ok(p == NULL, "Unexpected instance.\n");
3355
3357 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3358
3359 p = NULL;
3361 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
3362
3363 p2 = NULL;
3365 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
3366 ok(p != p2, "Unexpected instance.\n");
3367 IRawElementProviderSimple_Release(p2);
3368
3369 hr = IRawElementProviderSimple_get_HostRawElementProvider(p, &p2);
3370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3371 ok(p2 == NULL, "Unexpected instance.\n");
3372
3373 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
3374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3375 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
3376 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
3377
3378 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
3379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3380 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3381 VariantClear(&v);
3382
3383 /* No patterns are implemented on the HWND Host provider. */
3384 for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++)
3385 {
3386 IUnknown *unk;
3387
3388 unk = (void *)0xdeadbeef;
3389 hr = IRawElementProviderSimple_GetPatternProvider(p, i, &unk);
3390 ok(hr == S_OK, "Unexpected hr %#lx, %d.\n", hr, i);
3391 ok(!unk, "Pattern %d returned %p\n", i, unk);
3392 }
3393
3394 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
3395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3396 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
3397 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3398 "Unexpected provider options %#x\n", prov_opt);
3399
3400 /* Test behavior post Window destruction. */
3402
3403 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
3404 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3405 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
3406 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
3407
3408 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
3409 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3410 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3411 VariantClear(&v);
3412
3413 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
3414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3415 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
3416 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3417 "Unexpected provider options %#x\n", prov_opt);
3418
3419 IRawElementProviderSimple_Release(p);
3420
3421 UnregisterClassA("HostProviderFromHwnd class", NULL);
3422}
3423
3425{
3426 IStream **stream = param;
3427 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
3428 HRESULT hr;
3429
3431
3432 hr = CoGetInterfaceAndReleaseStream(stream[0], &IID_IUnknown, (void **)&unk_ns);
3433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3434
3435 hr = CoGetInterfaceAndReleaseStream(stream[1], &IID_IUnknown, (void **)&unk_ma);
3436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3437
3439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3440
3442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3443
3444 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
3445 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
3446
3448
3449 return 0;
3450}
3451
3453{
3454 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
3455 IStream *stream[2];
3456 IMarshal *marshal;
3457 HANDLE thread;
3458 ULONG refcnt;
3459 HRESULT hr;
3460
3461 /* ReservedNotSupportedValue. */
3463 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3464
3466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3467 ok(unk_ns != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.\n");
3468
3469 refcnt = IUnknown_AddRef(unk_ns);
3470 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3471
3472 refcnt = IUnknown_AddRef(unk_ns);
3473 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3474
3475 refcnt = IUnknown_Release(unk_ns);
3476 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3477
3479 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3480 ok(unk_ns2 != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.");
3481 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
3482
3483 marshal = NULL;
3484 hr = IUnknown_QueryInterface(unk_ns, &IID_IMarshal, (void **)&marshal);
3485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3486 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
3487
3488 refcnt = IMarshal_AddRef(marshal);
3489 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
3490
3491 refcnt = IMarshal_Release(marshal);
3492 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3493
3494 refcnt = IMarshal_Release(marshal);
3495 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
3496
3497 /* ReservedMixedAttributeValue. */
3499 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3500
3502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3503 ok(unk_ma != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
3504
3505 refcnt = IUnknown_AddRef(unk_ma);
3506 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3507
3508 refcnt = IUnknown_AddRef(unk_ma);
3509 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3510
3511 refcnt = IUnknown_Release(unk_ma);
3512 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3513
3515 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3516 ok(unk_ma2 != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
3517 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
3518
3519 marshal = NULL;
3520 hr = IUnknown_QueryInterface(unk_ma, &IID_IMarshal, (void **)&marshal);
3521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3522 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
3523
3524 refcnt = IMarshal_AddRef(marshal);
3525 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
3526
3527 refcnt = IMarshal_Release(marshal);
3528 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3529
3530 refcnt = IMarshal_Release(marshal);
3531 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
3532
3533 /* Test cross-thread marshaling behavior. */
3535
3537 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3540
3543 {
3544 MSG msg;
3545 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
3546 {
3549 }
3550 }
3552
3554}
3555
3556static struct ProxyEventSink
3557{
3558 IProxyProviderWinEventSink IProxyProviderWinEventSink_iface;
3560
3561 IRawElementProviderSimple *event_elprov;
3563
3564 IRawElementProviderSimple *prop_change_elprov;
3567
3568 IRawElementProviderSimple *structure_change_elprov;
3572
3573static void proxy_event_sink_clear(void)
3574{
3576 IRawElementProviderSimple_Release(ProxyEventSink.event_elprov);
3579
3581 IRawElementProviderSimple_Release(ProxyEventSink.prop_change_elprov);
3585
3587 IRawElementProviderSimple_Release(ProxyEventSink.structure_change_elprov);
3591}
3592
3593static inline struct ProxyEventSink *impl_from_ProxyEventSink(IProxyProviderWinEventSink *iface)
3594{
3596}
3597
3598static HRESULT WINAPI ProxyEventSink_QueryInterface(IProxyProviderWinEventSink *iface, REFIID riid, void **obj)
3599{
3600 *obj = NULL;
3601 if (IsEqualIID(riid, &IID_IProxyProviderWinEventSink) || IsEqualIID(riid, &IID_IUnknown))
3602 *obj = iface;
3603 else
3604 return E_NOINTERFACE;
3605
3606 IProxyProviderWinEventSink_AddRef(iface);
3607 return S_OK;
3608}
3609
3610static ULONG WINAPI ProxyEventSink_AddRef(IProxyProviderWinEventSink *iface)
3611{
3613 return InterlockedIncrement(&This->ref);
3614}
3615
3616static ULONG WINAPI ProxyEventSink_Release(IProxyProviderWinEventSink *iface)
3617{
3619 return InterlockedDecrement(&This->ref);
3620}
3621
3622static HRESULT WINAPI ProxyEventSink_AddAutomationPropertyChangedEvent(IProxyProviderWinEventSink *iface,
3623 IRawElementProviderSimple *elprov, PROPERTYID prop_id, VARIANT new_value)
3624{
3626
3628 This->prop_change_elprov = elprov;
3629 if (elprov)
3630 IRawElementProviderSimple_AddRef(elprov);
3631
3632 This->prop_change_prop_id = prop_id;
3633 VariantCopy(&This->prop_change_value, &new_value);
3634
3635 return S_OK;
3636}
3637
3638static HRESULT WINAPI ProxyEventSink_AddAutomationEvent(IProxyProviderWinEventSink *iface,
3639 IRawElementProviderSimple *elprov, EVENTID event_id)
3640{
3642
3644 This->event_elprov = elprov;
3645 if (elprov)
3646 IRawElementProviderSimple_AddRef(elprov);
3647 This->event_id = event_id;
3648
3649 return S_OK;
3650}
3651
3652static HRESULT WINAPI ProxyEventSink_AddStructureChangedEvent(IProxyProviderWinEventSink *iface,
3653 IRawElementProviderSimple *elprov, enum StructureChangeType structure_change_type, SAFEARRAY *runtime_id)
3654{
3656 HRESULT hr;
3657
3659 This->structure_change_elprov = elprov;
3660 if (elprov)
3661 IRawElementProviderSimple_AddRef(elprov);
3662 This->structure_change_type = structure_change_type;
3663
3664 hr = SafeArrayCopy(runtime_id, &This->structure_change_rt_id);
3665 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3666
3667 return S_OK;
3668}
3669
3670static const IProxyProviderWinEventSinkVtbl ProxyEventSinkVtbl = {
3677};
3678
3680{
3681 { &ProxyEventSinkVtbl },
3682 1,
3683};
3684
3685static void set_accessible_props(struct Accessible *acc, INT role, INT state,
3686 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height);
3687static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id);
3689{
3690 IProxyProviderWinEventHandler *handler;
3691 IRawElementProviderSimple *elprov;
3692 HRESULT hr;
3693
3694 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
3696 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3698
3699 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IProxyProviderWinEventHandler, (void **)&handler);
3700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3701 ok(!!handler, "Handler == NULL\n");
3702
3703 /* EVENT_SYSTEM_ALERT */
3705 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_SYSTEM_ALERT, hwnd, OBJID_CLIENT, CHILDID_SELF,
3707 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3709 ok(ProxyEventSink.event_id == UIA_SystemAlertEventId, "Unexpected event_id %d\n", ProxyEventSink.event_id);
3710 ok(ProxyEventSink.event_elprov == elprov, "Unexpected event_elprov %p\n", ProxyEventSink.event_elprov);
3712
3713 /* EVENT_OBJECT_FOCUS is not handled. */
3714 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, CHILDID_SELF,
3716 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3717
3718 /* EVENT_OBJECT_NAMECHANGE. */
3720 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
3721 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF,
3723 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3724 todo_wine ok(ProxyEventSink.prop_change_elprov == elprov, "Unexpected prop_change_elprov %p\n", ProxyEventSink.prop_change_elprov);
3725 todo_wine ok(ProxyEventSink.prop_change_prop_id == UIA_NamePropertyId, "Unexpected prop_change_prop_id %d\n",
3727 todo_wine ok(V_VT(&ProxyEventSink.prop_change_value) == VT_BSTR, "Unexpected prop_change_value vt %d\n",
3730 ok(!lstrcmpW(V_BSTR(&ProxyEventSink.prop_change_value), Accessible.name), "Unexpected BSTR %s\n",
3735
3736 /* EVENT_OBJECT_REORDER. */
3738 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3740 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_REORDER, hwnd, OBJID_CLIENT, CHILDID_SELF,
3742 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3743 todo_wine ok(ProxyEventSink.structure_change_elprov == elprov, "Unexpected structure_change_elprov %p\n",
3747 ok(!ProxyEventSink.structure_change_rt_id, "structure_change_rt_id != NULL\n");
3748 todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3751
3752 acc_client = NULL;
3753 IProxyProviderWinEventHandler_Release(handler);
3754 IRawElementProviderSimple_Release(elprov);
3755}
3756
3757DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
3759{
3761 HRESULT hr;
3762
3763 hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void**)&sp);
3764 if (SUCCEEDED(hr))
3765 {
3766 IAccessible *acc2 = NULL;
3767
3768 hr = IServiceProvider_QueryService(sp, &SID_AccFromDAWrapper, &IID_IAccessible, (void**)&acc2);
3769 IServiceProvider_Release(sp);
3770 if (SUCCEEDED(hr) && acc2)
3771 return acc2;
3772 }
3773
3774 return NULL;
3775}
3776
3777#define check_msaa_prov_acc( elprov, acc, cid) \
3778 check_msaa_prov_acc_( ((IUnknown *)elprov), (acc), (cid), __LINE__)
3779static void check_msaa_prov_acc_(IUnknown *elprov, IAccessible *acc, INT cid, int line)
3780{
3781 ILegacyIAccessibleProvider *accprov;
3782 IAccessible *acc2, *acc3;
3783 INT child_id;
3784 HRESULT hr;
3785
3786 hr = IUnknown_QueryInterface(elprov, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
3787 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3788 ok_(__FILE__, line)(!!accprov, "accprov == NULL\n");
3789
3790 acc2 = acc3 = NULL;
3791 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc2);
3792 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3793
3794 /*
3795 * Potentially get our IAccessible out of a direct annotation wrapper
3796 * IAccessible.
3797 */
3798 if (acc && acc2 && (acc != acc2) && (acc3 = msaa_acc_da_unwrap(acc2)))
3799 {
3800 IAccessible_Release(acc2);
3801 acc2 = acc3;
3802 }
3803 ok_(__FILE__, line)(acc2 == acc, "acc2 != acc\n");
3804 if (acc2)
3805 IAccessible_Release(acc2);
3806
3807 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
3808 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3809 ok_(__FILE__, line)(child_id == cid, "child_id != cid\n");
3810
3811 ILegacyIAccessibleProvider_Release(accprov);
3812}
3813
3814#define check_msaa_prov_host_elem_prov( elem, exp_host_prov) \
3815 check_msaa_prov_host_elem_prov_( ((IUnknown *)elem), (exp_host_prov), __LINE__)
3816static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov, int line)
3817{
3818 IRawElementProviderSimple *elprov, *elprov2;
3819 HRESULT hr;
3820
3821 hr = IUnknown_QueryInterface(elem, &IID_IRawElementProviderSimple, (void **)&elprov);
3822 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3823 ok_(__FILE__, line)(!!elprov, "elprov == NULL\n");
3824
3825 elprov2 = (void *)0xdeadbeef;
3826 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3827 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3828 ok_(__FILE__, line)((elprov2 != (void *)0xdeadbeef) && !!elprov2 == exp_host_prov, "Unexpected provider %p from get_HostRawElementProvider\n", elprov2);
3829
3830 if (elprov2)
3831 IRawElementProviderSimple_Release(elprov2);
3832 IRawElementProviderSimple_Release(elprov);
3833}
3834
3836{
3837 IRawElementProviderFragmentRoot *elroot, *elroot2;
3838 IRawElementProviderFragment *elfrag, *elfrag2;
3839 IRawElementProviderSimple *elprov;
3840 SAFEARRAY *ret_arr;
3841 ULONG old_ref;
3842 HRESULT hr;
3843
3844 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
3847
3848 elprov = NULL;
3849 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3851 ok(!!elprov, "elprov == NULL\n");
3852
3853 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3854 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3855 ok(!!elfrag, "elfrag == NULL\n");
3856
3857 /* GetEmbeddedFragmentRoots test. */
3858 ret_arr = (void *)0xdeadbeef;
3859 hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &ret_arr);
3860 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3861 ok(!ret_arr, "ret_arr != NULL\n");
3862
3863 /*
3864 * get_FragmentRoot does the equivalent of calling
3865 * AccessibleObjectFromWindow with OBJID_CLIENT on the HWND associated
3866 * with our IAccessible. Unlike UiaProviderFromIAccessible, it will create
3867 * a provider from a default oleacc proxy.
3868 */
3869 elroot = NULL;
3870 acc_client = NULL;
3871 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3872 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3874 ok(!!elroot, "elroot == NULL\n");
3875 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3876
3877 /*
3878 * ILegacyIAccessibleProvider::GetIAccessible returns a NULL
3879 * IAccessible if the provider represents an oleacc proxy.
3880 */
3882
3883 /*
3884 * Returns a provider from get_HostRawElementProvider without having
3885 * to query the HWND.
3886 */
3888
3889 hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
3890 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3891 ok(!!elfrag2, "elfrag2 == NULL\n");
3892
3893 /*
3894 * Even on a provider retrieved from get_FragmentRoot, the HWND is
3895 * queried and a new fragment root is returned rather than just
3896 * returning our current fragment root interface.
3897 */
3898 elroot2 = NULL;
3899 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3900 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
3901 IRawElementProviderFragment_Release(elfrag2);
3902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3903 ok(!!elroot2, "elroot2 == NULL\n");
3905 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3906
3907 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
3908 IRawElementProviderFragmentRoot_Release(elroot2);
3909 IRawElementProviderFragmentRoot_Release(elroot);
3910
3911 /*
3912 * Accessible is now the IAccessible for our HWND, so we'll get it instead
3913 * of an oleacc proxy.
3914 */
3916 elroot = NULL;
3917 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3918 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3920 ok(!!elroot, "elroot == NULL\n");
3921 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3923
3924 /*
3925 * Returns a provider from get_HostRawElementProvider without having
3926 * to query the HWND, same as before.
3927 */
3929
3930 hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
3931 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3932 ok(!!elfrag2, "elfrag2 == NULL\n");
3933
3934 /* Same deal as before, unique FragmentRoot even on a known root. */
3935 elroot2 = NULL;
3936 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3937 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
3938 IRawElementProviderFragment_Release(elfrag2);
3939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3940 ok(!!elroot2, "elroot2 == NULL\n");
3942 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3943
3944 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
3945 IRawElementProviderFragmentRoot_Release(elroot2);
3946
3947 IRawElementProviderFragmentRoot_Release(elroot);
3948 IRawElementProviderFragment_Release(elfrag);
3949
3950 /*
3951 * IRawElementProviderFragmentRoot::GetFocus will call get_accFocus.
3952 */
3953 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
3954 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3955 ok(!!elroot, "elroot == NULL\n");
3956
3957 /* Focus is CHILDID_SELF, returns NULL. */
3958 elfrag = (void *)0xdeadbeef;
3960 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
3961 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
3962 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3963 ok(!elfrag, "elfrag != NULL\n");
3964 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
3965
3966 /*
3967 * get_accFocus returns child ID 1, which is a simple child element.
3968 * get_accState for child ID 1 returns STATE_SYSTEM_INVISIBLE, so no
3969 * element will be returned.
3970 */
3971 elfrag = (void *)0xdeadbeef;
3973
3974 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
3975 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
3976 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
3977 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
3978 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3979 ok(!elfrag, "elfrag != NULL\n");
3980 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
3981 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
3982 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
3983
3984 /*
3985 * get_accFocus returns child ID 3, which is another simple child
3986 * element. get_accState for child ID 3 does not have
3987 * STATE_SYSTEM_INVISIBLE set, so it will return an element.
3988 */
3989 elfrag = (void *)0xdeadbeef;
3991
3992 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
3993 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
3994 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
3995 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
3996 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3997 ok(!!elfrag, "elfrag == NULL\n");
3999 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4000 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4001 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4002
4003 IRawElementProviderFragment_Release(elfrag);
4004
4005 /*
4006 * get_accFocus returns child ID 2 which is a full IAccessible,
4007 * Accessible_child.
4008 */
4009 elfrag = (void *)0xdeadbeef;
4012
4013 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4014 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4016 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4019 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4020 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4021 ok(!!elfrag, "elfrag == NULL\n");
4022 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4023 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4028
4029 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4030 IRawElementProviderFragment_Release(elfrag);
4031
4032 /*
4033 * get_accFocus returns child ID 2 which is a full IAccessible,
4034 * Accessible_child. It returns failure from get_accState so it isn't
4035 * returned.
4036 */
4037 elfrag = (void *)0xdeadbeef;
4039 Accessible_child.state = 0;
4040
4041 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4042 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4044 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4046 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4047 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4048 ok(!elfrag, "elfrag != NULL\n");
4049 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4050 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4054
4055 /*
4056 * get_accFocus returns child ID 7 which is a full IAccessible,
4057 * Accessible. This is the same IAccessible interface as the one we called
4058 * get_accFocus on, so it is ignored. Same behavior as CHILDID_SELF.
4059 */
4060 elfrag = (void *)0xdeadbeef;
4063
4064 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4065 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4066 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4067 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4069 ok(!elfrag, "elfrag != NULL\n");
4070 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4071 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4072 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4073
4074 /*
4075 * Return E_NOTIMPL from get_accFocus, returns a new provider representing
4076 * the same IAccessible.
4077 */
4078 elfrag = (void *)0xdeadbeef;
4079 old_ref = Accessible.ref;
4081
4082 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4083 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4084 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4085 ok(!!elfrag, "elfrag == NULL\n");
4086 ok(Accessible.ref > old_ref, "Unexpected ref %ld\n", Accessible.ref);
4087 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4088
4089 /* Two unique COM objects that represent the same IAccessible. */
4090 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elfrag), "elroot == elfrag\n");
4092 IRawElementProviderFragment_Release(elfrag);
4093 ok(Accessible.ref == old_ref, "Unexpected ref %ld\n", Accessible.ref);
4095
4096 /*
4097 * Similar to CHILDID_SELF, if the same IAccessible interface is returned
4098 * as a VT_DISPATCH, we'll get no element.
4099 */
4100 elfrag = (void *)0xdeadbeef;
4102
4103 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4104 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4105 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4107 ok(!elfrag, "elfrag != NULL\n");
4108 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4109 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4110
4111 /*
4112 * Return Accessible_child as a VT_DISPATCH - will get an element.
4113 */
4114 elfrag = (void *)0xdeadbeef;
4115 Accessible.focus_acc = &Accessible_child.IAccessible_iface;
4117
4118 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4120 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4123 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4125 ok(!!elfrag, "elfrag == NULL\n");
4126 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4131
4132 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4133 IRawElementProviderFragment_Release(elfrag);
4134
4135 /*
4136 * Fail get_accFocus on child.
4137 */
4138 Accessible_child.focus_child_id = -1;
4140
4141 elfrag = (void *)0xdeadbeef;
4142 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4144 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4147 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4148 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4149 ok(!!elfrag, "elfrag == NULL\n");
4150 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4155
4156 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4157 IRawElementProviderFragment_Release(elfrag);
4158
4159 IRawElementProviderFragmentRoot_Release(elroot);
4160 IRawElementProviderSimple_Release(elprov);
4161
4162 /*
4163 * Test simple child element.
4164 */
4165 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
4166 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4167
4168 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4169 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4170 ok(!!elfrag, "elfrag == NULL\n");
4171
4172 /* GetEmbeddedFragmentRoots test. */
4173 ret_arr = (void *)0xdeadbeef;
4174 hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &ret_arr);
4175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4176 ok(!ret_arr, "ret_arr != NULL\n");
4177
4178 /*
4179 * Simple child element queries HWND as well, does not just return its
4180 * parent.
4181 */
4182 elroot = NULL;
4183 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4184 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
4185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4186 ok(!!elroot, "elroot == NULL\n");
4187 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4190
4191 IRawElementProviderFragmentRoot_Release(elroot);
4192 IRawElementProviderFragment_Release(elfrag);
4193
4194 /*
4195 * IRawElementProviderFragmentRoot::GetFocus will not call get_accFocus
4196 * on a simple child IAccessible.
4197 */
4198 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
4199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4200 ok(!!elroot, "elroot == NULL\n");
4201
4202 elfrag = (void *)0xdeadbeef;
4203 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4205 ok(!elfrag, "elfrag != NULL\n");
4206
4207 IRawElementProviderFragmentRoot_Release(elroot);
4208 IRawElementProviderSimple_Release(elprov);
4209
4210 /*
4211 * Test child of root HWND IAccessible.
4212 */
4213 set_accessible_props(&Accessible_child, ROLE_SYSTEM_TEXT, 0, 0, L"acc_child_name", 0, 0, 0, 0);
4215
4216 elprov = NULL;
4217 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent); /* Gets HWND from parent IAccessible. */
4219 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4221 ok(!!elprov, "elprov == NULL\n");
4224
4225 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4226 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4227 ok(!!elfrag, "elfrag == NULL\n");
4228
4229 /* GetEmbeddedFragmentRoots test. */
4230 ret_arr = (void *)0xdeadbeef;
4231 hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &ret_arr);
4232 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4233 ok(!ret_arr, "ret_arr != NULL\n");
4234
4235 /*
4236 * Again, same behavior as simple children. It doesn't just retrieve the
4237 * parent IAccessible, it queries the HWND.
4238 */
4239 elroot = NULL;
4240 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4241 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
4242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4243 ok(!!elroot, "elroot == NULL\n");
4244 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4246
4247 IRawElementProviderFragmentRoot_Release(elroot);
4248 IRawElementProviderFragment_Release(elfrag);
4249
4250 /*
4251 * GetFocus tests.
4252 */
4253 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
4254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4255 ok(!!elroot, "elroot == NULL\n");
4256
4257 /*
4258 * get_accFocus returns E_NOTIMPL, returns new provider for same
4259 * IAccessible.
4260 */
4261 elfrag = (void *)0xdeadbeef;
4262 old_ref = Accessible_child.ref;
4263 Accessible_child.focus_child_id = -1;
4265 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4266 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4267 ok(!!elfrag, "elfrag == NULL\n");
4268 ok(Accessible_child.ref > old_ref, "Unexpected ref %ld\n", Accessible.ref);
4270
4271 /* Again, two unique COM objects that represent the same IAccessible. */
4272 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elfrag), "elroot == elfrag\n");
4273 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4274 IRawElementProviderFragment_Release(elfrag);
4275 ok(Accessible_child.ref == old_ref, "Unexpected ref %ld\n", Accessible.ref);
4276
4277 IRawElementProviderFragmentRoot_Release(elroot);
4278 IRawElementProviderSimple_Release(elprov);
4279
4281 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4282 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4283 acc_client = NULL;
4284}
4285
4289};
4290
4292 { ROLE_SYSTEM_TITLEBAR, UIA_TitleBarControlTypeId },
4293 { ROLE_SYSTEM_MENUBAR, UIA_MenuBarControlTypeId },
4294 { ROLE_SYSTEM_SCROLLBAR, UIA_ScrollBarControlTypeId },
4295 { ROLE_SYSTEM_GRIP, UIA_ThumbControlTypeId },
4296 { ROLE_SYSTEM_WINDOW, UIA_WindowControlTypeId },
4297 { ROLE_SYSTEM_MENUPOPUP, UIA_MenuControlTypeId },
4298 { ROLE_SYSTEM_MENUITEM, UIA_MenuItemControlTypeId },
4299 { ROLE_SYSTEM_TOOLTIP, UIA_ToolTipControlTypeId },
4300 { ROLE_SYSTEM_APPLICATION, UIA_WindowControlTypeId },
4301 { ROLE_SYSTEM_DOCUMENT, UIA_DocumentControlTypeId },
4302 { ROLE_SYSTEM_PANE, UIA_PaneControlTypeId },
4303 { ROLE_SYSTEM_GROUPING, UIA_GroupControlTypeId },
4304 { ROLE_SYSTEM_SEPARATOR, UIA_SeparatorControlTypeId },
4305 { ROLE_SYSTEM_TOOLBAR, UIA_ToolBarControlTypeId },
4306 { ROLE_SYSTEM_STATUSBAR, UIA_StatusBarControlTypeId },
4307 { ROLE_SYSTEM_TABLE, UIA_TableControlTypeId },
4308 { ROLE_SYSTEM_COLUMNHEADER, UIA_HeaderControlTypeId },
4309 { ROLE_SYSTEM_ROWHEADER, UIA_HeaderControlTypeId },
4310 { ROLE_SYSTEM_CELL, UIA_DataItemControlTypeId },
4311 { ROLE_SYSTEM_LINK, UIA_HyperlinkControlTypeId },
4312 { ROLE_SYSTEM_LIST, UIA_ListControlTypeId },
4313 { ROLE_SYSTEM_LISTITEM, UIA_ListItemControlTypeId },
4314 { ROLE_SYSTEM_OUTLINE, UIA_TreeControlTypeId },
4315 { ROLE_SYSTEM_OUTLINEITEM, UIA_TreeItemControlTypeId },
4316 { ROLE_SYSTEM_PAGETAB, UIA_TabItemControlTypeId },
4317 { ROLE_SYSTEM_INDICATOR, UIA_ThumbControlTypeId },
4318 { ROLE_SYSTEM_GRAPHIC, UIA_ImageControlTypeId },
4319 { ROLE_SYSTEM_STATICTEXT, UIA_TextControlTypeId },
4320 { ROLE_SYSTEM_TEXT, UIA_EditControlTypeId },
4321 { ROLE_SYSTEM_PUSHBUTTON, UIA_ButtonControlTypeId },
4322 { ROLE_SYSTEM_CHECKBUTTON, UIA_CheckBoxControlTypeId },
4323 { ROLE_SYSTEM_RADIOBUTTON, UIA_RadioButtonControlTypeId },
4324 { ROLE_SYSTEM_COMBOBOX, UIA_ComboBoxControlTypeId },
4325 { ROLE_SYSTEM_PROGRESSBAR, UIA_ProgressBarControlTypeId },
4326 { ROLE_SYSTEM_SLIDER, UIA_SliderControlTypeId },
4327 { ROLE_SYSTEM_SPINBUTTON, UIA_SpinnerControlTypeId },
4328 { ROLE_SYSTEM_BUTTONDROPDOWN, UIA_SplitButtonControlTypeId },
4329 { ROLE_SYSTEM_BUTTONMENU, UIA_MenuItemControlTypeId },
4330 { ROLE_SYSTEM_BUTTONDROPDOWNGRID, UIA_ButtonControlTypeId },
4331 { ROLE_SYSTEM_PAGETABLIST, UIA_TabControlTypeId },
4332 { ROLE_SYSTEM_SPLITBUTTON, UIA_SplitButtonControlTypeId },
4333 /* These accessible roles have no equivalent in UI Automation. */
4334 { ROLE_SYSTEM_SOUND, 0 },
4335 { ROLE_SYSTEM_CURSOR, 0 },
4336 { ROLE_SYSTEM_CARET, 0 },
4337 { ROLE_SYSTEM_ALERT, 0 },
4338 { ROLE_SYSTEM_CLIENT, 0 },
4339 { ROLE_SYSTEM_CHART, 0 },
4340 { ROLE_SYSTEM_DIALOG, 0 },
4341 { ROLE_SYSTEM_BORDER, 0 },
4342 { ROLE_SYSTEM_COLUMN, 0 },
4343 { ROLE_SYSTEM_ROW, 0 },
4344 { ROLE_SYSTEM_HELPBALLOON, 0 },
4345 { ROLE_SYSTEM_CHARACTER, 0 },
4346 { ROLE_SYSTEM_PROPERTYPAGE, 0 },
4347 { ROLE_SYSTEM_DROPLIST, 0 },
4348 { ROLE_SYSTEM_DIAL, 0 },
4349 { ROLE_SYSTEM_HOTKEYFIELD, 0 },
4350 { ROLE_SYSTEM_DIAGRAM, 0 },
4351 { ROLE_SYSTEM_ANIMATION, 0 },
4352 { ROLE_SYSTEM_EQUATION, 0 },
4353 { ROLE_SYSTEM_WHITESPACE, 0 },
4354 { ROLE_SYSTEM_IPADDRESS, 0 },
4355 { ROLE_SYSTEM_OUTLINEBUTTON, 0 },
4356};
4357
4361};
4362
4364 { STATE_SYSTEM_FOCUSED, UIA_HasKeyboardFocusPropertyId },
4365 { STATE_SYSTEM_FOCUSABLE, UIA_IsKeyboardFocusablePropertyId },
4366 { ~STATE_SYSTEM_UNAVAILABLE, UIA_IsEnabledPropertyId },
4367 { STATE_SYSTEM_PROTECTED, UIA_IsPasswordPropertyId },
4368};
4369
4370static void set_accessible_props(struct Accessible *acc, INT role, INT state,
4371 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height)
4372{
4373
4374 acc->role = role;
4375 acc->state = state;
4376 acc->child_count = child_count;
4377 acc->name = name;
4378 acc->left = left;
4379 acc->top = top;
4380 acc->width = width;
4381 acc->height = height;
4382}
4383
4384static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id)
4385{
4386 acc->enable_ia2 = enable_ia2;
4387 acc->unique_id = unique_id;
4388}
4389
4391{
4392 IRawElementProviderSimple *elprov, *elprov2;
4393 HRESULT hr;
4394
4395 /* Only one exposes an IA2 interface, no match. */
4396 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
4398 set_accessible_props(&Accessible2, ROLE_SYSTEM_TEXT, 0, 0, L"acc_name", 0, 0, 0, 0);
4400
4401 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4402 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4403 if (Accessible.ref != 3)
4404 {
4405 IRawElementProviderSimple_Release(elprov);
4406 win_skip("UiaProviderFromIAccessible has no IAccessible2 support, skipping tests.\n");
4407 return;
4408 }
4409
4410 acc_client = &Accessible2.IAccessible_iface;
4411 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4412 /* The four below are only called on Win10v1909. */
4413 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4414 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4415 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4416 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4417 elprov2 = (void *)0xdeadbeef;
4418 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4419 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4420 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4421 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4422 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4423
4424 /*
4425 * Win10v1909 has IAccessible2 support, but it's not used for checking if
4426 * two IAccessible interfaces match. Skip the comparison tests for this
4427 * Windows version.
4428 */
4429 if (Accessible.called_get_accRole)
4430 {
4431 IRawElementProviderSimple_Release(elprov);
4432 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4433 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4434 CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
4435 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
4436 win_skip("Win10v1909 doesn't support IAccessible2 interface comparison, skipping tests.\n");
4437 return;
4438 }
4439 Accessible.called_get_accRole = Accessible.expect_get_accRole = 0;
4440 Accessible2.called_get_accRole = Accessible2.expect_get_accRole = 0;
4441 Accessible2.called_QI_IAccIdentity = Accessible2.expect_QI_IAccIdentity = 0;
4442 Accessible2.called_get_accParent = Accessible2.expect_get_accParent = 0;
4443
4444 Accessible.role = Accessible2.role = 0;
4445 elprov2 = (void *)0xdeadbeef;
4446 acc_client = NULL;
4447 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4448 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4449 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4450
4451 IRawElementProviderSimple_Release(elprov);
4452 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4453
4454 /*
4455 * If &Accessible returns a failure code on get_uniqueID, &Accessible2's
4456 * uniqueID is not checked.
4457 */
4460 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4461 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4462 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4463
4464 acc_client = &Accessible2.IAccessible_iface;
4465 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4466 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4467 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4468 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4469 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4470 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4471 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
4472 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
4473 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
4474 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4475 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4476 elprov2 = (void *)0xdeadbeef;
4477 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4478 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4479 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4480 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4481 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4482 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4483 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4484 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4485 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4486 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4487 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
4488 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
4489 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
4492 IRawElementProviderSimple_Release(elprov2);
4493
4494 elprov2 = (void *)0xdeadbeef;
4495 acc_client = NULL;
4496 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4497 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4498 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4499 IRawElementProviderSimple_Release(elprov2);
4500
4501 IRawElementProviderSimple_Release(elprov);
4502 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4503
4504 /* Unique ID matches. */
4507 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4509 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4510
4511 acc_client = &Accessible2.IAccessible_iface;
4512 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4513 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
4514 SET_ACC_METHOD_EXPECT(&Accessible2, get_uniqueID);
4515 elprov2 = (void *)0xdeadbeef;
4516 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4517 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4518 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4519 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4520 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4521 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
4522 CHECK_ACC_METHOD_CALLED(&Accessible2, get_uniqueID);
4523 IRawElementProviderSimple_Release(elprov2);
4524
4525 elprov2 = (void *)0xdeadbeef;
4526 acc_client = NULL;
4527 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4528 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4529 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4530 IRawElementProviderSimple_Release(elprov2);
4531
4532 IRawElementProviderSimple_Release(elprov);
4533 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4534
4535 /* Unique ID mismatch. */
4538 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4540 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4541
4542 acc_client = &Accessible2.IAccessible_iface;
4543 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4544 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
4545 SET_ACC_METHOD_EXPECT(&Accessible2, get_uniqueID);
4546 elprov2 = (void *)0xdeadbeef;
4547 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4549 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4550 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4551 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4552 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
4553 CHECK_ACC_METHOD_CALLED(&Accessible2, get_uniqueID);
4554
4555 elprov2 = (void *)0xdeadbeef;
4556 acc_client = NULL;
4557 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4558 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4559 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4560
4561 IRawElementProviderSimple_Release(elprov);
4562 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4563
4564 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
4566 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
4568}
4569
4570#define check_fragment_acc( fragment, acc, cid) \
4571 check_fragment_acc_( (fragment), (acc), (cid), __LINE__)
4572static void check_fragment_acc_(IRawElementProviderFragment *elfrag, IAccessible *acc,
4573 INT cid, int line)
4574{
4575 ILegacyIAccessibleProvider *accprov;
4576 IAccessible *accessible;
4577 INT child_id;
4578 HRESULT hr;
4579
4580 hr = IRawElementProviderFragment_QueryInterface(elfrag, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
4581 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
4582 ok_(__FILE__, line) (!!accprov, "accprov == NULL\n");
4583
4584 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &accessible);
4585 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
4586 ok_(__FILE__, line) (accessible == acc, "accessible != acc\n");
4587 IAccessible_Release(accessible);
4588
4589 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
4590 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
4591 ok_(__FILE__, line) (child_id == cid, "child_id != cid\n");
4592
4593 ILegacyIAccessibleProvider_Release(accprov);
4594}
4595
4597{
4598 IRawElementProviderFragment *elfrag, *elfrag2, *elfrag3;
4599 IRawElementProviderSimple *elprov, *elprov2;
4600 HRESULT hr;
4601
4602 /*
4603 * Full IAccessible parent, with 4 children:
4604 * childid 1 is a simple element, with STATE_SYSTEM_INVISIBLE.
4605 * childid 2 is Accessible_child.
4606 * childid 3 is a simple element with STATE_SYSTEM_NORMAL.
4607 * childid 4 is Accessible_child2.
4608 */
4609 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4611 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4612
4613 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4614 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4615 ok(!!elfrag, "elfrag == NULL\n");
4616
4617 /*
4618 * First time doing NavigateDirection_Parent will result in the same root
4619 * accessible check as get_HostRawElementProvider. If this IAccessible is
4620 * the root for its associated HWND, NavigateDirection_Parent and
4621 * NavigateDirection_Next/PreviousSibling will do nothing, as UI Automation
4622 * provides non-client area providers for the root IAccessible's parent
4623 * and siblings.
4624 */
4625 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
4626 L"acc_name", 0, 0, 50, 50);
4627 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
4628 L"acc_name", 0, 0, 50, 50);
4629 acc_client = &Accessible2.IAccessible_iface;
4630 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4631 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4632 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4633 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4634 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4635 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4636 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4637 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
4638 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
4639 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
4640 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
4641 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4642 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4643 elfrag2 = (void *)0xdeadbeef;
4644 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4645 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4647 ok(!elfrag2, "elfrag2 != NULL\n");
4648 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4649 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4650 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4651 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4652 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4653 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4654 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4655 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
4656 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
4657 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
4658 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
4661 acc_client = NULL;
4662
4663 /* No check against root IAccessible, since it was done previously. */
4664 elprov2 = (void *)0xdeadbeef;
4665 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4666 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4667 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4668 IRawElementProviderSimple_Release(elprov2);
4669
4670 /* Do nothing. */
4671 elfrag2 = (void *)0xdeadbeef;
4672 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4673 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4674 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4675 ok(!elfrag2, "elfrag2 != NULL\n");
4676
4677 elfrag2 = (void *)0xdeadbeef;
4678 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4679 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4681 ok(!elfrag2, "elfrag2 != NULL\n");
4682
4683 elfrag2 = (void *)0xdeadbeef;
4684 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
4685 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4686 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4687 ok(!elfrag2, "elfrag2 != NULL\n");
4688
4689 /*
4690 * Retrieve childid 2 (Accessible_child) as first child. childid 1 is skipped due to
4691 * having a state of STATE_SYSTEM_INVISIBLE.
4692 */
4695 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 3);
4696 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 2);
4697 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4700 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4701 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4702 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4703 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4704 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4705 ok(!!elfrag2, "elfrag2 == NULL\n");
4706 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 3);
4707 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 2);
4711
4712 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4713 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4714 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4715 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4716 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_NextSibling, &elfrag3);
4717 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
4718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4719 ok(!!elfrag3, "elfrag2 == NULL\n");
4720 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4721 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4722 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4724
4725 IRawElementProviderFragment_Release(elfrag3);
4726 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4727 IRawElementProviderFragment_Release(elfrag2);
4728 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4729 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4730
4731 /* Retrieve childid 3 as first child now that Accessible_child is invisible. */
4733 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 4);
4734 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 3);
4735 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accState, 2);
4737 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4738 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4740 ok(!!elfrag2, "elfrag2 == NULL\n");
4741 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 4);
4742 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 3);
4743 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accState, 2);
4746 IRawElementProviderFragment_Release(elfrag2);
4747 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4748
4749 /* Retrieve childid 4 (Accessible_child2) as last child. */
4751 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 2);
4752 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4756 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4757 ok(Accessible_child2.ref == 2, "Unexpected refcnt %ld\n", Accessible_child2.ref);
4758 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4760 ok(!!elfrag2, "elfrag2 == NULL\n");
4761 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 2);
4762 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4766
4767 check_fragment_acc(elfrag2, &Accessible_child2.IAccessible_iface, CHILDID_SELF);
4768 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4769 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4770 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4771 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_PreviousSibling, &elfrag3);
4772 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
4773 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4774 ok(!!elfrag3, "elfrag2 == NULL\n");
4775 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4776 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4777 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4779
4780 IRawElementProviderFragment_Release(elfrag3);
4781 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4782 IRawElementProviderFragment_Release(elfrag2);
4783 ok(Accessible_child2.ref == 1, "Unexpected refcnt %ld\n", Accessible_child2.ref);
4784 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4785
4786 /* Retrieve childid 3 as last child, now that Accessible_child2 is STATE_SYSTEM_INVISIBLE. */
4788 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 3);
4789 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 2);
4790 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4792 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4793 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4794 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4795 ok(!!elfrag2, "elfrag2 == NULL\n");
4796 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 3);
4797 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 2);
4798 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4801 IRawElementProviderFragment_Release(elfrag2);
4802 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4803
4804 IRawElementProviderFragment_Release(elfrag);
4805 IRawElementProviderSimple_Release(elprov);
4806 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4807
4808 /*
4809 * Full IAccessible child tests.
4810 */
4812 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4813 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, 0, UIA_PFIA_DEFAULT, &elprov);
4814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4817 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4818
4819 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4821 ok(!!elfrag, "elfrag == NULL\n");
4822
4823 /*
4824 * After determining this isn't the root IAccessible, get_accParent will
4825 * be used to get the parent.
4826 */
4827 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4828 set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4829 acc_client = &Accessible2.IAccessible_iface;
4830 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4832 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4833 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4834 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4835 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4836 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4837 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4838 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4839 ok(!!elfrag2, "elfrag2 == NULL\n");
4842 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4845 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4847 IRawElementProviderFragment_Release(elfrag2);
4848 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4849 acc_client = NULL;
4850
4851 /* Second call only does get_accParent, no root check. */
4852 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4853 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4854 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4855 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4856 ok(!!elfrag2, "elfrag2 == NULL\n");
4859 IRawElementProviderFragment_Release(elfrag2);
4860 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4861
4862 /* ChildCount of 0, do nothing for First/Last child.*/
4863 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4864 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4865 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4866 ok(!elfrag2, "elfrag2 != NULL\n");
4867 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4868
4869 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4870 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4872 ok(!elfrag2, "elfrag2 != NULL\n");
4873 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4874
4875 /*
4876 * In the case of sibling navigation on an IAccessible that wasn't
4877 * received through previous navigation from a parent (i.e, from
4878 * NavigateDirection_First/LastChild), we have to figure out which
4879 * IAccessible child we represent by comparing against all children of our
4880 * IAccessible parent. If we find more than one IAccessible that matches,
4881 * or none at all that do, navigation will fail.
4882 */
4884 L"acc_child", 0, 0, 50, 50);
4886 L"acc_child", 0, 0, 50, 50);
4887 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 5);
4888 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 4);
4889 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4892 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4897 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accChildCount);
4900 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4901 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4902 ok(!elfrag2, "elfrag2 != NULL\n");
4903 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 5);
4904 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 4);
4908 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4913 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accChildCount);
4916
4917 /* Now they have a role mismatch, we can determine our position. */
4919 L"acc_child", 0, 0, 50, 50);
4920 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 6);
4921 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 5);
4922 /* Check ChildID 1 for STATE_SYSTEM_INVISIBLE. */
4923 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4924 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4927 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
4928 /*
4929 * Even though we didn't get a new fragment, now that we know our
4930 * position, a reference is added to the parent IAccessible.
4931 */
4932 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4933 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4934 ok(!elfrag2, "elfrag2 != NULL\n");
4935 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 6);
4936 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 5);
4937 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4941
4942 /* Now that we know our position, no extra nav work. */
4943 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4944 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4945 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4946 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4947 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4948 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4949 ok(!!elfrag2, "elfrag2 == NULL\n");
4950 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4951 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4952 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4953 if (elfrag2)
4954 {
4956 IRawElementProviderFragment_Release(elfrag2);
4957 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4958 }
4959
4960 IRawElementProviderFragment_Release(elfrag);
4961 IRawElementProviderSimple_Release(elprov);
4962 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4963 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4964
4965 /*
4966 * Simple element child tests.
4967 */
4968 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
4969 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4970 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4971
4972 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4974 ok(!!elfrag, "elfrag == NULL\n");
4975
4976 /*
4977 * Simple child elements don't check the root IAccessible, because they
4978 * can't be the root IAccessible.
4979 */
4980 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4981 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4982 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4983 ok(!!elfrag2, "elfrag2 == NULL\n");
4985 IRawElementProviderFragment_Release(elfrag2);
4986 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4987
4988 /*
4989 * Test NavigateDirection_First/LastChild on simple child element. Does
4990 * nothing, as simple children cannot have children.
4991 */
4992 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4993 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4994 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4995 ok(!elfrag2, "elfrag2 != NULL\n");
4996
4997 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4998 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4999 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5000 ok(!elfrag2, "elfrag2 != NULL\n");
5001
5002 /*
5003 * NavigateDirection_Next/PreviousSibling behaves normally, no IAccessible
5004 * comparisons.
5005 */
5006 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5007 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
5010 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
5011 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
5012 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
5013 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
5014 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5015 ok(!!elfrag2, "elfrag2 == NULL\n");
5016 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5017 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
5021 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
5022
5023 IRawElementProviderFragment_Release(elfrag2);
5024 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
5025 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
5026 IRawElementProviderFragment_Release(elfrag);
5027 IRawElementProviderSimple_Release(elprov);
5028 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5029
5030 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
5031 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
5032 set_accessible_props(&Accessible_child, 0, 0, 0, NULL, 0, 0, 0, 0);
5033 set_accessible_props(&Accessible_child2, 0, 0, 0, NULL, 0, 0, 0, 0);
5034}
5035
5037{
5038 IRawElementProviderSimple *elprov;
5039 RECT rect[2] = { 0 };
5040 HRESULT hr;
5041 VARIANT v;
5042 int i, x;
5043
5044 /* MSAA role to UIA control type test. */
5045 VariantInit(&v);
5046 for (i = 0; i < ARRAY_SIZE(msaa_role_uia_types); i++)
5047 {
5048 const struct msaa_role_uia_type *role = &msaa_role_uia_types[i];
5049 ILegacyIAccessibleProvider *accprov;
5050 DWORD role_val;
5051 IUnknown *unk;
5052
5053 /*
5054 * Roles get cached once a valid one is mapped, so create a new
5055 * element for each role.
5056 */
5057 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5058 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5059 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5060
5061 Accessible.role = role->acc_role;
5062 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5063 VariantClear(&v);
5064 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5065 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5066 if (role->uia_control_type)
5067 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
5068 else
5069 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
5070 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5071
5072 if (!role->uia_control_type)
5073 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5074 VariantClear(&v);
5075 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5077 if (role->uia_control_type)
5078 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
5079 else
5080 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
5081 if (!role->uia_control_type)
5082 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5083
5084 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
5085 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5086 ok(!!unk, "unk == NULL\n");
5087
5088 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
5089 IUnknown_Release(unk);
5090 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5091 ok(!!accprov, "accprov == NULL\n");
5092
5093 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5094 hr = ILegacyIAccessibleProvider_get_Role(accprov, &role_val);
5095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5096 ok(role_val == Accessible.role, "role_val != Accessible.role\n");
5097 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5098
5099 ILegacyIAccessibleProvider_Release(accprov);
5100 IRawElementProviderSimple_Release(elprov);
5101 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5102 }
5103
5104 /* ROLE_SYSTEM_CLOCK has no mapping in Windows < 10 1809. */
5105 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5107 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5108
5109 Accessible.role = ROLE_SYSTEM_CLOCK;
5110 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5111 VariantClear(&v);
5112 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5113 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5114 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
5115 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
5116 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5117
5118 if (V_VT(&v) == VT_EMPTY)
5119 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5120 VariantClear(&v);
5121 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5122 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
5123 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
5124 if (V_VT(&v) == VT_EMPTY)
5125 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5126
5127 Accessible.role = 0;
5128 IRawElementProviderSimple_Release(elprov);
5129 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5130
5131 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5132 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5133 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5134
5135 /* UIA PropertyId's that correspond directly to individual MSAA state flags. */
5136 for (i = 0; i < ARRAY_SIZE(msaa_state_uia_props); i++)
5137 {
5139
5140 for (x = 0; x < 2; x++)
5141 {
5142 Accessible.state = x ? state->acc_state : ~state->acc_state;
5143 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5144 hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v);
5145 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5146 ok(check_variant_bool(&v, x), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
5147 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5148 }
5149
5150 /* Failure HRESULTs are passed through. */
5151 Accessible.state = 0;
5152 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5153 hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v);
5154 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5155 ok(V_VT(&v) == VT_EMPTY, "Unexpected V_VT %d\n", V_VT(&v));
5156 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5157 }
5158 Accessible.state = 0;
5159
5160 /*
5161 * UIA_IsOffscreenPropertyId relies upon either STATE_SYSTEM_OFFSCREEN
5162 * being set, or accLocation returning a location that is within the
5163 * client area bounding box of the HWND it is contained within.
5164 */
5165 set_accessible_props(&Accessible, 0, STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0);
5166 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5167 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5169 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5170 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5171 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5172
5173 /* accLocation fails, will return FALSE. */
5174 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0);
5175 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5176 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5177 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5178 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5179 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5180 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5181 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5182 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5183
5184 /* Window is visible, Accessible is within its bounds. */
5186 ok(GetClientRect(Accessible.ow_hwnd, &rect[0]), "GetClientRect returned FALSE\n");
5188
5190 (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top));
5191 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5192 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5193 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5195 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
5196 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5197 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5198 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5199
5200 /*
5201 * Window is invisible, Accessible is within its bounds. Window visibility
5202 * doesn't effect whether or not an IAccessible is considered offscreen.
5203 */
5206 (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top));
5207 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5208 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5209 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5210 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5211 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
5212 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5213 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5214 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5215
5216 /* Accessible now outside of its window's bounds. */
5218 10, 10);
5219 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5220 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5221 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5222 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5223 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5224 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5225 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5226 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5227
5228 /* Accessible within window bounds, but not client area bounds. */
5229 ok(GetWindowRect(Accessible.ow_hwnd, &rect[1]), "GetWindowRect returned FALSE\n");
5231 (rect[0].left - rect[1].left) - 1, (rect[0].top - rect[1].top) - 1);
5232
5233 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5234 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5235 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5237 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5238 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5239 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5240 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5241
5242 IRawElementProviderSimple_Release(elprov);
5243 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5244
5245 /* UIA_NamePropertyId tests. */
5246 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible", 0, 0, 0, 0);
5247 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5248 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5249 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5250
5251 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5252 VariantInit(&v);
5253 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
5254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5255 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
5256 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
5257 VariantClear(&v);
5258 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5259
5260 /* Name is not cached. */
5261 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible2", 0, 0, 0, 0);
5262 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5263 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
5264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5265 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
5266 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
5267 VariantClear(&v);
5268 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5269
5270 IRawElementProviderSimple_Release(elprov);
5271 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5272}
5273
5275{
5276 ILegacyIAccessibleProvider *accprov;
5277 IRawElementProviderSimple *elprov, *elprov2;
5278 IRawElementProviderFragment *elfrag;
5279 enum ProviderOptions prov_opt;
5280 struct UiaRect rect;
5281 IAccessible *acc;
5282 IUnknown *unk;
5283 WNDCLASSA cls;
5284 HRESULT hr;
5285 HWND hwnd;
5286 VARIANT v;
5287 INT cid;
5288
5290 cls.style = 0;
5292 cls.cbClsExtra = 0;
5293 cls.cbWndExtra = 0;
5295 cls.hIcon = 0;
5296 cls.hCursor = NULL;
5297 cls.hbrBackground = NULL;
5298 cls.lpszMenuName = NULL;
5299 cls.lpszClassName = "UiaProviderFromIAccessible class";
5300
5301 RegisterClassA(&cls);
5302
5303 hwnd = CreateWindowA("UiaProviderFromIAccessible class", "Test window", WS_OVERLAPPEDWINDOW,
5304 0, 0, 100, 100, NULL, NULL, NULL, NULL);
5305
5306 hr = pUiaProviderFromIAccessible(NULL, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5307 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5308
5309 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, NULL);
5310 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5311
5312 /*
5313 * UiaProviderFromIAccessible will not wrap an MSAA proxy, this is
5314 * detected by checking for the 'IIS_IsOleaccProxy' service from the
5315 * IServiceProvider interface.
5316 */
5317 hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
5318 ok(hr == S_OK, "got %#lx\n", hr);
5319 ok(!!acc, "acc == NULL\n");
5320
5321 hr = pUiaProviderFromIAccessible(acc, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5322 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5323 IAccessible_Release(acc);
5324
5325 /* Don't return an HWND from accNavigate or OleWindow. */
5326 SET_ACC_METHOD_EXPECT(&Accessible, accNavigate);
5327 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent);
5330 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5331 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5332 CHECK_ACC_METHOD_CALLED(&Accessible, accNavigate);
5333 CHECK_ACC_METHOD_CALLED(&Accessible, get_accParent);
5334
5335 /* Return an HWND from accNavigate, not OleWindow. */
5336 SET_ACC_METHOD_EXPECT(&Accessible, accNavigate);
5337 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5341 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5342 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5343 CHECK_ACC_METHOD_CALLED(&Accessible, accNavigate);
5344 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5345 IRawElementProviderSimple_Release(elprov);
5346 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5347 acc_client = NULL;
5348
5349 /* Skip tests on Win10v1507. */
5350 if (called_winproc_GETOBJECT_CLIENT)
5351 {
5352 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
5353 return;
5354 }
5355 expect_winproc_GETOBJECT_CLIENT = FALSE;
5356
5357 /* Return an HWND from parent IAccessible's IOleWindow interface. */
5359 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
5362 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5363 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5366 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
5367 IRawElementProviderSimple_Release(elprov);
5368 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
5369
5370 /* Return an HWND from OleWindow, not accNavigate. */
5373 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5375 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5376
5377 hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opt);
5378 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5380 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
5381 "Unexpected provider options %#x\n", prov_opt);
5382
5383 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
5384
5385 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ProviderDescriptionPropertyId, &v);
5386 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5387 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
5388 VariantClear(&v);
5389
5390 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
5391 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5392 ok(!!unk, "unk == NULL\n");
5393 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
5394
5395 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
5396 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5397 ok(!!accprov, "accprov == NULL\n");
5398
5399 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
5400 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5401 ok(cid == CHILDID_SELF, "cid != CHILDID_SELF\n");
5402
5403 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
5404 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5405 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
5406 IAccessible_Release(acc);
5407 IUnknown_Release(unk);
5408 ILegacyIAccessibleProvider_Release(accprov);
5409
5410 IRawElementProviderSimple_Release(elprov);
5411 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5412
5413 /* ChildID other than CHILDID_SELF. */
5414 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
5415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5416 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5417
5418 /* Even simple children implement IRawElementProviderFragmentRoot. */
5419 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
5420
5421 /*
5422 * Simple child element (IAccessible without CHILDID_SELF) cannot be root
5423 * IAccessible. No checks against the root HWND IAccessible will be done.
5424 */
5425 elprov2 = (void *)0xdeadbeef;
5426 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5427 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5428 ok(!elprov2, "elprov != NULL\n");
5429
5430 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
5431 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5432 ok(!!unk, "unk == NULL\n");
5433 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
5434
5435 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
5436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5437 ok(!!accprov, "accprov == NULL\n");
5438
5439 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
5440 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5441 ok(cid == 1, "cid != CHILDID_SELF\n");
5442
5443 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
5444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5445 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
5446 IAccessible_Release(acc);
5447 IUnknown_Release(unk);
5448 ILegacyIAccessibleProvider_Release(accprov);
5449
5450 IRawElementProviderSimple_Release(elprov);
5451 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5452
5453 /*
5454 * &Accessible.IAccessible_iface will be compared against the default
5455 * client accessible object. Since we have all properties set to 0,
5456 * we return failure HRESULTs and all properties will get queried but not
5457 * compared.
5458 */
5459 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5461 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5462
5463 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5464 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5465 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5466 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5467 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5468 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5469 elprov2 = (void *)0xdeadbeef;
5470 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5471 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5472 ok(!elprov2, "elprov != NULL\n");
5473 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5474 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5475 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5476 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5477 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5478 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5479
5480 /*
5481 * Interface that isn't the HWND root, still implements
5482 * IRawElementProviderFragmentRoot.
5483 */
5484 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
5485
5486 /* Second call won't send WM_GETOBJECT. */
5487 elprov2 = (void *)0xdeadbeef;
5488 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5490 ok(!elprov2, "elprov != NULL\n");
5491
5492 IRawElementProviderSimple_Release(elprov);
5493 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5494
5495 /*
5496 * Return &Accessible.IAccessible_iface in response to OBJID_CLIENT,
5497 * interface pointers will be compared, no method calls to check property
5498 * values.
5499 */
5500 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5502 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5503
5504 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5505 elprov2 = (void *)0xdeadbeef;
5507 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5509 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5510 IRawElementProviderSimple_Release(elprov2);
5511 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5512
5513 /* Second call, no checks. */
5514 elprov2 = (void *)0xdeadbeef;
5515 acc_client = NULL;
5516 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5517 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5518 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5519 IRawElementProviderSimple_Release(elprov2);
5520
5521 IRawElementProviderSimple_Release(elprov);
5522 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5523
5524 /*
5525 * Return &Accessible2.IAccessible_iface in response to OBJID_CLIENT,
5526 * interface pointers won't match, so properties will be compared.
5527 */
5528 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5529 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5530 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5531
5532 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
5533 L"acc_name", 0, 0, 50, 50);
5534 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
5535 L"acc_name", 0, 0, 50, 50);
5536
5537 acc_client = &Accessible2.IAccessible_iface;
5538 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5539 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5540 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5541 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5542 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5543 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5544 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5545 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5546 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5547 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
5548 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
5549 /*
5550 * The IAccessible returned by WM_GETOBJECT will be checked for an
5551 * IAccIdentity interface to see if Dynamic Annotation properties should
5552 * be queried. If not present on the current IAccessible, it will check
5553 * the parent IAccessible for one.
5554 */
5555 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5556 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5557 elprov2 = (void *)0xdeadbeef;
5558 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5559 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5560 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5561 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5562 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5563 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5564 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5565 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5566 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5567 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5568 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5569 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5570 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5571 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
5572 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
5575 IRawElementProviderSimple_Release(elprov2);
5576
5577 elprov2 = (void *)0xdeadbeef;
5578 acc_client = NULL;
5579 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5580 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5581 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5582 IRawElementProviderSimple_Release(elprov2);
5583
5584 IRawElementProviderSimple_Release(elprov);
5585 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5586
5587 /*
5588 * If a failure HRESULT is returned from the IRawElementProviderSimple
5589 * IAccessible, the corresponding AOFW IAccessible method isn't called.
5590 * An exception is get_accChildCount, which is always called, but only
5591 * checked if the HRESULT return value is not a failure. If Role/State/Name
5592 * are not queried, no IAccIdentity check is done.
5593 */
5594 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5596 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5597
5598 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
5599 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
5600 L"acc_name", 0, 0, 50, 50);
5601
5602 acc_client = &Accessible2.IAccessible_iface;
5603 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5604 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5605 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5606 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5607 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5608 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5609 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5610 elprov2 = (void *)0xdeadbeef;
5611 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5613 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5614 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5615 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5616 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5617 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5618 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5619 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5620 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5621
5622 acc_client = NULL;
5623 elprov2 = (void *)0xdeadbeef;
5624 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5626 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5627
5628 IRawElementProviderSimple_Release(elprov);
5629 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5630
5631 /*
5632 * Properties are checked in a sequence of accRole, accState,
5633 * accChildCount, accLocation, and finally accName. If a mismatch is found
5634 * early in the sequence, the rest aren't checked.
5635 */
5636 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5638 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5639
5640 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
5641 set_accessible_props(&Accessible2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
5642
5643 acc_client = &Accessible2.IAccessible_iface;
5644 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5645 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5646 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5647 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5648 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5649 elprov2 = (void *)0xdeadbeef;
5650 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5651 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5652 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5653 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5654 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5655 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5658
5659 elprov2 = (void *)0xdeadbeef;
5660 acc_client = NULL;
5661 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5662 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5663 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5664
5665 IRawElementProviderSimple_Release(elprov);
5666 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5667
5668 /* 4/5 properties match, considered a match. */
5669 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5671 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5672
5673 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
5674 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
5675
5676 acc_client = &Accessible2.IAccessible_iface;
5677 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5678 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5679 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5680 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5681 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5682 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5683 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5684 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5685 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5686 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
5687 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5688 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5689 elprov2 = (void *)0xdeadbeef;
5690 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5691 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5692 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5693 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5694 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5695 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5696 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5697 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5698 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5699 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5700 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5701 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5702 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5703 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
5706 IRawElementProviderSimple_Release(elprov2);
5707
5708 elprov2 = (void *)0xdeadbeef;
5709 acc_client = NULL;
5710 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5711 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5712 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5713 IRawElementProviderSimple_Release(elprov2);
5714
5715 IRawElementProviderSimple_Release(elprov);
5716 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5717
5718 /* 3/5 properties match, not considered a match. */
5719 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5720 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5721 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5722
5723 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
5724 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
5725
5726 acc_client = &Accessible2.IAccessible_iface;
5727 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5728 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5729 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5730 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5731 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5732 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5733 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5734 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5735 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5736 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5737 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5738 elprov2 = (void *)0xdeadbeef;
5739 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5740 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5741 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5742 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5743 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5744 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5745 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5746 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5747 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5748 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5749 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5750 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5753
5754 elprov2 = (void *)0xdeadbeef;
5755 acc_client = NULL;
5756 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5757 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5758 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5759
5760 IRawElementProviderSimple_Release(elprov);
5761 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5762
5763 /* Only name matches, considered a match. */
5764 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5766 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5767
5768 set_accessible_props(&Accessible, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
5769 set_accessible_props(&Accessible2, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
5770
5771 acc_client = &Accessible2.IAccessible_iface;
5772 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5773 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5774 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5775 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5776 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5777 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5778 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5779 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
5780 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5781 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5782 elprov2 = (void *)0xdeadbeef;
5783 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5785 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5786 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5787 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5788 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5789 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5790 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5791 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5792 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5793 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5794 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
5797 IRawElementProviderSimple_Release(elprov2);
5798
5799 elprov2 = (void *)0xdeadbeef;
5800 acc_client = NULL;
5801 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5802 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5803 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5804 IRawElementProviderSimple_Release(elprov2);
5805
5806 IRawElementProviderSimple_Release(elprov);
5807 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5808
5809 /*
5810 * Test IRawElementProviderFragment_get_BoundingRectangle.
5811 */
5812 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, L"acc_name", 25, 25, 50, 50);
5813 /* Test the case where Accessible is not the root for its HWND. */
5814 acc_client = NULL;
5815 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5816 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5817 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5818
5819 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
5820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5821 ok(!!elfrag, "elfrag == NULL\n");
5822
5823 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5824 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5825 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5826 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5827 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5828 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5829 ok(rect.left == (double)Accessible.left, "Unexpected left value %f\n", rect.left);
5830 ok(rect.top == (double)Accessible.top, "Unexpected top value %f\n", rect.top);
5831 ok(rect.width == (double)Accessible.width, "Unexpected width value %f\n", rect.width);
5832 ok(rect.height == (double)Accessible.height, "Unexpected height value %f\n", rect.height);
5833 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5834 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5835 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5836 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5837
5838 /* If Accessible has STATE_SYSTEM_OFFSCREEN, it will return an empty rect. */
5839 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_OFFSCREEN, 0, L"acc_name", 0, 0, 50, 50);
5840 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5841 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5842 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5843 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5844 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5845 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5846 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5847 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5848
5849 IRawElementProviderFragment_Release(elfrag);
5850 IRawElementProviderSimple_Release(elprov);
5851 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5852
5853 /* Test case where accessible is the root accessible. */
5854 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
5856 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5858 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5859
5860 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
5861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5862 ok(!!elfrag, "elfrag == NULL\n");
5863
5864 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5865 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5866 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5867 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5868 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5869 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5870 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5871 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5872
5873 /* Second call does nothing. */
5874 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5875 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5876 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5877 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5878 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5879 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5880
5881 IRawElementProviderFragment_Release(elfrag);
5882 IRawElementProviderSimple_Release(elprov);
5883 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5884 acc_client = NULL;
5885
5891
5894 UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
5897}
5898
5900 const GUID *guid;
5901 int id;
5902};
5903
5905 { &RuntimeId_Property_GUID, UIA_RuntimeIdPropertyId },
5906 { &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId },
5907 { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId },
5908 { &ControlType_Property_GUID, UIA_ControlTypePropertyId },
5909 { &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId },
5910 { &Name_Property_GUID, UIA_NamePropertyId },
5911 { &AcceleratorKey_Property_GUID, UIA_AcceleratorKeyPropertyId },
5912 { &AccessKey_Property_GUID, UIA_AccessKeyPropertyId },
5913 { &HasKeyboardFocus_Property_GUID, UIA_HasKeyboardFocusPropertyId },
5914 { &IsKeyboardFocusable_Property_GUID, UIA_IsKeyboardFocusablePropertyId },
5915 { &IsEnabled_Property_GUID, UIA_IsEnabledPropertyId },
5916 { &AutomationId_Property_GUID, UIA_AutomationIdPropertyId },
5917 { &ClassName_Property_GUID, UIA_ClassNamePropertyId },
5918 { &HelpText_Property_GUID, UIA_HelpTextPropertyId },
5919 { &ClickablePoint_Property_GUID, UIA_ClickablePointPropertyId },
5920 { &Culture_Property_GUID, UIA_CulturePropertyId },
5921 { &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId },
5922 { &IsContentElement_Property_GUID, UIA_IsContentElementPropertyId },
5923 { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId },
5924 { &IsPassword_Property_GUID, UIA_IsPasswordPropertyId },
5925 { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId },
5926 { &ItemType_Property_GUID, UIA_ItemTypePropertyId },
5927 { &IsOffscreen_Property_GUID, UIA_IsOffscreenPropertyId },
5928 { &Orientation_Property_GUID, UIA_OrientationPropertyId },
5929 { &FrameworkId_Property_GUID, UIA_FrameworkIdPropertyId },
5930 { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId },
5931 { &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId },
5932 { &IsDockPatternAvailable_Property_GUID, UIA_IsDockPatternAvailablePropertyId },
5933 { &IsExpandCollapsePatternAvailable_Property_GUID, UIA_IsExpandCollapsePatternAvailablePropertyId },
5934 { &IsGridItemPatternAvailable_Property_GUID, UIA_IsGridItemPatternAvailablePropertyId },
5935 { &IsGridPatternAvailable_Property_GUID, UIA_IsGridPatternAvailablePropertyId },
5936 { &IsInvokePatternAvailable_Property_GUID, UIA_IsInvokePatternAvailablePropertyId },
5937 { &IsMultipleViewPatternAvailable_Property_GUID, UIA_IsMultipleViewPatternAvailablePropertyId },
5938 { &IsRangeValuePatternAvailable_Property_GUID, UIA_IsRangeValuePatternAvailablePropertyId },
5939 { &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId },
5940 { &IsScrollItemPatternAvailable_Property_GUID, UIA_IsScrollItemPatternAvailablePropertyId },
5941 { &IsSelectionItemPatternAvailable_Property_GUID, UIA_IsSelectionItemPatternAvailablePropertyId },
5942 { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId },
5943 { &IsTablePatternAvailable_Property_GUID, UIA_IsTablePatternAvailablePropertyId },
5944 { &IsTableItemPatternAvailable_Property_GUID, UIA_IsTableItemPatternAvailablePropertyId },
5945 { &IsTextPatternAvailable_Property_GUID, UIA_IsTextPatternAvailablePropertyId },
5946 { &IsTogglePatternAvailable_Property_GUID, UIA_IsTogglePatternAvailablePropertyId },
5947 { &IsTransformPatternAvailable_Property_GUID, UIA_IsTransformPatternAvailablePropertyId },
5948 { &IsValuePatternAvailable_Property_GUID, UIA_IsValuePatternAvailablePropertyId },
5949 { &IsWindowPatternAvailable_Property_GUID, UIA_IsWindowPatternAvailablePropertyId },
5950 { &Value_Value_Property_GUID, UIA_ValueValuePropertyId },
5951 { &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId },
5952 { &RangeValue_Value_Property_GUID, UIA_RangeValueValuePropertyId },
5953 { &RangeValue_IsReadOnly_Property_GUID, UIA_RangeValueIsReadOnlyPropertyId },
5954 { &RangeValue_Minimum_Property_GUID, UIA_RangeValueMinimumPropertyId },
5955 { &RangeValue_Maximum_Property_GUID, UIA_RangeValueMaximumPropertyId },
5956 { &RangeValue_LargeChange_Property_GUID, UIA_RangeValueLargeChangePropertyId },
5957 { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId },
5958 { &Scroll_HorizontalScrollPercent_Property_GUID, UIA_ScrollHorizontalScrollPercentPropertyId },
5959 { &Scroll_HorizontalViewSize_Property_GUID, UIA_ScrollHorizontalViewSizePropertyId },
5960 { &Scroll_VerticalScrollPercent_Property_GUID, UIA_ScrollVerticalScrollPercentPropertyId },
5961 { &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId },
5962 { &Scroll_HorizontallyScrollable_Property_GUID, UIA_ScrollHorizontallyScrollablePropertyId },
5963 { &Scroll_VerticallyScrollable_Property_GUID, UIA_ScrollVerticallyScrollablePropertyId },
5964 { &Selection_Selection_Property_GUID, UIA_SelectionSelectionPropertyId },
5965 { &Selection_CanSelectMultiple_Property_GUID, UIA_SelectionCanSelectMultiplePropertyId },
5966 { &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId },
5967 { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId },
5968 { &Grid_ColumnCount_Property_GUID, UIA_GridColumnCountPropertyId },
5969 { &GridItem_Row_Property_GUID, UIA_GridItemRowPropertyId },
5970 { &GridItem_Column_Property_GUID, UIA_GridItemColumnPropertyId },
5971 { &GridItem_RowSpan_Property_GUID, UIA_GridItemRowSpanPropertyId },
5972 { &GridItem_ColumnSpan_Property_GUID, UIA_GridItemColumnSpanPropertyId },
5973 { &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId },
5974 { &Dock_DockPosition_Property_GUID, UIA_DockDockPositionPropertyId },
5975 { &ExpandCollapse_ExpandCollapseState_Property_GUID, UIA_ExpandCollapseExpandCollapseStatePropertyId },
5976 { &MultipleView_CurrentView_Property_GUID, UIA_MultipleViewCurrentViewPropertyId },
5977 { &MultipleView_SupportedViews_Property_GUID, UIA_MultipleViewSupportedViewsPropertyId },
5978 { &Window_CanMaximize_Property_GUID, UIA_WindowCanMaximizePropertyId },
5979 { &Window_CanMinimize_Property_GUID, UIA_WindowCanMinimizePropertyId },
5980 { &Window_WindowVisualState_Property_GUID, UIA_WindowWindowVisualStatePropertyId },
5981 { &Window_WindowInteractionState_Property_GUID, UIA_WindowWindowInteractionStatePropertyId },
5982 { &Window_IsModal_Property_GUID, UIA_WindowIsModalPropertyId },
5983 { &Window_IsTopmost_Property_GUID, UIA_WindowIsTopmostPropertyId },
5984 { &SelectionItem_IsSelected_Property_GUID, UIA_SelectionItemIsSelectedPropertyId },
5985 { &SelectionItem_SelectionContainer_Property_GUID, UIA_SelectionItemSelectionContainerPropertyId },
5986 { &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId },
5987 { &Table_ColumnHeaders_Property_GUID, UIA_TableColumnHeadersPropertyId },
5988 { &Table_RowOrColumnMajor_Property_GUID, UIA_TableRowOrColumnMajorPropertyId },
5989 { &TableItem_RowHeaderItems_Property_GUID, UIA_TableItemRowHeaderItemsPropertyId },
5990 { &TableItem_ColumnHeaderItems_Property_GUID, UIA_TableItemColumnHeaderItemsPropertyId },
5991 { &Toggle_ToggleState_Property_GUID, UIA_ToggleToggleStatePropertyId },
5992 { &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId },
5993 { &Transform_CanResize_Property_GUID, UIA_TransformCanResizePropertyId },
5994 { &Transform_CanRotate_Property_GUID, UIA_TransformCanRotatePropertyId },
5995 { &IsLegacyIAccessiblePatternAvailable_Property_GUID, UIA_IsLegacyIAccessiblePatternAvailablePropertyId },
5996 { &LegacyIAccessible_ChildId_Property_GUID, UIA_LegacyIAccessibleChildIdPropertyId },
5997 { &LegacyIAccessible_Name_Property_GUID, UIA_LegacyIAccessibleNamePropertyId },
5998 { &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId },
5999 { &LegacyIAccessible_Description_Property_GUID, UIA_LegacyIAccessibleDescriptionPropertyId },
6000 { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId },
6001 { &LegacyIAccessible_State_Property_GUID, UIA_LegacyIAccessibleStatePropertyId },
6002 { &LegacyIAccessible_Help_Property_GUID, UIA_LegacyIAccessibleHelpPropertyId },
6003 { &LegacyIAccessible_KeyboardShortcut_Property_GUID, UIA_LegacyIAccessibleKeyboardShortcutPropertyId },
6004 { &LegacyIAccessible_Selection_Property_GUID, UIA_LegacyIAccessibleSelectionPropertyId },
6005 { &LegacyIAccessible_DefaultAction_Property_GUID, UIA_LegacyIAccessibleDefaultActionPropertyId },
6006 { &AriaRole_Property_GUID, UIA_AriaRolePropertyId },
6007 { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId },
6008 { &IsDataValidForForm_Property_GUID, UIA_IsDataValidForFormPropertyId },
6009 { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId },
6010 { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId },
6011 { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId },
6012 { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId },
6013 { &IsItemContainerPatternAvailable_Property_GUID, UIA_IsItemContainerPatternAvailablePropertyId },
6014 { &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId },
6015 { &IsSynchronizedInputPatternAvailable_Property_GUID, UIA_IsSynchronizedInputPatternAvailablePropertyId },
6016 /* Implemented on Win8+ */
6017 { &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId },
6018 { &IsObjectModelPatternAvailable_Property_GUID, UIA_IsObjectModelPatternAvailablePropertyId },
6019 { &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId },
6020 { &Annotation_AnnotationTypeName_Property_GUID, UIA_AnnotationAnnotationTypeNamePropertyId },
6021 { &Annotation_Author_Property_GUID, UIA_AnnotationAuthorPropertyId },
6022 { &Annotation_DateTime_Property_GUID, UIA_AnnotationDateTimePropertyId },
6023 { &Annotation_Target_Property_GUID, UIA_AnnotationTargetPropertyId },
6024 { &IsAnnotationPatternAvailable_Property_GUID, UIA_IsAnnotationPatternAvailablePropertyId },
6025 { &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId },
6026 { &Styles_StyleId_Property_GUID, UIA_StylesStyleIdPropertyId },
6027 { &Styles_StyleName_Property_GUID, UIA_StylesStyleNamePropertyId },
6028 { &Styles_FillColor_Property_GUID, UIA_StylesFillColorPropertyId },
6029 { &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId },
6030 { &Styles_Shape_Property_GUID, UIA_StylesShapePropertyId },
6031 { &Styles_FillPatternColor_Property_GUID, UIA_StylesFillPatternColorPropertyId },
6032 { &Styles_ExtendedProperties_Property_GUID, UIA_StylesExtendedPropertiesPropertyId },
6033 { &IsStylesPatternAvailable_Property_GUID, UIA_IsStylesPatternAvailablePropertyId },
6034 { &IsSpreadsheetPatternAvailable_Property_GUID, UIA_IsSpreadsheetPatternAvailablePropertyId },
6035 { &SpreadsheetItem_Formula_Property_GUID, UIA_SpreadsheetItemFormulaPropertyId },
6036 { &SpreadsheetItem_AnnotationObjects_Property_GUID, UIA_SpreadsheetItemAnnotationObjectsPropertyId },
6037 { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId },
6038 { &IsSpreadsheetItemPatternAvailable_Property_GUID, UIA_IsSpreadsheetItemPatternAvailablePropertyId },
6039 { &Transform2_CanZoom_Property_GUID, UIA_Transform2CanZoomPropertyId },
6040 { &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId },
6041 { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId },
6042 { &IsTextChildPatternAvailable_Property_GUID, UIA_IsTextChildPatternAvailablePropertyId },
6043 { &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId },
6044 { &Drag_IsGrabbed_Property_GUID, UIA_DragIsGrabbedPropertyId },
6045 { &Drag_DropEffect_Property_GUID, UIA_DragDropEffectPropertyId },
6046 { &Drag_DropEffects_Property_GUID, UIA_DragDropEffectsPropertyId },
6047 { &IsDropTargetPatternAvailable_Property_GUID, UIA_IsDropTargetPatternAvailablePropertyId },
6048 { &DropTarget_DropTargetEffect_Property_GUID, UIA_DropTargetDropTargetEffectPropertyId },
6049 { &DropTarget_DropTargetEffects_Property_GUID, UIA_DropTargetDropTargetEffectsPropertyId },
6050 { &Drag_GrabbedItems_Property_GUID, UIA_DragGrabbedItemsPropertyId },
6051 { &Transform2_ZoomLevel_Property_GUID, UIA_Transform2ZoomLevelPropertyId },
6052 { &Transform2_ZoomMinimum_Property_GUID, UIA_Transform2ZoomMinimumPropertyId },
6053 { &Transform2_ZoomMaximum_Property_GUID, UIA_Transform2ZoomMaximumPropertyId },
6054 { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId },
6055 { &IsTextEditPatternAvailable_Property_GUID, UIA_IsTextEditPatternAvailablePropertyId },
6056 { &IsPeripheral_Property_GUID, UIA_IsPeripheralPropertyId },
6057 /* Implemented on Win10v1507+. */
6058 { &IsCustomNavigationPatternAvailable_Property_GUID, UIA_IsCustomNavigationPatternAvailablePropertyId },
6059 { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId },
6060 { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId },
6061 { &Level_Property_GUID, UIA_LevelPropertyId },
6062 { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId },
6063 { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId },
6064 /* Implemented on Win10v1809+. */
6065 { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId },
6066 { &LocalizedLandmarkType_Property_GUID, UIA_LocalizedLandmarkTypePropertyId },
6067 { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId },
6068 { &FillColor_Property_GUID, UIA_FillColorPropertyId },
6069 { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId },
6070 { &FillType_Property_GUID, UIA_FillTypePropertyId },
6071 { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId },
6072 { &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId },
6073 { &CenterPoint_Property_GUID, UIA_CenterPointPropertyId },
6074 { &Rotation_Property_GUID, UIA_RotationPropertyId },
6075 { &Size_Property_GUID, UIA_SizePropertyId },
6076 { &IsSelectionPattern2Available_Property_GUID, UIA_IsSelectionPattern2AvailablePropertyId },
6077 { &Selection2_FirstSelectedItem_Property_GUID, UIA_Selection2FirstSelectedItemPropertyId },
6078 { &Selection2_LastSelectedItem_Property_GUID, UIA_Selection2LastSelectedItemPropertyId },
6079 { &Selection2_CurrentSelectedItem_Property_GUID, UIA_Selection2CurrentSelectedItemPropertyId },
6080 { &Selection2_ItemCount_Property_GUID, UIA_Selection2ItemCountPropertyId },
6081 { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId },
6082 { &IsDialog_Property_GUID, UIA_IsDialogPropertyId },
6083};
6084
6085static const struct uia_lookup_id uia_event_lookup_ids[] = {
6086 { &ToolTipOpened_Event_GUID, UIA_ToolTipOpenedEventId },
6087 { &ToolTipClosed_Event_GUID, UIA_ToolTipClosedEventId },
6088 { &StructureChanged_Event_GUID, UIA_StructureChangedEventId },
6089 { &MenuOpened_Event_GUID, UIA_MenuOpenedEventId },
6090 { &AutomationPropertyChanged_Event_GUID, UIA_AutomationPropertyChangedEventId },
6091 { &AutomationFocusChanged_Event_GUID, UIA_AutomationFocusChangedEventId },
6092 { &AsyncContentLoaded_Event_GUID, UIA_AsyncContentLoadedEventId },
6093 { &MenuClosed_Event_GUID, UIA_MenuClosedEventId },
6094 { &LayoutInvalidated_Event_GUID, UIA_LayoutInvalidatedEventId },
6095 { &Invoke_Invoked_Event_GUID, UIA_Invoke_InvokedEventId },
6096 { &SelectionItem_ElementAddedToSelectionEvent_Event_GUID, UIA_SelectionItem_ElementAddedToSelectionEventId },
6097 { &SelectionItem_ElementRemovedFromSelectionEvent_Event_GUID, UIA_SelectionItem_ElementRemovedFromSelectionEventId },
6098 { &SelectionItem_ElementSelectedEvent_Event_GUID, UIA_SelectionItem_ElementSelectedEventId },
6099 { &Selection_InvalidatedEvent_Event_GUID, UIA_Selection_InvalidatedEventId },
6100 { &Text_TextSelectionChangedEvent_Event_GUID, UIA_Text_TextSelectionChangedEventId },
6101 { &Text_TextChangedEvent_Event_GUID, UIA_Text_TextChangedEventId },
6102 { &Window_WindowOpened_Event_GUID, UIA_Window_WindowOpenedEventId },
6103 { &Window_WindowClosed_Event_GUID, UIA_Window_WindowClosedEventId },
6104 { &MenuModeStart_Event_GUID, UIA_MenuModeStartEventId },
6105 { &MenuModeEnd_Event_GUID, UIA_MenuModeEndEventId },
6106 { &InputReachedTarget_Event_GUID, UIA_InputReachedTargetEventId },
6107 { &InputReachedOtherElement_Event_GUID, UIA_InputReachedOtherElementEventId },
6108 { &InputDiscarded_Event_GUID, UIA_InputDiscardedEventId },
6109 /* Implemented on Win8+ */
6110 { &SystemAlert_Event_GUID, UIA_SystemAlertEventId },
6111 { &LiveRegionChanged_Event_GUID, UIA_LiveRegionChangedEventId },
6112 { &HostedFragmentRootsInvalidated_Event_GUID, UIA_HostedFragmentRootsInvalidatedEventId },
6113 { &Drag_DragStart_Event_GUID, UIA_Drag_DragStartEventId },
6114 { &Drag_DragCancel_Event_GUID, UIA_Drag_DragCancelEventId },
6115 { &Drag_DragComplete_Event_GUID, UIA_Drag_DragCompleteEventId },
6116 { &DropTarget_DragEnter_Event_GUID, UIA_DropTarget_DragEnterEventId },
6117 { &DropTarget_DragLeave_Event_GUID, UIA_DropTarget_DragLeaveEventId },
6118 { &DropTarget_Dropped_Event_GUID, UIA_DropTarget_DroppedEventId },
6119 { &TextEdit_TextChanged_Event_GUID, UIA_TextEdit_TextChangedEventId },
6120 { &TextEdit_ConversionTargetChanged_Event_GUID, UIA_TextEdit_ConversionTargetChangedEventId },
6121 /* Implemented on Win10v1809+. */
6122 { &Changes_Event_GUID, UIA_ChangesEventId },
6123 { &Notification_Event_GUID, UIA_NotificationEventId },
6124};
6125
6126static const struct uia_lookup_id uia_pattern_lookup_ids[] = {
6127 { &Invoke_Pattern_GUID, UIA_InvokePatternId },
6128 { &Selection_Pattern_GUID, UIA_SelectionPatternId },
6129 { &Value_Pattern_GUID, UIA_ValuePatternId },
6130 { &RangeValue_Pattern_GUID, UIA_RangeValuePatternId },
6131 { &Scroll_Pattern_GUID, UIA_ScrollPatternId },
6132 { &ExpandCollapse_Pattern_GUID, UIA_ExpandCollapsePatternId },
6133 { &Grid_Pattern_GUID, UIA_GridPatternId },
6134 { &GridItem_Pattern_GUID, UIA_GridItemPatternId },
6135 { &MultipleView_Pattern_GUID, UIA_MultipleViewPatternId },
6136 { &Window_Pattern_GUID, UIA_WindowPatternId },
6137 { &SelectionItem_Pattern_GUID, UIA_SelectionItemPatternId },
6138 { &Dock_Pattern_GUID, UIA_DockPatternId },
6139 { &Table_Pattern_GUID, UIA_TablePatternId },
6140 { &TableItem_Pattern_GUID, UIA_TableItemPatternId },
6141 { &Text_Pattern_GUID, UIA_TextPatternId },
6142 { &Toggle_Pattern_GUID, UIA_TogglePatternId },
6143 { &Transform_Pattern_GUID, UIA_TransformPatternId },
6144 { &ScrollItem_Pattern_GUID, UIA_ScrollItemPatternId },
6145 { &LegacyIAccessible_Pattern_GUID, UIA_LegacyIAccessiblePatternId },
6146 { &ItemContainer_Pattern_GUID, UIA_ItemContainerPatternId },
6147 { &VirtualizedItem_Pattern_GUID, UIA_VirtualizedItemPatternId },
6148 { &SynchronizedInput_Pattern_GUID, UIA_SynchronizedInputPatternId },
6149 /* Implemented on Win8+ */
6150 { &ObjectModel_Pattern_GUID, UIA_ObjectModelPatternId },
6151 { &Annotation_Pattern_GUID, UIA_AnnotationPatternId },
6152 { &Text_Pattern2_GUID, UIA_TextPattern2Id },
6153 { &Styles_Pattern_GUID, UIA_StylesPatternId },
6154 { &Spreadsheet_Pattern_GUID, UIA_SpreadsheetPatternId },
6155 { &SpreadsheetItem_Pattern_GUID, UIA_SpreadsheetItemPatternId },
6156 { &Tranform_Pattern2_GUID, UIA_TransformPattern2Id },
6157 { &TextChild_Pattern_GUID, UIA_TextChildPatternId },
6158 { &Drag_Pattern_GUID, UIA_DragPatternId },
6159 { &DropTarget_Pattern_GUID, UIA_DropTargetPatternId },
6160 { &TextEdit_Pattern_GUID, UIA_TextEditPatternId },
6161 /* Implemented on Win10+. */
6162 { &CustomNavigation_Pattern_GUID, UIA_CustomNavigationPatternId },
6163};
6164
6166 { &Button_Control_GUID, UIA_ButtonControlTypeId },
6167 { &Calendar_Control_GUID, UIA_CalendarControlTypeId },
6168 { &CheckBox_Control_GUID, UIA_CheckBoxControlTypeId },
6169 { &ComboBox_Control_GUID, UIA_ComboBoxControlTypeId },
6170 { &Edit_Control_GUID, UIA_EditControlTypeId },
6171 { &Hyperlink_Control_GUID, UIA_HyperlinkControlTypeId },
6172 { &Image_Control_GUID, UIA_ImageControlTypeId },
6173 { &ListItem_Control_GUID, UIA_ListItemControlTypeId },
6174 { &List_Control_GUID, UIA_ListControlTypeId },
6175 { &Menu_Control_GUID, UIA_MenuControlTypeId },
6176 { &MenuBar_Control_GUID, UIA_MenuBarControlTypeId },
6177 { &MenuItem_Control_GUID, UIA_MenuItemControlTypeId },
6178 { &ProgressBar_Control_GUID, UIA_ProgressBarControlTypeId },
6179 { &RadioButton_Control_GUID, UIA_RadioButtonControlTypeId },
6180 { &ScrollBar_Control_GUID, UIA_ScrollBarControlTypeId },
6181 { &Slider_Control_GUID, UIA_SliderControlTypeId },
6182 { &Spinner_Control_GUID, UIA_SpinnerControlTypeId },
6183 { &StatusBar_Control_GUID, UIA_StatusBarControlTypeId },
6184 { &Tab_Control_GUID, UIA_TabControlTypeId },
6185 { &TabItem_Control_GUID, UIA_TabItemControlTypeId },
6186 { &Text_Control_GUID, UIA_TextControlTypeId },
6187 { &ToolBar_Control_GUID, UIA_ToolBarControlTypeId },
6188 { &ToolTip_Control_GUID, UIA_ToolTipControlTypeId },
6189 { &Tree_Control_GUID, UIA_TreeControlTypeId },
6190 { &TreeItem_Control_GUID, UIA_TreeItemControlTypeId },
6191 { &Custom_Control_GUID, UIA_CustomControlTypeId },
6192 { &Group_Control_GUID, UIA_GroupControlTypeId },
6193 { &Thumb_Control_GUID, UIA_ThumbControlTypeId },
6194 { &DataGrid_Control_GUID, UIA_DataGridControlTypeId },
6195 { &DataItem_Control_GUID, UIA_DataItemControlTypeId },
6196 { &Document_Control_GUID, UIA_DocumentControlTypeId },
6197 { &SplitButton_Control_GUID, UIA_SplitButtonControlTypeId },
6198 { &Window_Control_GUID, UIA_WindowControlTypeId },
6199 { &Pane_Control_GUID, UIA_PaneControlTypeId },
6200 { &Header_Control_GUID, UIA_HeaderControlTypeId },
6201 { &HeaderItem_Control_GUID, UIA_HeaderItemControlTypeId },
6202 { &Table_Control_GUID, UIA_TableControlTypeId },
6203 { &TitleBar_Control_GUID, UIA_TitleBarControlTypeId },
6204 { &Separator_Control_GUID, UIA_SeparatorControlTypeId },
6205 /* Implemented on Win8+ */
6206 { &SemanticZoom_Control_GUID, UIA_SemanticZoomControlTypeId },
6207 { &AppBar_Control_GUID, UIA_AppBarControlTypeId },
6208};
6209
6210static void test_UiaLookupId(void)
6211{
6212 static const struct {
6213 const char *id_type_name;
6214 int id_type;
6215 const struct uia_lookup_id *ids;
6216 int ids_count;
6217 } tests[] =
6218 {
6223 };
6224 unsigned int i, y;
6225
6226 for (i = 0; i < ARRAY_SIZE(tests); i++)
6227 {
6228 for (y = 0; y < tests[i].ids_count; y++)
6229 {
6230 int id = UiaLookupId(tests[i].id_type, tests[i].ids[y].guid);
6231
6232 if (!id)
6233 {
6234 win_skip("No %s id for GUID %s, skipping further tests.\n", tests[i].id_type_name, debugstr_guid(tests[i].ids[y].guid));
6235 break;
6236 }
6237
6238 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);
6239 }
6240 }
6241}
6242
6243static const struct prov_method_sequence node_from_prov1[] = {
6245 { 0 }
6246};
6247
6248static const struct prov_method_sequence node_from_prov2[] = {
6250 /* Win10v1507 and below call this. */
6251 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6253 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6254 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6255 /* Only called on Windows versions past Win10v1507. */
6257 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6258 { 0 }
6259};
6260
6261static const struct prov_method_sequence node_from_prov3[] = {
6263 /* Win10v1507 and below call this. */
6264 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6266 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6267 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6268 /* Only called on Windows versions past Win10v1507. */
6270 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6271 { 0 }
6272};
6273
6274static const struct prov_method_sequence node_from_prov4[] = {
6276 /* Win10v1507 and below call this. */
6277 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6279 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6280 /* Only called on Windows versions past Win10v1507. */
6282 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6283 { 0 }
6284};
6285
6286static const struct prov_method_sequence node_from_prov5[] = {
6288 /* Win10v1507 and below call this. */
6289 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6292 /* Win10v1507 and below call this. */
6293 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6295 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6296 /* These three are only done on Win10v1507 and below. */
6299 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6300 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6301 /* This is only done on Win10v1507. */
6303 /* Only called on Windows versions past Win10v1507. */
6305 /* Win10v1507 and below call this. */
6306 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
6307 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6308 { 0 }
6309};
6310
6311static const struct prov_method_sequence node_from_prov6[] = {
6313 /* Win10v1507 and below call this. */
6314 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6317 /* Win10v1507 and below call this. */
6318 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6320 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6323 /* Only called on Windows versions past Win10v1507. */
6325 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6326 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6327 /* This is only done on Win10v1507. */
6329 /* Only called on Windows versions past Win10v1507. */
6331 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6332 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6333 { 0 }
6334};
6335
6336static const struct prov_method_sequence node_from_prov7[] = {
6338 /* Win10v1507 and below call this. */
6339 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6342 /* Win10v1507 and below call this. */
6343 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6345 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6348 /* Only called on Windows versions past Win10v1507. */
6350 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6351 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6352 /* This is only done on Win10v1507. */
6354 /* Only called on Windows versions past Win10v1507. */
6356 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6357 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6358 { 0 }
6359};
6360
6361static const struct prov_method_sequence node_from_prov8[] = {
6363 /* Win10v1507 and below call this. */
6364 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6366 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6367 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6368 /* Only called on Windows versions past Win10v1507. */
6370 { 0 }
6371};
6372
6373static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com);
6375{
6376 HUIANODE node = param;
6377 HRESULT hr;
6378 VARIANT v;
6379
6380 /*
6381 * Since this is a node representing an IRawElementProviderSimple with
6382 * ProviderOptions_UseComThreading set, it is only usable in threads that
6383 * have initialized COM.
6384 */
6385 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
6386 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
6387
6389
6390 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
6391 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6392 check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v, FALSE);
6393
6394 /*
6395 * When retrieving a UIAutomationType_Element property, if UseComThreading
6396 * is set, we'll get an HUIANODE that will make calls inside of the
6397 * apartment of the node it is retrieved from. I.e, if we received a node
6398 * with UseComThreading set from another node with UseComThreading set
6399 * inside of an STA, the returned node will have all of its methods called
6400 * from the STA thread.
6401 */
6403 Provider_child.expected_tid = Provider.expected_tid;
6404 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6405 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6406 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
6407
6408 /* Unset ProviderOptions_UseComThreading. */
6410 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6411 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6412
6413 /*
6414 * ProviderOptions_UseComThreading not set, GetPropertyValue will be
6415 * called on the current thread.
6416 */
6417 Provider_child.expected_tid = GetCurrentThreadId();
6418 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
6419
6421
6422 return 0;
6423}
6424
6426{
6427 HANDLE thread;
6428 HUIANODE node;
6429 HRESULT hr;
6430
6431 /* Test ProviderOptions_UseComThreading. */
6432 Provider.hwnd = NULL;
6433 prov_root = NULL;
6436 ok_method_sequence(node_from_prov8, "node_from_prov8");
6437
6438 /*
6439 * On Windows versions prior to Windows 10, UiaNodeFromProvider ignores the
6440 * ProviderOptions_UseComThreading flag.
6441 */
6442 if (hr == S_OK)
6443 {
6444 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
6446 return;
6447 }
6448 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx.\n", hr);
6449
6452 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6453 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6454 ok_method_sequence(node_from_prov8, "node_from_prov8");
6455
6459 {
6460 MSG msg;
6461 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
6462 {
6465 }
6466 }
6468
6469 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6470 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6471 Provider_child.expected_tid = Provider.expected_tid = 0;
6472
6474}
6476{
6477 WNDCLASSA cls;
6478 HUIANODE node;
6479 HRESULT hr;
6480 ULONG ref;
6481 HWND hwnd;
6482 VARIANT v;
6483
6484 cls.style = 0;
6486 cls.cbClsExtra = 0;
6487 cls.cbWndExtra = 0;
6489 cls.hIcon = 0;
6490 cls.hCursor = NULL;
6491 cls.hbrBackground = NULL;
6492 cls.lpszMenuName = NULL;
6493 cls.lpszClassName = "UiaNodeFromProvider class";
6494
6495 RegisterClassA(&cls);
6496
6497 hwnd = CreateWindowA("UiaNodeFromProvider class", "Test window", WS_OVERLAPPEDWINDOW,
6498 0, 0, 100, 100, NULL, NULL, NULL, NULL);
6499
6500 /* Run these tests early, we end up in an implicit MTA later. */
6502
6504
6506 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6507
6509 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6510
6511 /* Must have a successful call to get_ProviderOptions. */
6512 Provider.prov_opts = 0;
6513 node = (void *)0xdeadbeef;
6515 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
6516 ok(!node, "node != NULL\n");
6517 ok_method_sequence(node_from_prov1, "node_from_prov1");
6518
6519 /* No HWND exposed through Provider. */
6521 node = (void *)0xdeadbeef;
6523 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6524
6525 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6526 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6528 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
6529 VariantClear(&v);
6530
6531 ok_method_sequence(node_from_prov2, "node_from_prov2");
6532
6533 /* HUIANODE represents a COM interface. */
6534 ref = IUnknown_AddRef((IUnknown *)node);
6535 ok(ref == 2, "Unexpected refcnt %ld\n", ref);
6536
6537 ref = IUnknown_AddRef((IUnknown *)node);
6538 ok(ref == 3, "Unexpected refcnt %ld\n", ref);
6539
6540 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6541
6542 ref = IUnknown_Release((IUnknown *)node);
6543 ok(ref == 1, "Unexpected refcnt %ld\n", ref);
6544
6545 ref = IUnknown_Release((IUnknown *)node);
6546 ok(ref == 0, "Unexpected refcnt %ld\n", ref);
6547 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6548
6549 /*
6550 * No HWND exposed through Provider_child, but it returns a parent from
6551 * NavigateDirection_Parent. Behavior doesn't change.
6552 */
6554 node = (void *)0xdeadbeef;
6555 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
6556 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6557
6558 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6559 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6561 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6562 VariantClear(&v);
6563
6564 ok_method_sequence(node_from_prov3, "node_from_prov3");
6565 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6566 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6567
6568 /* HWND exposed, but Provider2 not returned from WM_GETOBJECT. */
6569 Provider.hwnd = hwnd;
6570 prov_root = NULL;
6571 node = (void *)0xdeadbeef;
6572 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6573 /* Win10v1507 and below send this, Windows 7 sends it twice. */
6574 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
6577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6578 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6579 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6580 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6581
6582 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6583 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6585 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
6588 VariantClear(&v);
6589
6591 ok_method_sequence(node_from_prov4, "node_from_prov4");
6592
6593 ok(!!node, "node == NULL\n");
6594 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6595 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6596
6597 /*
6598 * Provider is our main provider, since Provider2 is also a main, it won't
6599 * get added.
6600 */
6601 Provider.hwnd = Provider2.hwnd = hwnd;
6603 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = TRUE;
6604 prov_root = &Provider2.IRawElementProviderSimple_iface;
6605 node = (void *)0xdeadbeef;
6606 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6607 /* Windows 7 sends this. */
6608 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6610 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6611 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6612 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6613
6614 /* Win10v1507 and below hold a reference to the root provider for the HWND */
6615 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6616 ok(!!node, "node == NULL\n");
6617
6618 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6619 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6621 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
6624 VariantClear(&v);
6625
6626 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = FALSE;
6627 ok_method_sequence(node_from_prov5, "node_from_prov5");
6628
6629 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6630 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6631 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6632
6633 /*
6634 * Provider is classified as an Hwnd provider, Provider2 will become our
6635 * Main provider since we don't have one already.
6636 */
6639 prov_root = &Provider2.IRawElementProviderSimple_iface;
6640 node = (void *)0xdeadbeef;
6641 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6642 /* Windows 7 sends this. */
6643 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6645 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6646 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6647 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6648
6649 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6650 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6652 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
6654 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
6655 VariantClear(&v);
6656
6657 ok_method_sequence(node_from_prov6, "node_from_prov6");
6658
6659 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
6660 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6661
6662 ok(!!node, "node == NULL\n");
6663 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6664 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6665 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6666
6667 /* Provider_child has a parent, so it will be "(parent link)". */
6669 Provider_child.hwnd = hwnd;
6671 prov_root = &Provider2.IRawElementProviderSimple_iface;
6672 node = (void *)0xdeadbeef;
6673 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6674 /* Windows 7 sends this. */
6675 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6676 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
6677 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6678 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6679 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6680
6681 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6682 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6684 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", FALSE);
6686 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_child", TRUE);
6687 VariantClear(&v);
6688
6689 ok_method_sequence(node_from_prov7, "node_from_prov7");
6690
6691 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
6692 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6693
6694 ok(!!node, "node == NULL\n");
6695 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6696 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6697 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6698
6701 UnregisterClassA("UiaNodeFromProvider class", NULL);
6702 prov_root = NULL;
6703}
6704
6705/* Sequence for types other than UIAutomationType_Element. */
6706static const struct prov_method_sequence get_prop_seq[] = {
6708 { 0 }
6709};
6710
6711/* Sequence for getting a property that returns an invalid type. */
6714 /* Windows 7 calls this. */
6716 { 0 }
6717};
6718
6719/* UIAutomationType_Element sequence. */
6723 /* Win10v1507 and below call this. */
6724 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6726 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6727 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6728 /* Only called on Windows versions past Win10v1507. */
6731 { 0 }
6732};
6733
6734/* UIAutomationType_ElementArray sequence. */
6738 /* Win10v1507 and below call this. */
6739 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6741 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6742 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6745 /* Win10v1507 and below call this. */
6746 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6748 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6749 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6753 { 0 }
6754};
6755
6758 { 0 }
6759};
6760
6764 { 0 }
6765};
6766
6770 /*
6771 * Win10v21H2+ and above call these, attempting to get the fragment root's
6772 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6773 */
6776 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6778 { 0 }
6779};
6780
6785 /*
6786 * Win10v21H2+ and above call these, attempting to get the fragment root's
6787 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6788 */
6791 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6793 { 0 }
6794};
6795
6798 /*
6799 * Win10v21H2+ and above call these, attempting to get the fragment root's
6800 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6801 */
6804 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6806 { 0 }
6807};
6808
6811 { 0 }
6812};
6813
6814static void set_uia_rect(struct UiaRect *rect, double left, double top, double width, double height)
6815{
6816 rect->left = left;
6817 rect->top = top;
6818 rect->width = width;
6819 rect->height = height;
6820}
6821
6822#define check_uia_rect_val( v, rect ) \
6823 check_uia_rect_val_( (v), (rect), __FILE__, __LINE__)
6824static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *file, int line)
6825{
6826 LONG lbound, ubound, elems, idx;
6827 SAFEARRAY *sa;
6828 double tmp[4];
6829 VARTYPE vt;
6830 HRESULT hr;
6831 UINT dims;
6832
6833 ok_(file, line)(V_VT(v) == (VT_R8 | VT_ARRAY), "Unexpected rect VT hr %d.\n", V_VT(v));
6834 if (V_VT(v) != (VT_R8 | VT_ARRAY))
6835 return;
6836
6837 sa = V_ARRAY(v);
6839 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6840 ok_(file, line)(vt == VT_R8, "Unexpected vt %d\n", vt);
6841
6842 dims = SafeArrayGetDim(sa);
6843 ok_(file, line)(dims == 1, "Unexpected dims %d\n", dims);
6844
6845 lbound = ubound = elems = 0;
6846 hr = SafeArrayGetLBound(sa, 1, &lbound);
6847 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
6848 ok_(file, line)(lbound == 0, "Unexpected lbound %ld\n", lbound);
6849
6850 hr = SafeArrayGetUBound(sa, 1, &ubound);
6851 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
6852 ok_(file, line)(ubound == 3, "Unexpected ubound %ld\n", ubound);
6853
6854 elems = (ubound - lbound) + 1;
6855 ok_(file, line)(elems == 4, "Unexpected rect elems %ld\n", elems);
6856
6857 for (idx = 0; idx < ARRAY_SIZE(tmp); idx++)
6858 {
6859 hr = SafeArrayGetElement(sa, &idx, &tmp[idx]);
6860 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetElement at idx %ld.\n", hr, idx);
6861 }
6862
6863 ok_(file, line)(tmp[0] == rect->left, "Unexpected left value %f, expected %f\n", tmp[0], rect->left);
6864 ok_(file, line)(tmp[1] == rect->top, "Unexpected top value %f, expected %f\n", tmp[1], rect->top);
6865 ok_(file, line)(tmp[2] == rect->width, "Unexpected width value %f, expected %f\n", tmp[2], rect->width);
6866 ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height);
6867}
6868
6869#define check_uia_rect_rect_val( rect, uia_rect ) \
6870 check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__)
6871static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line)
6872{
6873 ok_(file, line)(rect->left == (LONG)uia_rect->left, "Unexpected left value %ld, expected %ld\n", rect->left, (LONG)uia_rect->left);
6874 ok_(file, line)(rect->top == (LONG)uia_rect->top, "Unexpected top value %ld, expected %ld\n", rect->top, (LONG)uia_rect->top);
6875 ok_(file, line)(rect->right == (LONG)(uia_rect->left + uia_rect->width), "Unexpected right value %ld, expected %ld\n", rect->right,
6876 (LONG)(uia_rect->left + uia_rect->width));
6877 ok_(file, line)(rect->bottom == (LONG)(uia_rect->top + uia_rect->height), "Unexpected bottom value %ld, expected %ld\n", rect->bottom,
6878 (LONG)(uia_rect->top + uia_rect->height));
6879}
6880
6881static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com)
6882{
6883 LONG idx;
6884
6885 switch (type)
6886 {
6887 case UIAutomationType_String:
6888 ok(V_VT(v) == VT_BSTR, "Unexpected VT %d\n", V_VT(v));
6889 ok(!lstrcmpW(V_BSTR(v), uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(v)));
6891 break;
6892
6893 case UIAutomationType_Bool:
6894 ok(V_VT(v) == VT_BOOL, "Unexpected VT %d\n", V_VT(v));
6895
6896 /* UIA_IsKeyboardFocusablePropertyId is broken on Win8 and Win10v1507. */
6897 if (prop_id == UIA_IsKeyboardFocusablePropertyId)
6899 "Unexpected BOOL %#x\n", V_BOOL(v));
6900 else
6901 ok(check_variant_bool(v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(v));
6903 break;
6904
6905 case UIAutomationType_Int:
6906 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
6907
6908 if (prop_id == UIA_NativeWindowHandlePropertyId)
6909 ok(ULongToHandle(V_I4(v)) == Provider.hwnd, "Unexpected I4 %#lx\n", V_I4(v));
6910 else
6911 ok(V_I4(v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(v));
6913 break;
6914
6915 case UIAutomationType_IntArray:
6916 ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v));
6917
6918 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
6919 {
6920 ULONG val;
6921
6923 ok(val == uia_i4_arr_prop_val[idx], "Unexpected I4 %#lx at idx %ld\n", val, idx);
6924 }
6926 break;
6927
6928 case UIAutomationType_Double:
6929 ok(V_VT(v) == VT_R8, "Unexpected VT %d\n", V_VT(v));
6930 ok(V_R8(v) == uia_r8_prop_val, "Unexpected R8 %lf\n", V_R8(v));
6932 break;
6933
6934 case UIAutomationType_DoubleArray:
6935 ok(V_VT(v) == (VT_ARRAY | VT_R8), "Unexpected VT %d\n", V_VT(v));
6936 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
6937 {
6938 double val;
6939
6941 ok(val == uia_r8_arr_prop_val[idx], "Unexpected R8 %lf at idx %ld\n", val, idx);
6942 }
6944 break;
6945
6946 case UIAutomationType_Element:
6947 {
6948 HUIANODE tmp_node;
6949 HRESULT hr;
6950 VARIANT v1;
6951
6952 if (from_com)
6953 {
6954 IUIAutomationElement *elem;
6955
6956 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
6957 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElement, (void **)&elem);
6958 VariantClear(v);
6959 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6960 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6961
6962 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_ControlTypePropertyId, TRUE, &v1);
6963 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6964 IUIAutomationElement_Release(elem);
6965 }
6966 else
6967 {
6968#ifdef _WIN64
6969 ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
6970 tmp_node = (HUIANODE)V_I8(v);
6971#else
6972 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
6973 tmp_node = (HUIANODE)V_I4(v);
6974#endif
6975 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6976
6977 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
6978 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6979 ok(UiaNodeRelease(tmp_node), "Failed to release node\n");
6980 }
6981
6982 ok(V_VT(&v1) == VT_I4, "Unexpected VT %d\n", V_VT(&v1));
6983 ok(V_I4(&v1) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v1));
6984 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6985
6987 break;
6988 }
6989
6990 case UIAutomationType_ElementArray:
6991 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6992 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
6993 if (from_com)
6994 {
6995 IUIAutomationElementArray *elem_arr = NULL;
6996 HRESULT hr;
6997 int len;
6998
6999 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
7000 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
7001 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7002 ok(!!elem_arr, "elem_arr == NULL\n");
7003 if (!elem_arr)
7004 {
7005 VariantClear(v);
7006 break;
7007 }
7008
7009 hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
7010 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7011 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
7012
7013 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
7014 {
7015 IUIAutomationElement *tmp_elem = NULL;
7016 VARIANT v1;
7017
7018 hr = IUIAutomationElementArray_GetElement(elem_arr, idx, &tmp_elem);
7019 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7020 ok(!!tmp_elem, "tmp_elem == NULL\n");
7021
7022 hr = IUIAutomationElement_GetCurrentPropertyValueEx(tmp_elem, UIA_ControlTypePropertyId, TRUE, &v1);
7023 ok(hr == S_OK, "elem[%ld] Unexpected hr %#lx\n", idx, hr);
7024 ok(V_VT(&v1) == VT_I4, "elem[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
7025 ok(V_I4(&v1) == uia_i4_prop_val, "elem[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
7026
7027 IUIAutomationElement_Release(tmp_elem);
7028 VariantClear(&v1);
7029 }
7030
7031 IUIAutomationElementArray_Release(elem_arr);
7032 }
7033 else
7034 {
7035 ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v));
7036 if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN))
7037 break;
7038
7039 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
7040 {
7041 HUIANODE tmp_node;
7042 HRESULT hr;
7043 VARIANT v1;
7044
7045 SafeArrayGetElement(V_ARRAY(v), &idx, &tmp_node);
7046
7047 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
7048 ok(hr == S_OK, "node[%ld] Unexpected hr %#lx\n", idx, hr);
7049 ok(V_VT(&v1) == VT_I4, "node[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
7050 ok(V_I4(&v1) == uia_i4_prop_val, "node[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
7051
7052 ok(UiaNodeRelease(tmp_node), "Failed to release node[%ld]\n", idx);
7053 VariantClear(&v1);
7054 }
7055 }
7056
7057 VariantClear(v);
7058 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7059 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
7061 break;
7062
7063 default:
7064 break;
7065 }
7066
7067 VariantClear(v);
7068 V_VT(v) = VT_EMPTY;
7069}
7070
7073 enum UIAutomationType type;
7075};
7076
7078 { &ProcessId_Property_GUID, UIAutomationType_Int, TRUE },
7079 { &ControlType_Property_GUID, UIAutomationType_Int },
7080 { &LocalizedControlType_Property_GUID, UIAutomationType_String, TRUE },
7081 { &Name_Property_GUID, UIAutomationType_String },
7082 { &AcceleratorKey_Property_GUID, UIAutomationType_String },
7083 { &AccessKey_Property_GUID, UIAutomationType_String },
7084 { &HasKeyboardFocus_Property_GUID, UIAutomationType_Bool },
7085 { &IsKeyboardFocusable_Property_GUID, UIAutomationType_Bool },
7086 { &IsEnabled_Property_GUID, UIAutomationType_Bool },
7087 { &AutomationId_Property_GUID, UIAutomationType_String },
7088 { &ClassName_Property_GUID, UIAutomationType_String },
7089 { &HelpText_Property_GUID, UIAutomationType_String },
7090 { &Culture_Property_GUID, UIAutomationType_Int },
7091 { &IsControlElement_Property_GUID, UIAutomationType_Bool },
7092 { &IsContentElement_Property_GUID, UIAutomationType_Bool },
7093 { &LabeledBy_Property_GUID, UIAutomationType_Element },
7094 { &IsPassword_Property_GUID, UIAutomationType_Bool },
7095 { &NewNativeWindowHandle_Property_GUID, UIAutomationType_Int },
7096 { &ItemType_Property_GUID, UIAutomationType_String },
7097 { &IsOffscreen_Property_GUID, UIAutomationType_Bool },
7098 { &Orientation_Property_GUID, UIAutomationType_Int },
7099 { &FrameworkId_Property_GUID, UIAutomationType_String },
7100 { &IsRequiredForForm_Property_GUID, UIAutomationType_Bool },
7101 { &ItemStatus_Property_GUID, UIAutomationType_String },
7102 { &AriaRole_Property_GUID, UIAutomationType_String },
7103 { &AriaProperties_Property_GUID, UIAutomationType_String },
7104 { &IsDataValidForForm_Property_GUID, UIAutomationType_Bool },
7105 { &ControllerFor_Property_GUID, UIAutomationType_ElementArray },
7106 { &DescribedBy_Property_GUID, UIAutomationType_ElementArray },
7107 { &FlowsTo_Property_GUID, UIAutomationType_ElementArray },
7108 /* Implemented on Win8+ */
7109 { &OptimizeForVisualContent_Property_GUID, UIAutomationType_Bool },
7110 { &LiveSetting_Property_GUID, UIAutomationType_Int },
7111 { &FlowsFrom_Property_GUID, UIAutomationType_ElementArray },
7112 { &IsPeripheral_Property_GUID, UIAutomationType_Bool },
7113 /* Implemented on Win10v1507+. */
7114 { &PositionInSet_Property_GUID, UIAutomationType_Int },
7115 { &SizeOfSet_Property_GUID, UIAutomationType_Int },
7116 { &Level_Property_GUID, UIAutomationType_Int },
7117 { &AnnotationTypes_Property_GUID, UIAutomationType_IntArray },
7118 { &AnnotationObjects_Property_GUID, UIAutomationType_ElementArray },
7119 /* Implemented on Win10v1809+. */
7120 { &LandmarkType_Property_GUID, UIAutomationType_Int },
7121 { &LocalizedLandmarkType_Property_GUID, UIAutomationType_String, TRUE },
7122 { &FullDescription_Property_GUID, UIAutomationType_String },
7123 { &FillColor_Property_GUID, UIAutomationType_Int },
7124 { &OutlineColor_Property_GUID, UIAutomationType_IntArray },
7125 { &FillType_Property_GUID, UIAutomationType_Int },
7126 { &VisualEffects_Property_GUID, UIAutomationType_Int },
7127 { &OutlineThickness_Property_GUID, UIAutomationType_DoubleArray },
7128 { &Rotation_Property_GUID, UIAutomationType_Double },
7129 { &Size_Property_GUID, UIAutomationType_DoubleArray },
7130 { &HeadingLevel_Property_GUID, UIAutomationType_Int },
7131 { &IsDialog_Property_GUID, UIAutomationType_Bool },
7132};
7133
7135{
7136 const struct uia_element_property *elem_prop;
7137 struct UiaRect rect;
7138 IUnknown *unk_ns;
7139 unsigned int i;
7140 HUIANODE node;
7141 int prop_id;
7142 HRESULT hr;
7143 VARIANT v;
7144
7146
7150 node = (void *)0xdeadbeef;
7152 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7153 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7155
7157 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7158
7159 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
7160 {
7161 elem_prop = &element_properties[i];
7162
7164 VariantClear(&v);
7166 if (!prop_id)
7167 {
7168 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
7169 break;
7170 }
7171 winetest_push_context("prop_id %d", prop_id);
7172 hr = UiaGetPropertyValue(node, prop_id, &v);
7173 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7174 check_uia_prop_val(prop_id, elem_prop->type, &v, FALSE);
7175
7176 /*
7177 * Some properties have special behavior if an invalid value is
7178 * returned, skip them here.
7179 */
7180 if (!elem_prop->skip_invalid)
7181 {
7183 hr = UiaGetPropertyValue(node, prop_id, &v);
7184 if (hr == E_NOTIMPL)
7185 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7186 else
7187 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7188 if (SUCCEEDED(hr))
7189 {
7191 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7192 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7193 VariantClear(&v);
7194 }
7195 }
7196
7198 }
7199
7200 /* IValueProvider pattern property IDs. */
7201 Provider.value_pattern_data.is_supported = FALSE;
7202 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
7203 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7204 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7205 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7207 VariantClear(&v);
7208
7209 Provider.value_pattern_data.is_supported = TRUE;
7210 for (i = 0; i < 2; i++)
7211 {
7212 Provider.value_pattern_data.is_read_only = i;
7213
7214 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
7215 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7216 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
7217 ok(check_variant_bool(&v, i), "Unexpected BOOL %#x\n", V_BOOL(&v));
7219 VariantClear(&v);
7220 }
7221
7222 /* ILegacyIAccessibleProvider pattern property IDs. */
7223 Provider.legacy_acc_pattern_data.is_supported = FALSE;
7224 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v);
7225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7226 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7227 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7229 VariantClear(&v);
7230
7231 Provider.legacy_acc_pattern_data.is_supported = TRUE;
7232 for (i = 0; i < 2; i++)
7233 {
7235
7236 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v);
7237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7238 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7239 ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v));
7241 VariantClear(&v);
7242 }
7243
7244 for (i = 0; i < 2; i++)
7245 {
7247
7248 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleRolePropertyId, &v);
7249 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7250 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7251 ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v));
7253 VariantClear(&v);
7254 }
7255
7256 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7257 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
7259
7260 /*
7261 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
7262 * It's the only version with this behavior.
7263 */
7264 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
7265 {
7266 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
7267 goto exit;
7268 }
7269
7271 node = (void *)0xdeadbeef;
7272 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
7273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7274 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7275
7276 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
7277 set_uia_rect(&rect, 0, 0, 50, 50);
7278 Provider_child.bounds_rect = rect;
7279 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
7280 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7282 VariantClear(&v);
7283
7284 ok_method_sequence(get_bounding_rect_seq, "get_bounding_rect_seq");
7285
7286 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
7287 set_uia_rect(&rect, 0, 0, 0, 0);
7288 Provider_child.bounds_rect = rect;
7289 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
7290 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7291 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7292 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7293 VariantClear(&v);
7294 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
7295
7296 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7297 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7299
7300exit:
7301
7302 IUnknown_Release(unk_ns);
7304}
7305
7306static const struct prov_method_sequence get_runtime_id1[] = {
7308 { 0 }
7309};
7310
7311static const struct prov_method_sequence get_runtime_id2[] = {
7314 { 0 }
7315};
7316
7317static const struct prov_method_sequence get_runtime_id3[] = {
7321 /* Not called on Windows 7. */
7322 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7323 /* Only called on Win8+. */
7326 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7328 { 0 }
7329};
7330
7331static const struct prov_method_sequence get_runtime_id4[] = {
7335 /* Not called on Windows 7. */
7336 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7337 /* These methods are only called on Win8+. */
7341 { 0 }
7342};
7343
7344static const struct prov_method_sequence get_runtime_id5[] = {
7349 { 0 }
7350};
7351
7352static void test_UiaGetRuntimeId(void)
7353{
7356 int rt_id[4], tmp, i;
7357 IUnknown *unk_ns;
7358 SAFEARRAY *sa;
7359 WNDCLASSA cls;
7360 HUIANODE node;
7361 HRESULT hr;
7362 HWND hwnd;
7363 VARIANT v;
7364
7365 VariantInit(&v);
7366 cls.style = 0;
7368 cls.cbClsExtra = 0;
7369 cls.cbWndExtra = 0;
7371 cls.hIcon = 0;
7372 cls.hCursor = NULL;
7373 cls.hbrBackground = NULL;
7374 cls.lpszMenuName = NULL;
7375 cls.lpszClassName = "UiaGetRuntimeId class";
7376
7377 RegisterClassA(&cls);
7378
7379 hwnd = CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW,
7380 0, 0, 100, 100, NULL, NULL, NULL, NULL);
7381
7383 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7384
7387 Provider.hwnd = Provider2.hwnd = Provider_child.hwnd = NULL;
7388 node = (void *)0xdeadbeef;
7389 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
7390 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7391 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7392
7393 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7394 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7396 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
7397 VariantClear(&v);
7398
7400
7401 /* NULL runtime ID. */
7402 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0;
7403 sa = (void *)0xdeadbeef;
7405 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7406 ok(!sa, "sa != NULL\n");
7407 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
7408
7409 /* No UiaAppendRuntimeId prefix, returns GetRuntimeId array directly. */
7410 Provider_child.runtime_id[0] = rt_id[0] = 5;
7411 Provider_child.runtime_id[1] = rt_id[1] = 2;
7412 sa = (void *)0xdeadbeef;
7414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7415 ok(!!sa, "sa == NULL\n");
7416 check_runtime_id(rt_id, 2, sa);
7418 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
7419
7420 /*
7421 * If a provider returns a RuntimeId beginning with the constant
7422 * UiaAppendRuntimeId, UI Automation will add a prefix based on the
7423 * providers HWND fragment root before returning to the client. The added
7424 * prefix is 3 int values, with:
7425 *
7426 * idx[0] always being 42. (UIA_RUNTIME_ID_PREFIX)
7427 * idx[1] always being the HWND.
7428 * idx[2] has three different values depending on what type of provider
7429 * the fragment root is. Fragment roots can be an override provider, a
7430 * nonclient provider, or a main provider.
7431 */
7432 Provider_child.frag_root = NULL;
7433 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7434 Provider_child.runtime_id[1] = 2;
7435 sa = (void *)0xdeadbeef;
7436
7437 /* Provider_child has no fragment root for UiaAppendRuntimeId. */
7439 /* Windows 7 returns S_OK. */
7440 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
7441 ok(!sa, "sa != NULL\n");
7442 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
7443
7444 /*
7445 * UIA_RuntimeIdPropertyId won't return a failure code from
7446 * UiaGetPropertyValue.
7447 */
7448 hr = UiaGetPropertyValue(node, UIA_RuntimeIdPropertyId, &v);
7449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7450 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7451 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7452 VariantClear(&v);
7453 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
7454
7455 /*
7456 * Provider_child returns a fragment root that doesn't expose an HWND. On
7457 * Win8+, fragment roots are navigated recursively until either a NULL
7458 * fragment root is returned, the same fragment root as the current one is
7459 * returned, or a fragment root with an HWND is returned.
7460 */
7463 Provider2.hwnd = NULL;
7464 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
7465 Provider.hwnd = NULL;
7466 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7467 Provider_child.runtime_id[1] = 2;
7468 sa = (void *)0xdeadbeef;
7470 /* Windows 7 returns S_OK. */
7471 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
7472 ok(!sa, "sa != NULL\n");
7473 ok_method_sequence(get_runtime_id3, "get_runtime_id3");
7474
7475 /* Provider2 returns an HWND. */
7476 Provider.hwnd = NULL;
7477 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
7478 Provider2.hwnd = hwnd;
7480 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7481 Provider_child.runtime_id[1] = rt_id[3] = 2;
7482 sa = NULL;
7484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7485 /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */
7486 ok(!!sa || broken(!sa), "sa == NULL\n");
7488
7489 ok_method_sequence(get_runtime_id4, "get_runtime_id4");
7490
7491 /* Test RuntimeId values for different root fragment provider types. */
7493 Provider.hwnd = hwnd;
7494 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7495 Provider_child.runtime_id[1] = rt_id[3] = 2;
7496 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
7497 rt_id[1] = HandleToULong(hwnd);
7498 for (i = 0; i < ARRAY_SIZE(root_prov_opts); i++)
7499 {
7500 LONG lbound;
7501
7502 Provider.prov_opts = root_prov_opts[i];
7503 sa = NULL;
7505 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7506 ok(!!sa, "sa == NULL\n");
7507
7508 hr = SafeArrayGetLBound(sa, 1, &lbound);
7509 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
7510
7511 lbound = lbound + 2;
7512 hr = SafeArrayGetElement(sa, &lbound, &tmp);
7513 ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
7514 if (i)
7515 ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n");
7516
7517 rt_id[2] = tmp;
7518 check_runtime_id(rt_id, 4, sa);
7519
7521 ok_method_sequence(get_runtime_id5, "get_runtime_id5");
7522 }
7523
7525
7526 /* Test behavior on a node with an associated HWND. */
7529 Provider.hwnd = Provider2.hwnd = hwnd;
7530 prov_root = &Provider2.IRawElementProviderSimple_iface;
7531 node = (void *)0xdeadbeef;
7532 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7533 /* Windows 7 sends this. */
7534 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7536 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7537 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7538 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7539
7540 VariantInit(&v);
7541 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7542 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7544 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
7546 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
7547 VariantClear(&v);
7548
7549 ok_method_sequence(node_from_prov6, "node_from_prov6");
7550
7551 /* No methods called, RuntimeId is based on the node's HWND. */
7553 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7554 ok(!!sa, "sa == NULL\n");
7555 ok(!sequence_cnt, "Unexpected sequence_cnt %d\n", sequence_cnt);
7556
7557 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
7558 rt_id[1] = HandleToULong(hwnd);
7559 check_runtime_id(rt_id, 2, sa);
7562
7564 UnregisterClassA("UiaGetRuntimeId class", NULL);
7566}
7567
7570 { 0 },
7571};
7572
7574{
7575 HUIANODE node, node2;
7576 ULONG node_ref;
7577 HRESULT hr;
7578 VARIANT v;
7579
7581 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7582
7584 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7585
7586 node = (void *)0xdeadbeef;
7587 V_VT(&v) = VT_R8;
7589 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7590 ok(!node, "node != NULL\n");
7591
7592 node = NULL;
7595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7596 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7597 ok(!!node, "node == NULL\n");
7598 ok_method_sequence(node_from_var_seq, "node_from_var_seq");
7599
7600 node2 = (void *)0xdeadbeef;
7601 V_VT(&v) = VT_UNKNOWN;
7602 V_UNKNOWN(&v) = (IUnknown *)node;
7603 hr = UiaHUiaNodeFromVariant(&v, &node2);
7604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7605 ok(node == node2, "node != NULL\n");
7606
7607 node_ref = IUnknown_AddRef((IUnknown *)node);
7608 ok(node_ref == 3, "Unexpected node_ref %ld\n", node_ref);
7609 VariantClear(&v);
7610 IUnknown_Release((IUnknown *)node);
7611
7612#ifdef _WIN64
7613 node2 = (void *)0xdeadbeef;
7614 V_VT(&v) = VT_I4;
7615 V_I4(&v) = 0xbeefdead;
7616 hr = UiaHUiaNodeFromVariant(&v, &node2);
7617 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7618 ok(!node2, "node2 != NULL\n");
7619
7620 node2 = (void *)0xdeadbeef;
7621 V_VT(&v) = VT_I8;
7622 V_I8(&v) = (UINT64)node;
7623 hr = UiaHUiaNodeFromVariant(&v, &node2);
7624 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7625 ok(node2 == (void *)V_I8(&v), "node2 != V_I8\n");
7626#else
7627 node2 = (void *)0xdeadbeef;
7628 V_VT(&v) = VT_I8;
7629 V_I8(&v) = 0xbeefdead;
7630 hr = UiaHUiaNodeFromVariant(&v, &node2);
7631 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7632 ok(!node2, "node2 != NULL\n");
7633
7634 node2 = (void *)0xdeadbeef;
7635 V_VT(&v) = VT_I4;
7636 V_I4(&v) = (UINT32)node;
7637 hr = UiaHUiaNodeFromVariant(&v, &node2);
7638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7639 ok(node2 == (void *)V_I4(&v), "node2 != V_I4\n");
7640#endif
7641
7643}
7644
7645static const struct prov_method_sequence node_from_hwnd1[] = {
7647 { 0 }
7648};
7649
7650static const struct prov_method_sequence node_from_hwnd2[] = {
7652 /* Win10v1507 and below call this. */
7653 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7655 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7658 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7659 /* Windows 10+ calls this. */
7661 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7662 { 0 }
7663};
7664
7665static const struct prov_method_sequence node_from_hwnd3[] = {
7668 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7669 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
7673 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7674 { 0 }
7675};
7676
7677static const struct prov_method_sequence node_from_hwnd4[] = {
7680 /* Win10v1507 and below call this. */
7681 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7683 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7684 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7685 /* Only called on Windows versions past Win10v1507. */
7687 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7688 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7689 { 0 }
7690};
7691
7692static const struct prov_method_sequence node_from_hwnd5[] = {
7693 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
7695 /* Win10v1507 and below call this. */
7696 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7698 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7699 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7701 /* Only done in Windows 8+. */
7704 /* These two are only done on Windows 7. */
7706 { &Provider_child, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7707 { 0 }
7708};
7709
7710static const struct prov_method_sequence node_from_hwnd6[] = {
7713 /* Win10v1507 and below call this. */
7714 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7716 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7717 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7719 /* Next 4 are only done in Windows 8+. */
7725 /* Next two are only done on Win10v1809+. */
7728 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7729 /* Next two are only done on Win10v1809+. */
7732 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7733 { 0 }
7734};
7735
7736static const struct prov_method_sequence node_from_hwnd7[] = {
7739 /* Win10v1507 and below call this. */
7740 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7742 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7746 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7748 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7751 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7752 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7753 { 0 }
7754};
7755
7756static const struct prov_method_sequence node_from_hwnd8[] = {
7759 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7760 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
7764 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7765 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7766 { 0 }
7767};
7768
7769static const struct prov_method_sequence node_from_hwnd9[] = {
7771 /* Win10v1507 and below call this. */
7772 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7774 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7775 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7777 /* Only done in Windows 8+. */
7780 /* These three are only done on Windows 7. */
7782 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7783 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
7784 { 0 }
7785};
7786
7789 /* Next two only done on Windows 8+. */
7793 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win11+. */
7794 { 0 }
7795};
7796
7799 /* Win10v1507 and below call this. */
7800 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7802 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7803 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7809 { 0 }
7810};
7811
7814 /* Win10v1507 and below call this. */
7815 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7817 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7818 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7822 { 0 }
7823};
7824
7827 /* Win10v1507 and below call this. */
7828 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7830 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7831 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7834 { 0 }
7835};
7836
7839 /* Win10v1507 and below call this. */
7840 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7842 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7844 { 0 }
7845};
7846
7848{
7849 APTTYPEQUALIFIER apt_qualifier;
7850 APTTYPE apt_type;
7851 WCHAR buf[2048];
7852 HUIANODE node;
7853 HRESULT hr;
7854 DWORD pid;
7855 HWND hwnd;
7856 VARIANT v;
7857
7858 hwnd = FindWindowA("UiaNodeFromHandle class", "Test window");
7859
7860 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7861 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
7862
7864 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7865
7866 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7867 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7868
7869 memset(buf, 0, sizeof(buf));
7871 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7873 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7877
7878 VariantClear(&v);
7879
7880 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7881 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7882 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
7883 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7884
7885 /*
7886 * On Windows 8 and above, if a node contains a nested provider, the
7887 * process will be in an implicit MTA until the node is released.
7888 */
7889 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7890 ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
7891 if (SUCCEEDED(hr))
7892 {
7893 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7894 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7895 }
7896
7898
7899 /* Node released, we're out of the implicit MTA. */
7900 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7901
7902 /* Windows 10v1709-1809 are stuck in an implicit MTA. */
7903 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
7904 if (SUCCEEDED(hr))
7905 {
7906 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7907 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7908 }
7909}
7910
7912{
7913 HUIANODE node, node2, node3;
7914 HWND hwnd = (HWND)param;
7915 WCHAR buf[2048];
7916 HRESULT hr;
7917 VARIANT v;
7918
7920
7921 /* Only sent twice on Windows 11. */
7922 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
7923 /* Only sent on Win7. */
7924 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7927 Provider.hwnd = hwnd;
7933 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7934 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
7935 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7936 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7937
7938 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7939 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7940
7941 memset(buf, 0, sizeof(buf));
7942 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7944 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7948
7949 VariantClear(&v);
7950
7952 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
7953
7954 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7955 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7956 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
7957
7958 /*
7959 * On Windows, nested providers are always called on a separate thread if
7960 * UseComThreading isn't set. Since we're doing COM marshaling, if we're
7961 * currently in an MTA, we just call the nested provider from the current
7962 * thread.
7963 */
7965 Provider.last_call_tid != GetWindowThreadProcessId(hwnd, NULL), "Expected method call on separate thread\n");
7966
7967 /*
7968 * Elements returned from nested providers have to be able to get a
7969 * RuntimeId, or else we'll get E_FAIL on Win8+.
7970 */
7972 Provider_child.expected_tid = Provider.expected_tid;
7973 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7974 Provider_child.runtime_id[1] = 2;
7975 Provider_child.frag_root = NULL;
7976 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7977 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
7978 if (SUCCEEDED(hr))
7979 {
7980 hr = UiaHUiaNodeFromVariant(&v, &node2);
7981 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7982 UiaNodeRelease(node2);
7983 }
7984
7985 ok_method_sequence(node_from_hwnd5, "node_from_hwnd5");
7986
7987 /* RuntimeId check succeeds, we'll get a nested node. */
7989 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7990 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7991 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7992
7993 hr = UiaHUiaNodeFromVariant(&v, &node2);
7994 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7995 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
7996 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7997
7998 /*
7999 * Even though this is a nested node, without any additional
8000 * providers, it will not have the 'Nested' prefix.
8001 */
8003 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8004 VariantClear(&v);
8005
8006 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8007 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8008 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8009 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8010 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
8011
8012 UiaNodeRelease(node2);
8013
8014 /*
8015 * There is a delay between nested nodes being released and the
8016 * corresponding IRawElementProviderSimple release on newer Windows
8017 * versions.
8018 */
8019 if (Provider_child.ref != 1)
8020 Sleep(50);
8021 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8022
8023 /*
8024 * Returned nested elements with an HWND will have client-side providers
8025 * added to them.
8026 */
8027 Provider_child.hwnd = hwnd;
8028 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8029 /* Only sent on Win7. */
8030 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8031 Provider_child.ignore_hwnd_prop = TRUE;
8032 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8033 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8034 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8035 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8036 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
8037
8038 hr = UiaHUiaNodeFromVariant(&v, &node2);
8039 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8040 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
8041 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8042
8043 memset(buf, 0, sizeof(buf));
8044 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", TRUE, buf), "Failed to get nested provider description\n");
8045
8047 check_node_provider_desc(buf, L"Main", L"Provider_child", TRUE);
8048
8052 VariantClear(&v);
8053
8054 Provider_child.ignore_hwnd_prop = FALSE;
8055 ok_method_sequence(node_from_hwnd7, "node_from_hwnd7");
8056 UiaNodeRelease(node2);
8057
8058 if (Provider_child.ref != 1)
8059 Sleep(50);
8060 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8061
8062 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8063 /* Win10v1809 can be slow to call Release on Provider. */
8064 if (Provider.ref != 1)
8065 Sleep(50);
8066 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8067
8068 /* ProviderOptions_UseComThreading test from a separate thread. */
8069 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8070 /* Only sent on Win7. */
8071 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8075 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
8077 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8078 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8079 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8080 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8081
8082 ok_method_sequence(node_from_hwnd10, "node_from_hwnd10");
8083
8084 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8085 /* Win10v1809 can be slow to call Release on Provider. */
8086 if (Provider.ref != 1)
8087 Sleep(50);
8088 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8089
8090 if (!pUiaDisconnectProvider)
8091 {
8092 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
8093 goto exit;
8094 }
8095
8096 /*
8097 * UiaDisconnectProvider tests.
8098 */
8099 /* Only sent twice on Windows 11. */
8100 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
8103 Provider.hwnd = hwnd;
8109 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8110 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
8111 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8112
8113 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8114 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8115
8116 memset(buf, 0, sizeof(buf));
8117 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
8119 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
8123 VariantClear(&v);
8124
8126 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
8127
8128 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8129 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8130 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
8131
8132 /* Nodes returned from a nested node will be tracked and disconnectable. */
8134 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
8135 Provider_child.runtime_id[1] = 2;
8136 Provider_child.hwnd = NULL;
8138 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8139 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8140 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
8141
8142 hr = UiaHUiaNodeFromVariant(&v, &node2);
8143 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8144 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
8145 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8147 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8148 VariantClear(&v);
8149
8150 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8151 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8152 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8153 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8154 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
8155
8156 /* Get a new node for the same provider. */
8157 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8158 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8159 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
8160
8161 hr = UiaHUiaNodeFromVariant(&v, &node3);
8162 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8163 hr = UiaGetPropertyValue(node3, UIA_ProviderDescriptionPropertyId, &v);
8164 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8166 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8167 VariantClear(&v);
8168
8169 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
8170 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8171 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8172 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8173 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
8174
8175 /*
8176 * Both node2 and node3 represent Provider_child, one call to
8177 * UiaDisconnectProvider disconnects both.
8178 */
8179 hr = pUiaDisconnectProvider(&Provider_child.IRawElementProviderSimple_iface);
8180 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8181 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8182
8183 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8184 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
8185
8186 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
8187 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
8188 ok_method_sequence(disconnect_prov1, "disconnect_prov1");
8189
8190 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8191 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
8192
8193 /*
8194 * Returns same failure code as UiaGetRuntimeId when we fail to get a
8195 * fragment root for AppendRuntimeId.
8196 */
8197 Provider.hwnd = NULL;
8199 Provider.runtime_id[1] = 2;
8201 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8202 ok(hr == E_FAIL, "Unexpected hr %#lx\n", hr);
8203 ok_method_sequence(disconnect_prov2, "disconnect_prov2");
8204
8205 /*
8206 * Comparisons for disconnection are only based on RuntimeId comparisons,
8207 * not interface pointer values. If an interface returns a NULL RuntimeId,
8208 * no disconnection will occur.
8209 */
8211 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8212 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
8213 ok_method_sequence(disconnect_prov3, "disconnect_prov3");
8214
8215 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8216 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8217 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
8218
8219 /* Finally, disconnect node. */
8220 Provider.hwnd = hwnd;
8221 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8222 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8223
8224 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8225 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
8226 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8227 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
8228
8229exit:
8231
8232 return 0;
8233}
8234
8235static void test_UiaNodeFromHandle(const char *name)
8236{
8237 APTTYPEQUALIFIER apt_qualifier;
8239 char cmdline[MAX_PATH];
8241 HUIANODE node, node2;
8242 APTTYPE apt_type;
8244 WNDCLASSA cls;
8245 HANDLE thread;
8246 HRESULT hr;
8247 HWND hwnd;
8248 VARIANT v;
8249
8250 cls.style = 0;
8252 cls.cbClsExtra = 0;
8253 cls.cbWndExtra = 0;
8255 cls.hIcon = 0;
8256 cls.hCursor = NULL;
8257 cls.hbrBackground = NULL;
8258 cls.lpszMenuName = NULL;
8259 cls.lpszClassName = "UiaNodeFromHandle class";
8260 RegisterClassA(&cls);
8261
8262 hwnd = CreateWindowA("UiaNodeFromHandle class", "Test window", WS_OVERLAPPEDWINDOW,
8263 0, 0, 100, 100, NULL, NULL, NULL, NULL);
8264
8266 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
8267
8269 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
8270
8271 /* COM uninitialized, no provider returned by UiaReturnRawElementProvider. */
8272 prov_root = NULL;
8273 node = (void *)0xdeadbeef;
8274 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8275 /* Only sent twice on Win7. */
8276 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8278 /*
8279 * On all versions of Windows prior to Windows 11, this would fail due to
8280 * COM being uninitialized, presumably because it tries to get an MSAA
8281 * proxy. Windows 11 now has the thread end up in an implicit MTA after
8282 * the call to UiaNodeFromHandle, which is probably why this now succeeds.
8283 * I don't know of anything that relies on this behavior, so for now we
8284 * won't match it.
8285 */
8286 todo_wine ok(hr == S_OK || broken(hr == E_FAIL), "Unexpected hr %#lx.\n", hr);
8287 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8288 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8289 if (SUCCEEDED(hr))
8291
8292 /*
8293 * COM initialized, no provider returned by UiaReturnRawElementProvider.
8294 * In this case, we get a default MSAA proxy.
8295 */
8297 prov_root = NULL;
8298 node = (void *)0xdeadbeef;
8299 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8300 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8302 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8303 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8304 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8305
8306 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8307 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8313 VariantClear(&v);
8314
8315 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8316
8317 /*
8318 * COM initialized, but provider passed into UiaReturnRawElementProvider
8319 * returns a failure code on get_ProviderOptions. Same behavior as before.
8320 */
8321 Provider.prov_opts = 0;
8322 Provider.hwnd = hwnd;
8324 node = (void *)0xdeadbeef;
8325 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8326 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8328 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8329 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8330 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8331
8332 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8333 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8339 VariantClear(&v);
8340
8341 ok_method_sequence(node_from_hwnd1, "node_from_hwnd1");
8342
8343 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8344
8345 /*
8346 * COM initialized, but provider passed into UiaReturnRawElementProvider
8347 * on Win8+ will have its RuntimeId queried for UiaDisconnectProvider.
8348 * It will fail due to the lack of a valid fragment root, and we'll fall
8349 * back to an MSAA proxy. On Win7, RuntimeId isn't queried because the
8350 * disconnection functions weren't implemented yet.
8351 */
8353 Provider.hwnd = NULL;
8355 node = (void *)0xdeadbeef;
8356 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8357 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8360 Provider.runtime_id[1] = 1;
8362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8363 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
8364 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8365 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8366
8367 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8368 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8369
8371 if (Provider.ref == 1 || get_provider_desc(V_BSTR(&v), L"Annotation:", NULL))
8372 {
8375 }
8376 else
8377 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
8378
8381 VariantClear(&v);
8382
8383 ok_method_sequence(node_from_hwnd9, "node_from_hwnd9");
8384 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8385 /*
8386 * Bug on Windows 8 through Win10v1709 - if we have a RuntimeId failure,
8387 * refcount doesn't get decremented.
8388 */
8389 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
8390 if (Provider.ref == 2)
8391 IRawElementProviderSimple_Release(&Provider.IRawElementProviderSimple_iface);
8392
8394
8395 /*
8396 * COM uninitialized, return a Provider from UiaReturnRawElementProvider
8397 * with ProviderOptions_ServerSideProvider.
8398 */
8400 Provider.hwnd = hwnd;
8402 node = (void *)0xdeadbeef;
8403 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8404 /* Only sent on Win7. */
8405 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8406 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8409 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8410 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8411 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8412
8413 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8414 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8416 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
8419 VariantClear(&v);
8420
8421 ok_method_sequence(node_from_hwnd2, "node_from_hwnd2");
8422
8423 /* For same-thread HWND nodes, no disconnection will occur. */
8424 if (pUiaDisconnectProvider)
8425 {
8426 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8427 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8428
8429 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
8430 }
8431
8432 /*
8433 * This is relevant too: Since we don't get a 'nested' node, all calls
8434 * will occur on the current thread.
8435 */
8437 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8438 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8439 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
8440
8441 /* UIAutomationType_Element properties will return a normal node. */
8443 Provider_child.hwnd = NULL;
8444 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8445 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8446
8447 hr = UiaHUiaNodeFromVariant(&v, &node2);
8448 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8449 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
8450 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8452 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8453 VariantClear(&v);
8454
8455 Provider_child.expected_tid = GetCurrentThreadId();
8456 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8457 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8458 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8459 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8460 ok_method_sequence(node_from_hwnd4, "node_from_hwnd4");
8461
8462 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8463
8464 Provider.expected_tid = Provider_child.expected_tid = 0;
8465 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8466
8467 /*
8468 * On Windows 8 and above, after the first successful call to
8469 * UiaReturnRawElementProvider the process ends up in an implicit MTA
8470 * until the process exits.
8471 */
8472 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
8473 /* Wine's provider thread doesn't always terminate immediately. */
8474 if (hr == S_OK && !strcmp(winetest_platform, "wine"))
8475 {
8476 Sleep(10);
8477 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
8478 }
8479 todo_wine ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
8480 if (SUCCEEDED(hr))
8481 {
8482 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
8483 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
8484 }
8485
8489 {
8490 MSG msg;
8491 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
8492 {
8495 }
8496 }
8498
8499 /* Test behavior from separate process. */
8501 Provider.hwnd = hwnd;
8504 sprintf(cmdline, "\"%s\" uiautomation UiaNodeFromHandle_client_proc", name);
8505 memset(&startup, 0, sizeof(startup));
8506 startup.cb = sizeof(startup);
8507 /* Only called twice on Windows 11. */
8508 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
8509 /* Only sent on Win7. */
8510 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8513 {
8514 MSG msg;
8515 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
8516 {
8519 }
8520 }
8521
8522 GetExitCodeProcess(proc.hProcess, &exit_code);
8523 if (exit_code > 255)
8524 ok(0, "unhandled exception %08x in child process %04x\n", (UINT)exit_code, (UINT)GetProcessId(proc.hProcess));
8525 else if (exit_code)
8526 ok(0, "%u failures in child process\n", (UINT)exit_code);
8527
8528 CloseHandle(proc.hProcess);
8529 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8530 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8532 ok_method_sequence(node_from_hwnd8, "node_from_hwnd8");
8533
8535
8537 UnregisterClassA("UiaNodeFromHandle class", NULL);
8538 prov_root = NULL;
8539}
8540
8541static const struct prov_method_sequence reg_prov_cb1[] = {
8542 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8543 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
8544 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8545 { 0 }
8546};
8547
8548static const struct prov_method_sequence reg_prov_cb2[] = {
8549 /* These two are only done on Win10v1809+. */
8551 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8552 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8553 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
8554 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8555 { 0 }
8556};
8557
8558static const struct prov_method_sequence reg_prov_cb3[] = {
8560 /* These two are only done on Win10v1809+. */
8562 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8563 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8564 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8565 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8566 /* These three only done on Win10+. */
8570 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8571 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8572 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8573 { 0 }
8574};
8575
8576static const struct prov_method_sequence reg_prov_cb4[] = {
8578 /* These two are only done on Win10v1809+. */
8580 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8581 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8582 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8583 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8584 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8585 /* These four only done on Win10+. */
8590 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8591 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8592 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8593 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8594 { 0 }
8595};
8596
8597static const struct prov_method_sequence reg_prov_cb5[] = {
8598 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8599 { 0 }
8600};
8601
8602static const struct prov_method_sequence reg_prov_cb6[] = {
8603 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8604 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8605 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8606 { 0 }
8607};
8608
8609static const struct prov_method_sequence reg_prov_cb7[] = {
8610 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8611 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8612 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8613 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8614 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8615 { 0 }
8616};
8617
8618static const struct prov_method_sequence reg_prov_cb8[] = {
8619 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8620 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8621 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8622 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8623 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8624 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8625 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8626 { 0 }
8627};
8628
8629static const struct prov_method_sequence reg_prov_cb9[] = {
8630 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8631 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8632 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8633 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8634 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8635 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8636 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8637 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8638 { 0 }
8639};
8640
8641static const struct prov_method_sequence reg_prov_cb10[] = {
8643 /* These two are only done on Win10v1809+. */
8645 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8646 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8647 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8648 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8649 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8650 /* These four only done on Win10+. */
8655 { 0 }
8656};
8657
8658static const struct prov_method_sequence reg_prov_cb11[] = {
8660 /* Win10v1507 and below call this. */
8661 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8663 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8667 /* These two are only done on Win10v1809+. */
8669 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8670 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8671 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8672 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8673 /* These three only done on Win10+. */
8677 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8678 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8679 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8680 { 0 }
8681};
8682
8683static const struct prov_method_sequence reg_prov_cb12[] = {
8685 /* Win10v1507 and below call this. */
8686 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8688 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8692 /* Win10v1507 and below call this. */
8693 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8695 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8697 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8699 /* These two are only done on Win10v1809+. */
8701 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8702 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8703 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8704 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8705 /* These three only done on Win10+. */
8709 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8710 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8711 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8712 { 0 }
8713};
8714
8715static const struct prov_method_sequence reg_prov_cb13[] = {
8717 /* Win10v1507 and below call this. */
8718 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8720 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8724 /* Win10v1507 and below call this. */
8725 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8727 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8729 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8730 /* Provider override only retrieved successfully on Win10v1809+ */
8733 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8736 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1507 and below. */
8737 /* These two are only done on Win10v1809+. */
8739 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8740 /* Only done on Win10v1809+. */
8741 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8742 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8743 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8744 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8745 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8746 /* These three only done on Win10+. */
8750 /* Only done on Win10v1809+. */
8751 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
8752 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8753 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8754 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8755 { 0 }
8756};
8757
8758static SAFEARRAY *get_safearray_for_elprov(IRawElementProviderSimple *elprov)
8759{
8760 SAFEARRAY *sa = NULL;
8761 LONG idx = 0;
8762
8763 if (elprov)
8764 {
8766 if (sa)
8767 SafeArrayPutElement(sa, &idx, (void *)elprov);
8768 }
8769
8770 return sa;
8771}
8772
8773static IRawElementProviderSimple *base_hwnd_prov, *proxy_prov, *parent_proxy_prov, *nc_prov;
8774#ifdef __REACTOS__
8776#else
8778#endif
8779{
8780 IRawElementProviderSimple *elprov = NULL;
8781
8782 switch (prov_type)
8783 {
8785 CHECK_EXPECT(prov_callback_base_hwnd);
8786 if (hwnd == Provider_hwnd3.hwnd)
8787 elprov = &Provider_hwnd3.IRawElementProviderSimple_iface;
8788 else if (hwnd == Provider_hwnd2.hwnd)
8789 elprov = &Provider_hwnd2.IRawElementProviderSimple_iface;
8790 else
8791 elprov = base_hwnd_prov;
8792 break;
8793
8794 case ProviderType_Proxy:
8795 if (Provider_proxy.hwnd == hwnd)
8796 {
8797 CHECK_EXPECT(prov_callback_proxy);
8798 elprov = proxy_prov;
8799 }
8800 else if (hwnd == GetParent(Provider_proxy.hwnd))
8801 {
8802 CHECK_EXPECT(prov_callback_parent_proxy);
8803 elprov = parent_proxy_prov;
8804 }
8805 break;
8806
8808 CHECK_EXPECT(prov_callback_nonclient);
8809 if (hwnd == Provider_nc3.hwnd)
8810 elprov = &Provider_nc3.IRawElementProviderSimple_iface;
8811 else if (hwnd == Provider_nc2.hwnd)
8812 elprov = &Provider_nc2.IRawElementProviderSimple_iface;
8813 else
8814 elprov = nc_prov;
8815 break;
8816
8817 default:
8818 break;
8819 }
8820
8821 return get_safearray_for_elprov(elprov);
8822}
8823
8824/*
8825 * Windows 11 will infinitely loop if a clientside provider isn't returned for
8826 * an HWND in certain circumstances. In order to prevent this, we use these
8827 * temporary clientside providers.
8828 */
8830{
8831 IRawElementProviderSimple IRawElementProviderSimple_iface;
8833
8836};
8837
8838static inline struct ClientSideProvider *impl_from_ClientSideProvider(IRawElementProviderSimple *iface)
8839{
8841}
8842
8843static HRESULT WINAPI ClientSideProvider_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
8844{
8845 *ppv = NULL;
8846 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
8847 *ppv = iface;
8848 else
8849 return E_NOINTERFACE;
8850
8851 IRawElementProviderSimple_AddRef(iface);
8852 return S_OK;
8853}
8854
8855static ULONG WINAPI ClientSideProvider_AddRef(IRawElementProviderSimple *iface)
8856{
8858 return InterlockedIncrement(&This->ref);
8859}
8860
8861static ULONG WINAPI ClientSideProvider_Release(IRawElementProviderSimple *iface)
8862{
8865
8866 if (!ref)
8867 free(This);
8868
8869 return ref;
8870}
8871
8872static HRESULT WINAPI ClientSideProvider_get_ProviderOptions(IRawElementProviderSimple *iface,
8873 enum ProviderOptions *ret_val)
8874{
8876
8878 if (This->prov_type == ProviderType_NonClientArea)
8880
8881 return S_OK;
8882}
8883
8884static HRESULT WINAPI ClientSideProvider_GetPatternProvider(IRawElementProviderSimple *iface,
8885 PATTERNID pattern_id, IUnknown **ret_val)
8886{
8887 *ret_val = NULL;
8888 return S_OK;
8889}
8890
8891static HRESULT WINAPI ClientSideProvider_GetPropertyValue(IRawElementProviderSimple *iface, PROPERTYID prop_id,
8892 VARIANT *ret_val)
8893{
8895
8896 VariantInit(ret_val);
8897 switch (prop_id)
8898 {
8899 case UIA_NativeWindowHandlePropertyId:
8900 if (This->prov_type == ProviderType_BaseHwnd)
8901 {
8902 V_VT(ret_val) = VT_I4;
8903 V_I4(ret_val) = HandleToULong(This->hwnd);
8904 }
8905 break;
8906
8907 case UIA_ProviderDescriptionPropertyId:
8908 V_VT(ret_val) = VT_BSTR;
8909 V_BSTR(ret_val) = SysAllocString(L"ClientSideProvider");
8910 break;
8911
8912 default:
8913 break;
8914 }
8915
8916 return S_OK;
8917}
8918
8919static HRESULT WINAPI ClientSideProvider_get_HostRawElementProvider(IRawElementProviderSimple *iface,
8920 IRawElementProviderSimple **ret_val)
8921{
8923
8924 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
8925}
8926
8927static IRawElementProviderSimpleVtbl ClientSideProviderVtbl = {
8935};
8936
8938{
8939 struct ClientSideProvider *prov = malloc(sizeof(*prov));
8940
8941 if (!prov)
8942 {
8943 trace("Failed to allocate memory for temporary clientside provider\n");
8944 return NULL;
8945 }
8946
8948 prov->ref = 1;
8949 prov->prov_type = prov_type;
8950 prov->hwnd = hwnd;
8951
8952 return &prov->IRawElementProviderSimple_iface;
8953}
8954
8957{
8960 0, 0, { (DWORD_PTR)(__FILE__ ": clientside_provider_callback_cs") }
8961};
8963static CONDITION_VARIABLE *clientside_provider_callback_cv;
8964
8965/*
8966 * Same deal as test_uia_provider_callback, except we only return a provider
8967 * if we can match one by HWND. This is necessary due to certain versions of
8968 * Windows 10 unpredictably attempting to create elements in the background.
8969 */
8970#ifdef __REACTOS__
8972#else
8974#endif
8975{
8976 IRawElementProviderSimple *elprov = NULL;
8977 SAFEARRAY *sa = NULL;
8978
8983 switch (prov_type)
8984 {
8986 if (hwnd == Provider_hwnd3.hwnd)
8987 elprov = &Provider_hwnd3.IRawElementProviderSimple_iface;
8988 else if (hwnd == Provider_hwnd2.hwnd)
8989 elprov = &Provider_hwnd2.IRawElementProviderSimple_iface;
8990 else if (hwnd == Provider_hwnd.hwnd)
8991 elprov = &Provider_hwnd.IRawElementProviderSimple_iface;
8992
8993 if (elprov)
8994 CHECK_EXPECT(prov_callback_base_hwnd);
8995 break;
8996
8997 case ProviderType_Proxy:
8998 if (Provider_proxy.hwnd == hwnd)
8999 elprov = proxy_prov;
9000 break;
9001
9003 if (hwnd == Provider_nc3.hwnd)
9004 elprov = &Provider_nc3.IRawElementProviderSimple_iface;
9005 else if (hwnd == Provider_nc2.hwnd)
9006 elprov = &Provider_nc2.IRawElementProviderSimple_iface;
9007 else if (hwnd == Provider_nc.hwnd)
9008 elprov = &Provider_nc.IRawElementProviderSimple_iface;
9009
9010 if (elprov)
9011 CHECK_EXPECT(prov_callback_nonclient);
9012 break;
9013
9014 default:
9015 break;
9016 }
9017
9018 if (!elprov)
9019 {
9021 return NULL;
9022 }
9023 else
9024 IRawElementProviderSimple_AddRef(elprov);
9025
9026 sa = get_safearray_for_elprov(elprov);
9027 IRawElementProviderSimple_Release(elprov);
9028 return sa;
9029}
9030
9031/*
9032 * Some versions of Windows 10 query multiple unrelated HWNDs when
9033 * winevents are fired, this function waits for these to stop before
9034 * continuing to the next test.
9035 */
9036#define TIME_SINCE_LAST_CALLBACK_TIMEOUT 200
9038{
9039 DWORD start_time = GetTickCount();
9040 CONDITION_VARIABLE cv;
9041 BOOL ret = FALSE;
9042
9046 while (1)
9047 {
9049
9050 if ((GetTickCount() - start_time) >= total_timeout)
9051 ret = TRUE;
9052 else if (!ret_val && (GetLastError() == ERROR_TIMEOUT))
9053 ret = FALSE;
9054 else if (!ret_val)
9055 trace("SleepConditionVariableCS failed, last err %ld\n", GetLastError());
9056 else
9057 continue;
9058
9059 break;
9060 }
9061
9064 return ret;
9065}
9066
9068{
9069 HWND hwnd, hwnd2;
9070 WNDCLASSA cls;
9071 HUIANODE node;
9072 HRESULT hr;
9073 VARIANT v;
9074
9075 cls.style = 0;
9077 cls.cbClsExtra = 0;
9078 cls.cbWndExtra = 0;
9080 cls.hIcon = 0;
9081 cls.hCursor = NULL;
9082 cls.hbrBackground = NULL;
9083 cls.lpszMenuName = NULL;
9084 cls.lpszClassName = "UiaRegisterProviderCallback class";
9085
9086 RegisterClassA(&cls);
9087
9089 cls.lpszClassName = "UiaRegisterProviderCallback child class";
9090 RegisterClassA(&cls);
9091
9092 hwnd = CreateWindowA("UiaRegisterProviderCallback class", "Test window", WS_OVERLAPPEDWINDOW,
9093 0, 0, 100, 100, NULL, NULL, NULL, NULL);
9094
9095 hwnd2 = CreateWindowA("UiaRegisterProviderCallback child class", "Test child window", WS_CHILD,
9096 0, 0, 100, 100, hwnd, NULL, NULL, NULL);
9097
9099
9100 /* No providers returned by UiaRootObjectId or the provider callback. */
9101 Provider_proxy.hwnd = hwnd2;
9103 node = (void *)0xdeadbeef;
9104 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9105 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9106 SET_EXPECT(prov_callback_base_hwnd);
9107 SET_EXPECT(prov_callback_nonclient);
9108 SET_EXPECT(prov_callback_proxy);
9109 SET_EXPECT(prov_callback_parent_proxy);
9110 hr = UiaNodeFromHandle(hwnd2, &node);
9111 /* Windows 7 returns S_OK with a NULL HUIANODE. */
9112 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
9113 ok(!node, "node != NULL\n");
9114 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9115 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9116 CHECK_CALLED(prov_callback_base_hwnd);
9117 CHECK_CALLED(prov_callback_nonclient);
9118 CHECK_CALLED(prov_callback_proxy);
9119 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9120
9121 /* Return only nonclient proxy provider. */
9123 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9125 node = (void *)0xdeadbeef;
9126 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9127 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9128 SET_EXPECT(prov_callback_base_hwnd);
9129 SET_EXPECT(prov_callback_nonclient);
9130 SET_EXPECT(prov_callback_proxy);
9131 SET_EXPECT(prov_callback_parent_proxy);
9132 hr = UiaNodeFromHandle(hwnd2, &node);
9133 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9134 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9135 ok(!!node, "node == NULL\n");
9136 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9137 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9138 CHECK_CALLED(prov_callback_base_hwnd);
9139 CHECK_CALLED(prov_callback_nonclient);
9140 CHECK_CALLED(prov_callback_proxy);
9141 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9142
9143 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9144 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9146 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
9147 VariantClear(&v);
9148
9149 ok_method_sequence(reg_prov_cb1, "reg_prov_cb1");
9150
9152 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
9153
9154 /* Return only base_hwnd provider. */
9156 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9158 node = (void *)0xdeadbeef;
9159 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9160 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9161 SET_EXPECT(prov_callback_base_hwnd);
9162 SET_EXPECT(prov_callback_nonclient);
9163 SET_EXPECT(prov_callback_proxy);
9164 SET_EXPECT(prov_callback_parent_proxy);
9165 hr = UiaNodeFromHandle(hwnd2, &node);
9166 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9167 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9168 ok(!!node, "node == NULL\n");
9169 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9170 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9171 CHECK_CALLED(prov_callback_base_hwnd);
9172 CHECK_CALLED(prov_callback_nonclient);
9173 CHECK_CALLED(prov_callback_proxy);
9174 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9175
9176 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9177 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9179 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", TRUE);
9180 VariantClear(&v);
9181
9182 ok_method_sequence(reg_prov_cb2, "reg_prov_cb2");
9183
9185 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9186
9187 /* Return providers for all ProviderTypes. */
9188 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9189 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
9190 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
9191 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9192 Provider_proxy.hwnd = hwnd2;
9194 node = (void *)0xdeadbeef;
9195 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9196 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9197 SET_EXPECT(prov_callback_base_hwnd);
9198 SET_EXPECT(prov_callback_nonclient);
9199 SET_EXPECT(prov_callback_proxy);
9200 SET_EXPECT(prov_callback_parent_proxy);
9201 hr = UiaNodeFromHandle(hwnd2, &node);
9202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9203 ok(!!node, "node == NULL\n");
9204 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9205 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
9206 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9207 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9208 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9209 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9210 CHECK_CALLED(prov_callback_base_hwnd);
9211 CHECK_CALLED(prov_callback_nonclient);
9212 CHECK_CALLED(prov_callback_proxy);
9213 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9214
9215 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9216 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9218 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
9219 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9220 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9221 VariantClear(&v);
9222
9223 ok_method_sequence(reg_prov_cb3, "reg_prov_cb3");
9224
9226 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9227 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
9228 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9229
9230 /* Return an override provider from Provider_proxy2. */
9231 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9232 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
9233 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
9234 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9235 Provider_proxy2.override_hwnd = hwnd2;
9237 node = (void *)0xdeadbeef;
9238 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9239 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9240 SET_EXPECT(prov_callback_base_hwnd);
9241 SET_EXPECT(prov_callback_nonclient);
9242 SET_EXPECT(prov_callback_proxy);
9243 SET_EXPECT(prov_callback_parent_proxy);
9244 hr = UiaNodeFromHandle(hwnd2, &node);
9245 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9246 ok(!!node, "node == NULL\n");
9247 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9248 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
9249 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9250 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9251 todo_wine ok(Provider_override.ref == 2, "Unexpected refcnt %ld\n", Provider_override.ref);
9252 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9253 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9254 CHECK_CALLED(prov_callback_base_hwnd);
9255 CHECK_CALLED(prov_callback_nonclient);
9256 CHECK_CALLED(prov_callback_proxy);
9257 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9258
9259 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9260 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9262 check_node_provider_desc_todo(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
9263 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider_proxy", FALSE);
9264 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9265 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9266 VariantClear(&v);
9267
9268 ok_method_sequence(reg_prov_cb4, "reg_prov_cb4");
9269
9270 /*
9271 * Test the order that Providers are queried for properties. The order is:
9272 * Override provider.
9273 * Main provider.
9274 * Nonclient provider.
9275 * Hwnd provider.
9276 *
9277 * UI Automation tries to get a property from each in this order until one
9278 * returns a value. If none do, the property isn't supported.
9279 */
9280 if (Provider_override.ref == 2)
9281 {
9282 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9283 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9284 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9285 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9286 ok_method_sequence(reg_prov_cb5, "reg_prov_cb5");
9287 }
9288
9289 /* Property retrieved from Provider_proxy (Main) */
9290 Provider_override.ret_invalid_prop_type = TRUE;
9291 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9292 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9293 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9294 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9295 ok_method_sequence(reg_prov_cb6, "reg_prov_cb6");
9296
9297 /* Property retrieved from Provider_nc (Nonclient) */
9298 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
9299 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9300 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9301 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9302 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9303 ok_method_sequence(reg_prov_cb7, "reg_prov_cb7");
9304
9305 /* Property retrieved from Provider_hwnd (Hwnd) */
9306 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
9307 Provider_nc.ret_invalid_prop_type = TRUE;
9308 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9309 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9310 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9311 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9312 ok_method_sequence(reg_prov_cb8, "reg_prov_cb8");
9313
9314 /* Property retrieved from none of the providers. */
9315 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
9316 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = TRUE;
9317 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9318 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9319 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
9320 ok_method_sequence(reg_prov_cb9, "reg_prov_cb9");
9321
9323 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9324 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
9325 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9326 ok(Provider_override.ref == 1, "Unexpected refcnt %ld\n", Provider_override.ref);
9327 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = FALSE;
9328 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = FALSE;
9329
9330 /*
9331 * Provider_hwnd has ProviderOptions_UseComThreading, and COM hasn't been
9332 * initialized. One provider failing will cause the entire node to fail
9333 * creation on Win10+.
9334 */
9336 node = (void *)0xdeadbeef;
9337 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9338 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9339 SET_EXPECT(prov_callback_base_hwnd);
9340 SET_EXPECT(prov_callback_nonclient);
9341 SET_EXPECT(prov_callback_proxy);
9342 SET_EXPECT(prov_callback_parent_proxy);
9343 hr = UiaNodeFromHandle(hwnd2, &node);
9344 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
9345 ok(!node || broken(!!node), "node != NULL\n");
9346 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9347 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9348 CHECK_CALLED(prov_callback_base_hwnd);
9349 CHECK_CALLED(prov_callback_nonclient);
9350 CHECK_CALLED(prov_callback_proxy);
9351 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9352 ok_method_sequence(reg_prov_cb10, "reg_prov_cb10");
9355
9356 /*
9357 * Provider returned by UiaRootObjectId on hwnd2. No ProviderType_Proxy
9358 * callback for hwnd2.
9359 */
9360 Provider.hwnd = hwnd2;
9363 Provider_proxy2.override_hwnd = NULL;
9364 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9365 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9366 SET_EXPECT(prov_callback_base_hwnd);
9367 SET_EXPECT(prov_callback_nonclient);
9368 SET_EXPECT(prov_callback_parent_proxy);
9369 hr = UiaNodeFromHandle(hwnd2, &node);
9370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9371 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9372 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9373 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9374 CHECK_CALLED(prov_callback_base_hwnd);
9375 CHECK_CALLED(prov_callback_nonclient);
9376 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9377
9378 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9379 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9381 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9382 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9383 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9384 VariantClear(&v);
9385
9386 ok_method_sequence(reg_prov_cb11, "reg_prov_cb11");
9387
9389
9390 /*
9391 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
9392 * doesn't give an HWND override provider, UIA will attempt to get a proxy
9393 * provider to check it for an HWND override provider.
9394 */
9395 Provider.hwnd = hwnd2;
9396 Provider2.hwnd = hwnd;
9399 prov_root = &Provider2.IRawElementProviderSimple_iface;
9400 Provider_proxy2.override_hwnd = NULL;
9401 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9402 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9403 SET_EXPECT(prov_callback_base_hwnd);
9404 SET_EXPECT(prov_callback_nonclient);
9405 SET_EXPECT(prov_callback_parent_proxy);
9406 hr = UiaNodeFromHandle(hwnd2, &node);
9407 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9408 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9409 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9410 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9411 CHECK_CALLED(prov_callback_base_hwnd);
9412 CHECK_CALLED(prov_callback_nonclient);
9413 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9414
9415 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9416 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9418 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9419 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9420 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9421 VariantClear(&v);
9422
9423 ok_method_sequence(reg_prov_cb12, "reg_prov_cb12");
9424
9426
9427 /*
9428 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
9429 * returns an HWND override, no ProviderType_Proxy callback for hwnd.
9430 */
9431 Provider.hwnd = hwnd2;
9432 Provider2.hwnd = hwnd;
9433 Provider2.override_hwnd = Provider_override.hwnd = hwnd2;
9434 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = TRUE;
9437 prov_root = &Provider2.IRawElementProviderSimple_iface;
9438 Provider_proxy2.override_hwnd = NULL;
9439 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9440 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9441 SET_EXPECT(prov_callback_base_hwnd);
9442 SET_EXPECT(prov_callback_nonclient);
9443 SET_EXPECT(prov_callback_parent_proxy);
9444 hr = UiaNodeFromHandle(hwnd2, &node);
9445 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9446 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9447 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9448 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9449 CHECK_CALLED(prov_callback_base_hwnd);
9450 CHECK_CALLED(prov_callback_nonclient);
9451
9452 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9453 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9455 check_node_provider_desc_todo(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
9456 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
9457 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9458 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9459 VariantClear(&v);
9460
9461 ok_method_sequence(reg_prov_cb13, "reg_prov_cb13");
9462
9464
9465 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = FALSE;
9467
9469 UnregisterClassA("UiaRegisterProviderCallback class", NULL);
9470 UnregisterClassA("UiaRegisterProviderCallback child class", NULL);
9471}
9472
9473static void set_cache_request(struct UiaCacheRequest *req, struct UiaCondition *view_cond, int scope,
9474 PROPERTYID *prop_ids, int prop_ids_count, PATTERNID *pattern_ids, int pattern_ids_count, int elem_mode)
9475{
9476 req->pViewCondition = view_cond;
9477 req->Scope = scope;
9478
9479 req->pProperties = prop_ids;
9480 req->cProperties = prop_ids_count;
9481 req->pPatterns = pattern_ids;
9482 req->cPatterns = pattern_ids_count;
9483
9484 req->automationElementMode = elem_mode;
9485}
9486
9487static void set_property_condition(struct UiaPropertyCondition *cond, int prop_id, VARIANT *val, int flags)
9488{
9490 cond->PropertyId = prop_id;
9491 cond->Value = *val;
9492 cond->Flags = flags;
9493}
9494
9495static void set_and_or_condition(struct UiaAndOrCondition *cond, int cond_type,
9496 struct UiaCondition **conds, int cond_count)
9497{
9498 cond->ConditionType = cond_type;
9499 cond->ppConditions = conds;
9500 cond->cConditions = cond_count;
9501}
9502
9503static void set_not_condition(struct UiaNotCondition *cond, struct UiaCondition *not_cond)
9504{
9506 cond->pConditions = not_cond;
9507}
9508
9509#define MAX_NODE_PROVIDERS 4
9513
9519};
9520
9522{
9523 memset(desc, 0, sizeof(*desc));
9524 desc->pid = pid;
9525 desc->hwnd = hwnd;
9526}
9527
9530{
9531 desc->prov_type[desc->prov_count] = prov_type;
9532 desc->prov_name[desc->prov_count] = prov_name;
9533 desc->parent_link[desc->prov_count] = parent_link;
9534 desc->nested_desc[desc->prov_count] = nested_desc;
9535 desc->prov_count++;
9536}
9537
9540{
9542}
9543
9544#define test_node_provider_desc( desc, desc_str ) \
9545 test_node_provider_desc_( (desc), (desc_str), __FILE__, __LINE__)
9546static void test_node_provider_desc_(struct node_provider_desc *desc, BSTR desc_str, const char *file, int line)
9547{
9548 int i;
9549
9550 check_node_provider_desc_prefix_(desc_str, desc->pid, desc->hwnd, file, line);
9551 for (i = 0; i < desc->prov_count; i++)
9552 {
9553 if (desc->nested_desc[i])
9554 {
9555 WCHAR buf[2048];
9556
9557 ok_(file, line)(get_nested_provider_desc(desc_str, desc->prov_type[i], desc->parent_link[i], buf),
9558 "Failed to get nested provider description\n");
9559 test_node_provider_desc_(desc->nested_desc[i], buf, file, line);
9560 }
9561 else
9562 check_node_provider_desc_(desc_str, desc->prov_type[i], desc->prov_name[i], desc->parent_link[i], FALSE, file, line);
9563 }
9564}
9565
9566/*
9567 * Cache requests are returned as a two dimensional safearray, with the first
9568 * dimension being the element index, and the second index being the
9569 * node/property/pattern value index for the element. The first element value is
9570 * always an HUIANODE, followed by requested property values, and finally
9571 * requested pattern handles.
9572 */
9573#define test_cache_req_sa( sa, exp_lbound, exp_elems, exp_node_desc ) \
9574 test_cache_req_sa_( (sa), (exp_lbound), (exp_elems), (exp_node_desc), __FILE__, __LINE__)
9575static void test_cache_req_sa_(SAFEARRAY *sa, LONG exp_lbound[2], LONG exp_elems[2],
9576 struct node_provider_desc *exp_node_desc, const char *file, int line)
9577{
9578 HUIANODE node;
9579 HRESULT hr;
9580 VARTYPE vt;
9581 VARIANT v;
9582 UINT dims;
9583 int i;
9584
9586 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9587 ok_(file, line)(vt == VT_VARIANT, "Unexpected vt %d\n", vt);
9588
9589 dims = SafeArrayGetDim(sa);
9590 ok_(file, line)(dims == 2, "Unexpected dims %d\n", dims);
9591
9592 for (i = 0; i < 2; i++)
9593 {
9594 LONG lbound, ubound, elems;
9595
9596 lbound = ubound = elems = 0;
9597 hr = SafeArrayGetLBound(sa, 1 + i, &lbound);
9598 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
9599 ok_(file, line)(exp_lbound[i] == lbound, "Unexpected lbound[%d] %ld\n", i, lbound);
9600
9601 hr = SafeArrayGetUBound(sa, 1 + i, &ubound);
9602 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
9603
9604 elems = (ubound - lbound) + 1;
9605 ok_(file, line)(exp_elems[i] == elems, "Unexpected elems[%d] %ld\n", i, elems);
9606 }
9607
9608 for (i = 0; i < exp_elems[0]; i++)
9609 {
9610 LONG idx[2] = { (exp_lbound[0] + i), exp_lbound[1] };
9611
9613 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9614
9616 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9617 VariantClear(&v);
9618
9619 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9620 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9621 test_node_provider_desc_(&exp_node_desc[i], V_BSTR(&v), file, line);
9622 VariantClear(&v);
9623
9625 }
9626}
9627
9628#define test_provider_event_advise_added( prov, event_id, todo) \
9629 test_provider_event_advise_added_( (prov), (event_id), (todo), __FILE__, __LINE__)
9630static void test_provider_event_advise_added_(struct Provider *prov, int event_id, BOOL todo, const char *file, int line)
9631{
9632 todo_wine_if (todo) ok_(file, line)(prov->advise_events_added_event_id == event_id, "%s: Unexpected advise event added, event ID %d.\n",
9634}
9635
9636static const struct prov_method_sequence cache_req_seq1[] = {
9637 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9638 { 0 }
9639};
9640
9641/*
9642 * Win10v1507 and below will attempt to do parent navigation if the
9643 * conditional check fails.
9644 */
9645static const struct prov_method_sequence cache_req_seq2[] = {
9646 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9647 { 0 }
9648};
9649
9650static const struct prov_method_sequence cache_req_seq3[] = {
9651 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9653 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9655 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9656 /* Navigates towards parent to check for clientside provider siblings. */
9657 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9659 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9660 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9661 { 0 }
9662};
9663
9664static const struct prov_method_sequence cache_req_seq4[] = {
9665 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
9666 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9667 { 0 }
9668};
9669
9670/* Sequence for non-matching property condition. */
9671static const struct prov_method_sequence cache_req_seq5[] = {
9672 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
9673 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* Dependent upon property condition. */
9674 /* Only done on Win10v1507 and below. */
9675 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9676 { 0 }
9677};
9678
9679static const struct prov_method_sequence cache_req_seq6[] = {
9681 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9682 /* Only done on Win10v1507 and below. */
9683 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9684 { 0 }
9685};
9686
9687static const struct prov_method_sequence cache_req_seq7[] = {
9689 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId. */
9690 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9691 { 0 }
9692};
9693
9694static const struct prov_method_sequence cache_req_seq8[] = {
9696 { 0 }
9697};
9698
9699static const struct prov_method_sequence cache_req_seq9[] = {
9700 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9701 /* Done twice on Windows, but we shouldn't need to replicate this. */
9702 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_IsControlElementPropertyId */
9703 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9705 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9706 /* Only done on Win10v1507 and below. */
9707 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9708 { 0 }
9709};
9710
9711static const struct prov_method_sequence cache_req_seq10[] = {
9712 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9713 /* Done twice on Windows, but we shouldn't need to replicate this. */
9714 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_IsControlElementPropertyId */
9715 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9717 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9718 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9719 { 0 }
9720};
9721
9725{
9726 LONG exp_lbound[2], exp_elems[2], idx[2], i;
9727 struct Provider_prop_override prop_override;
9728 struct node_provider_desc exp_node_desc[2];
9729 struct UiaPropertyCondition prop_cond;
9730 struct UiaAndOrCondition and_or_cond;
9731 struct UiaCacheRequest cache_req;
9732 struct UiaCondition *cond_arr[2];
9733 struct UiaNotCondition not_cond;
9734 VARIANT v, v_arr[2];
9735 SAFEARRAY *out_req;
9736 IUnknown *unk_ns;
9737 BSTR tree_struct;
9738 int prop_ids[2];
9739 HUIANODE node;
9740 HRESULT hr;
9741
9743
9745 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9746
9747 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9749
9751 Provider.hwnd = NULL;
9753 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9754 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9755
9756 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9757 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9759 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9760 VariantClear(&v);
9761
9763
9764 /* NULL arg tests. */
9766 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, NULL);
9767 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9768
9769 hr = UiaGetUpdatedCache(node, NULL, NormalizeState_None, NULL, &out_req, &tree_struct);
9770 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9771
9772 hr = UiaGetUpdatedCache(NULL, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9773 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9774
9775 /*
9776 * Cache request with NULL view condition, doesn't matter with
9777 * NormalizeState_None as passed in HUIANODE isn't evaluated against any
9778 * condition.
9779 */
9780 tree_struct = NULL; out_req = NULL;
9781 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9783 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9785 ok(!!out_req, "out_req == NULL\n");
9786 ok(!!tree_struct, "tree_struct == NULL\n");
9787
9788 exp_lbound[0] = exp_lbound[1] = 0;
9789 exp_elems[0] = exp_elems[1] = 1;
9790 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9791 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9792 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
9793
9794 SafeArrayDestroy(out_req);
9795 SysFreeString(tree_struct);
9796
9797 /*
9798 * NormalizeState_View, HUIANODE gets checked against the ConditionType_False
9799 * condition within the cache request structure, nothing is returned.
9800 */
9801 tree_struct = NULL; out_req = NULL;
9803 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9804 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9805 ok(!out_req, "out_req != NULL\n");
9806
9807 /* Empty tree structure string. */
9808 ok(!!tree_struct, "tree_struct == NULL\n");
9809 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9810 SysFreeString(tree_struct);
9811 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
9812
9813 /*
9814 * NormalizeState_View, HUIANODE gets checked against the ConditionType_True
9815 * condition within the cache request structure, returns this HUIANODE.
9816 */
9817 tree_struct = NULL; out_req = NULL;
9819 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9821 ok(!!out_req, "out_req == NULL\n");
9822 ok(!!tree_struct, "tree_struct == NULL\n");
9823
9824 exp_lbound[0] = exp_lbound[1] = 0;
9825 exp_elems[0] = exp_elems[1] = 1;
9826 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9827 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9828 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
9829
9830 SafeArrayDestroy(out_req);
9831 SysFreeString(tree_struct);
9832
9833 /*
9834 * NormalizeState_Custom, HUIANODE gets checked against our passed in
9835 * ConditionType_False condition.
9836 */
9838 tree_struct = NULL; out_req = NULL;
9839 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaFalseCondition, &out_req, &tree_struct);
9840 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9841 ok(!out_req, "out_req != NULL\n");
9842
9843 /* Empty tree structure string. */
9844 ok(!!tree_struct, "tree_struct == NULL\n");
9845 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9846 SysFreeString(tree_struct);
9847
9848 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
9849
9850 /*
9851 * NormalizeState_Custom, HUIANODE gets checked against the ConditionType_True
9852 * condition we pass in, returns this HUIANODE.
9853 */
9854 tree_struct = NULL; out_req = NULL;
9856 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaTrueCondition, &out_req, &tree_struct);
9857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9858 ok(!!out_req, "out_req == NULL\n");
9859 ok(!!tree_struct, "tree_struct == NULL\n");
9860
9861 exp_lbound[0] = exp_lbound[1] = 0;
9862 exp_elems[0] = exp_elems[1] = 1;
9863 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9864 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9865 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
9866
9867 SafeArrayDestroy(out_req);
9868 SysFreeString(tree_struct);
9869
9870 /*
9871 * CacheRequest with TreeScope_Children.
9872 */
9873 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9875 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9876 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
9877 tree_struct = NULL; out_req = NULL;
9879 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9880 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9881 todo_wine ok(!!out_req, "out_req == NULL\n");
9882 todo_wine ok(!!tree_struct, "tree_struct == NULL\n");
9883 todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9884 todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9885 if (out_req)
9886 {
9887 exp_elems[0] = 2;
9888 exp_elems[1] = 1;
9889 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9890
9891 ok(!wcscmp(tree_struct, L"(P)P))"), "tree structure %s\n", debugstr_w(tree_struct));
9892 ok_method_sequence(cache_req_seq3, "cache_req_seq3");
9893 }
9894
9895 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
9896 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
9897 SafeArrayDestroy(out_req);
9898 SysFreeString(tree_struct);
9899
9900 /*
9901 * ConditionType_And tests.
9902 */
9903 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9905 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9906 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9907 cond_arr[1] = (struct UiaCondition *)&UiaTrueCondition;
9908 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
9909 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9911 tree_struct = NULL; out_req = NULL;
9912
9913 /* Equivalent to: if (1 && 1) */
9914 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9916 ok(!!out_req, "out_req == NULL\n");
9917 ok(!!tree_struct, "tree_struct == NULL\n");
9918
9919 exp_lbound[0] = exp_lbound[1] = 0;
9920 exp_elems[0] = exp_elems[1] = 1;
9921 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9922 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9924
9925 SafeArrayDestroy(out_req);
9926 SysFreeString(tree_struct);
9927
9928 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9929 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9930 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
9931 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9933 tree_struct = NULL; out_req = NULL;
9934
9935 /* Equivalent to: if (1 && 0) */
9936 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9937 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9939 ok(!out_req, "out_req != NULL\n");
9940 ok(!!tree_struct, "tree_struct == NULL\n");
9941 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9942
9943 SysFreeString(tree_struct);
9944
9945 /*
9946 * ConditionType_Or tests.
9947 */
9948 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9949 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9950 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
9951 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9953 tree_struct = NULL; out_req = NULL;
9954
9955 /* Equivalent to: if (1 || 0) */
9956 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9958 ok(!!out_req, "out_req == NULL\n");
9959 ok(!!tree_struct, "tree_struct == NULL\n");
9960
9961 exp_lbound[0] = exp_lbound[1] = 0;
9962 exp_elems[0] = exp_elems[1] = 1;
9963 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9964 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9966
9967 SafeArrayDestroy(out_req);
9968 SysFreeString(tree_struct);
9969
9970 cond_arr[0] = (struct UiaCondition *)&UiaFalseCondition;
9971 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9972 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
9973 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9975 tree_struct = NULL; out_req = NULL;
9976
9977 /* Equivalent to: if (0 || 0) */
9978 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9979 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9981 ok(!out_req, "out_req != NULL\n");
9982 ok(!!tree_struct, "tree_struct == NULL\n");
9983 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9984
9985 SysFreeString(tree_struct);
9986
9987 /*
9988 * ConditionType_Not tests.
9989 */
9990 set_not_condition(&not_cond, (struct UiaCondition *)&UiaFalseCondition);
9991 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
9993 tree_struct = NULL; out_req = NULL;
9994
9995 /* Equivalent to: if (!0) */
9996 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9997 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9998 ok(!!out_req, "out_req == NULL\n");
9999 ok(!!tree_struct, "tree_struct == NULL\n");
10000
10001 exp_lbound[0] = exp_lbound[1] = 0;
10002 exp_elems[0] = exp_elems[1] = 1;
10003 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10004 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10006
10007 SafeArrayDestroy(out_req);
10008 SysFreeString(tree_struct);
10009
10010 set_not_condition(&not_cond, (struct UiaCondition *)&UiaTrueCondition);
10011 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
10013 tree_struct = NULL; out_req = NULL;
10014
10015 /* Equivalent to: if (!1) */
10016 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10018 ok(!out_req, "out_req != NULL\n");
10019 ok(!!tree_struct, "tree_struct == NULL\n");
10020 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10021 SysFreeString(tree_struct);
10023
10024 /*
10025 * ConditionType_Property tests.
10026 */
10028
10029 /* Test UIAutomationType_IntArray property conditions. */
10030 if (UiaLookupId(AutomationIdentifierType_Property, &OutlineColor_Property_GUID))
10031 {
10032 V_VT(&v) = VT_I4 | VT_ARRAY;
10034 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
10035 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10037 tree_struct = NULL; out_req = NULL;
10038
10039 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10040 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10041 ok(!!out_req, "out_req == NULL\n");
10042 ok(!!tree_struct, "tree_struct == NULL\n");
10043
10044 exp_lbound[0] = exp_lbound[1] = 0;
10045 exp_elems[0] = exp_elems[1] = 1;
10046 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10047 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10049
10050 SafeArrayDestroy(out_req);
10051 SysFreeString(tree_struct);
10052 VariantClear(&v);
10053
10054 /* Same values, except we're short by one element. */
10055 V_VT(&v) = VT_I4 | VT_ARRAY;
10057
10058 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val) - 1; i++)
10059 SafeArrayPutElement(V_ARRAY(&prop_cond.Value), &i, (void *)&uia_i4_arr_prop_val[i]);
10060
10061 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
10062 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10064 tree_struct = NULL; out_req = NULL;
10065
10066 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10067 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10069 ok(!out_req, "out_req != NULL\n");
10070 ok(!!tree_struct, "tree_struct == NULL\n");
10071 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10072
10073 SysFreeString(tree_struct);
10074 VariantClear(&v);
10075 }
10076 else
10077 win_skip("UIA_OutlineColorPropertyId unavailable, skipping property condition tests for it.\n");
10078
10079 /* UIA_RuntimeIdPropertyId comparison. */
10080 Provider.runtime_id[0] = 0xdeadbeef; Provider.runtime_id[1] = 0xfeedbeef;
10081 V_VT(&v) = VT_I4 | VT_ARRAY;
10083 for (i = 0; i < ARRAY_SIZE(Provider.runtime_id); i++)
10085
10086 set_property_condition(&prop_cond, UIA_RuntimeIdPropertyId, &v, PropertyConditionFlags_None);
10087 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10089 tree_struct = NULL; out_req = NULL;
10090
10091 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10092 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10093 ok(!!out_req, "out_req == NULL\n");
10094 ok(!!tree_struct, "tree_struct == NULL\n");
10095
10096 exp_lbound[0] = exp_lbound[1] = 0;
10097 exp_elems[0] = exp_elems[1] = 1;
10098 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10099 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10101
10102 SafeArrayDestroy(out_req);
10103 SysFreeString(tree_struct);
10104 VariantClear(&prop_cond.Value);
10105
10106 /* UIAutomationType_Bool property condition tests. */
10107 prop_override.prop_id = UIA_IsControlElementPropertyId;
10108 V_VT(&prop_override.val) = VT_BOOL;
10109 V_BOOL(&prop_override.val) = VARIANT_FALSE;
10110 Provider.prop_override = &prop_override;
10112
10113 V_VT(&v) = VT_BOOL;
10114 V_BOOL(&v) = VARIANT_FALSE;
10115 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10116 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10118 tree_struct = NULL; out_req = NULL;
10119
10120 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10121 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10122 ok(!!out_req, "out_req == NULL\n");
10123 ok(!!tree_struct, "tree_struct == NULL\n");
10124
10125 exp_lbound[0] = exp_lbound[1] = 0;
10126 exp_elems[0] = exp_elems[1] = 1;
10127 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10128 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10130
10131 SafeArrayDestroy(out_req);
10132 SysFreeString(tree_struct);
10133 VariantClear(&v);
10134
10135 /*
10136 * Provider now returns VARIANT_TRUE for UIA_IsControlElementPropertyId,
10137 * conditional check will fail.
10138 */
10139 prop_override.prop_id = UIA_IsControlElementPropertyId;
10140 V_VT(&prop_override.val) = VT_BOOL;
10141 V_BOOL(&prop_override.val) = VARIANT_TRUE;
10142 Provider.prop_override = &prop_override;
10144
10145 V_VT(&v) = VT_BOOL;
10146 V_BOOL(&v) = VARIANT_FALSE;
10147 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10148 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10150 tree_struct = NULL; out_req = NULL;
10151
10152 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10153 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10155 ok(!out_req, "out_req != NULL\n");
10156 ok(!!tree_struct, "tree_struct == NULL\n");
10157 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10158
10159 SysFreeString(tree_struct);
10160 VariantClear(&v);
10161
10164
10165 /*
10166 * Tests for property value caching.
10167 */
10168 prop_ids[0] = UIA_RuntimeIdPropertyId;
10169 /* Invalid property ID, no work will be done. */
10170 prop_ids[1] = 1;
10171 tree_struct = NULL; out_req = NULL;
10172 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
10173 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
10174 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
10175 ok(!out_req, "out_req != NULL\n");
10176 ok(!tree_struct, "tree_struct != NULL\n");
10177
10178 /*
10179 * Retrieve values for UIA_RuntimeIdPropertyId and
10180 * UIA_IsControlElementPropertyId in the returned cache.
10181 */
10182 prop_ids[0] = UIA_RuntimeIdPropertyId;
10183 prop_ids[1] = UIA_IsControlElementPropertyId;
10185 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10186 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10187
10188 tree_struct = NULL; out_req = NULL;
10189 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
10190 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
10191 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10192 ok(!!out_req, "out_req == NULL\n");
10193 ok(!!tree_struct, "tree_struct == NULL\n");
10194
10195 exp_lbound[0] = exp_lbound[1] = 0;
10196 exp_elems[0] = 1;
10197 exp_elems[1] = 3;
10198 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10199 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10200
10201 idx[0] = 0;
10202 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
10203 {
10204 idx[1] = 1 + i;
10205 VariantInit(&v_arr[i]);
10206 hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
10207 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10208 }
10209
10210 ok(V_VT(&v_arr[0]) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
10211 ok(V_UNKNOWN(&v_arr[0]) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v_arr[0]));
10212 VariantClear(&v_arr[0]);
10213
10214 ok(check_variant_bool(&v_arr[1], TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
10215 VariantClear(&v_arr[1]);
10216
10217 ok_method_sequence(cache_req_seq7, "cache_req_seq7");
10218 SafeArrayDestroy(out_req);
10219 SysFreeString(tree_struct);
10220
10221 /*
10222 * Again, but return a valid runtime ID and a different value for
10223 * UIA_IsControlElementPropertyId.
10224 */
10225 V_VT(&v) = VT_BOOL;
10226 V_BOOL(&v) = VARIANT_FALSE;
10227 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
10228 set_provider_prop_override(&Provider, &prop_override, 1);
10229 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
10230 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10231 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10232
10233 tree_struct = NULL; out_req = NULL;
10234 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
10235 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
10236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10237 ok(!!out_req, "out_req == NULL\n");
10238 ok(!!tree_struct, "tree_struct == NULL\n");
10239
10240 exp_lbound[0] = exp_lbound[1] = 0;
10241 exp_elems[0] = 1;
10242 exp_elems[1] = 3;
10243 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10244 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10245
10246 idx[0] = 0;
10247 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
10248 {
10249 idx[1] = 1 + i;
10250 VariantInit(&v_arr[i]);
10251 hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
10252 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10253 }
10254
10255 ok(V_VT(&v_arr[0]) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v_arr[0]));
10257 VariantClear(&v_arr[0]);
10258
10259 ok(check_variant_bool(&v_arr[1], FALSE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
10260 VariantClear(&v_arr[1]);
10261
10262 ok_method_sequence(cache_req_seq7, "cache_req_seq7");
10263 SafeArrayDestroy(out_req);
10264 SysFreeString(tree_struct);
10265
10266 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10267 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10268
10269 /* Normalization navigation tests. */
10272
10273 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
10274 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10275 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10276 ok_method_sequence(cache_req_seq8, "cache_req_seq8");
10277
10278 /*
10279 * Neither Provider_child or Provider match this condition, return
10280 * nothing.
10281 */
10283 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10284 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10285 tree_struct = NULL; out_req = NULL;
10286 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10287 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10288 ok(!out_req, "out_req != NULL\n");
10289 ok(!!tree_struct, "tree_struct == NULL\n");
10290 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10291 SysFreeString(tree_struct);
10292 ok_method_sequence(cache_req_seq9, "cache_req_seq9");
10293
10294 /*
10295 * Provider now matches our condition, we'll get Provider in the cache
10296 * request.
10297 */
10299 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
10300 set_provider_prop_override(&Provider, &prop_override, 1);
10301 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10302 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10303
10304 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10305 tree_struct = NULL; out_req = NULL;
10306 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10307 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10308 ok(!!out_req, "out_req == NULL\n");
10309 ok(!!tree_struct, "tree_struct == NULL\n");
10310 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10311
10312 exp_lbound[0] = exp_lbound[1] = 0;
10313 exp_elems[0] = exp_elems[1] = 1;
10314 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10315 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10316 ok_method_sequence(cache_req_seq10, "cache_req_seq10");
10317
10318 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10319 SafeArrayDestroy(out_req);
10320 SysFreeString(tree_struct);
10321 VariantClear(&v);
10322
10323 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10324 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10327
10328 IUnknown_Release(unk_ns);
10330}
10331
10332static const struct prov_method_sequence nav_seq1[] = {
10335 /* Only done on Win10v1809+ */
10337 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10338 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10339 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10340 /* Windows 10+ calls these. */
10344 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10345 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10346 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10347 { 0 }
10348};
10349
10350static const struct prov_method_sequence nav_seq2[] = {
10351 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10352 NODE_CREATE_SEQ(&Provider_hwnd_child),
10353 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10354 { 0 }
10355};
10356
10357static const struct prov_method_sequence nav_seq3[] = {
10358 { &Provider_hwnd_child, FRAG_NAVIGATE}, /* NavigateDirection_NextSibling */
10359 NODE_CREATE_SEQ(&Provider_hwnd_child2),
10360 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10361 { 0 }
10362};
10363
10364static const struct prov_method_sequence nav_seq4[] = {
10365 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10366 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10368 /* All Windows versions use the NativeWindowHandle provider type check here. */
10369 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
10373 /* Only done on Win10v1809+ */
10375 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10376 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10377 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10378 /* Windows 10+ calls these. */
10382 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10383 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS },
10384 /* Win10v1507 and below call this. */
10385 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10386 { &Provider_nc_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
10387 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
10388 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10389 /* Only called on Windows versions past Win10v1507. */
10390 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
10391 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10392 { 0 }
10393};
10394
10395static const struct prov_method_sequence nav_seq5[] = {
10396 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
10397 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10402 /* Only done on Win10v1809+ */
10404 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10405 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10406 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10407 /* Windows 10+ calls these. */
10411 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
10412 NODE_CREATE_SEQ(&Provider_hwnd_child2),
10413 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10414 { 0 }
10415};
10416
10417static const struct prov_method_sequence nav_seq6[] = {
10418 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10419 NODE_CREATE_SEQ(&Provider_nc_child2),
10420 { &Provider_nc_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10421 { 0 }
10422};
10423
10424static const struct prov_method_sequence nav_seq7[] = {
10425 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10426 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10431 /* Only done on Win10v1809+ */
10433 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10434 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10435 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10436 /* Windows 10+ calls these. */
10440 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10442 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10443 { 0 }
10444};
10445
10446static const struct prov_method_sequence nav_seq8[] = {
10447 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10449 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10450 { 0 }
10451};
10452
10453static const struct prov_method_sequence nav_seq9[] = {
10454 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10455 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10457 /* Win10v1507 and below call this. */
10458 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10462 /* Only done on Win10v1809+ */
10464 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10465 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10466 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10467 /* Windows 10+ calls these. */
10471 /* Navigates to parent a second time. */
10472 { &Provider_child2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10474 /* Win10v1507 and below call this. */
10475 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10478 /* Win10v1507 and below call this. */
10479 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10481 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10484 /* Only done on Win10v1809+ */
10486 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10487 { &Provider_nc, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10488 { &Provider_hwnd, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10489 /* Windows 10+ calls these. */
10493};
10494
10495static const struct prov_method_sequence nav_seq10[] = {
10496 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
10498 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10499 { 0 }
10500};
10501
10502static const struct prov_method_sequence nav_seq11[] = {
10503 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10504 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS },
10505 /* All Windows versions use the NativeWindowHandle provider type check here. */
10506 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
10507 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
10510 /* Only done on Win10v1809+ */
10511 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
10512 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10513 /* Windows 10+ calls these. */
10516 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
10517 { &Provider_hwnd_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10518 NODE_CREATE_SEQ(&Provider_hwnd_child2),
10519 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10520 { 0 }
10521};
10522
10523static const struct prov_method_sequence nav_seq12[] = {
10524 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
10526 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10530 /* Only done on Win10v1809+ */
10532 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10533 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10534 /* Windows 10+ calls these. */
10538 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
10540 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10541 { 0 }
10542};
10543
10544static const struct prov_method_sequence nav_seq13[] = {
10547 /* Only done on Win10v1809+ */
10549 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10550 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10551 /* Windows 10+ calls these. */
10555 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10556 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10557 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10558 { 0 }
10559};
10560
10561static const struct prov_method_sequence nav_seq14[] = {
10562 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10564 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10565 { 0 }
10566};
10567
10568static const struct prov_method_sequence nav_seq15[] = {
10569 NODE_CREATE_SEQ(&Provider_child2_child_child),
10570 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10571};
10572
10573static const struct prov_method_sequence nav_seq16[] = {
10574 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10575 NODE_CREATE_SEQ(&Provider_child2_child),
10576 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10577 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10579 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10580 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10582 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10583 /* Only done on Win10v1507 and below. */
10584 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10585 { 0 }
10586};
10587
10588static const struct prov_method_sequence nav_seq17[] = {
10589 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10590 NODE_CREATE_SEQ(&Provider_child2_child),
10591 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10592 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10594 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10595 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10597 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10598 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10599 { 0 }
10600};
10601
10602static void set_provider_nav_ifaces(struct Provider *prov, struct Provider *parent, struct Provider *frag_root,
10603 struct Provider *prev_sibling, struct Provider *next_sibling, struct Provider *first_child,
10604 struct Provider *last_child)
10605{
10606 prov->parent = NULL;
10607 prov->frag_root = NULL;
10608 prov->prev_sibling = NULL;
10609 prov->next_sibling = NULL;
10610 prov->first_child = NULL;
10611 prov->last_child = NULL;
10612
10613 if (parent)
10614 prov->parent = &parent->IRawElementProviderFragment_iface;
10615 if (frag_root)
10616 prov->frag_root = &frag_root->IRawElementProviderFragmentRoot_iface;
10617 if (prev_sibling)
10618 prov->prev_sibling = &prev_sibling->IRawElementProviderFragment_iface;
10619 if (next_sibling)
10620 prov->next_sibling = &next_sibling->IRawElementProviderFragment_iface;
10621 if (first_child)
10622 prov->first_child = &first_child->IRawElementProviderFragment_iface;
10623 if (last_child)
10624 prov->last_child = &last_child->IRawElementProviderFragment_iface;
10625}
10626
10627static void test_UiaNavigate(void)
10628{
10629 struct Provider_prop_override prop_override;
10630 LONG exp_lbound[2], exp_elems[2], idx[2], i;
10631 struct node_provider_desc exp_node_desc[4];
10632 struct UiaPropertyCondition prop_cond;
10633 struct UiaCacheRequest cache_req;
10634 HUIANODE node, node2, node3;
10635 SAFEARRAY *out_req;
10636 BSTR tree_struct;
10637 WNDCLASSA cls;
10638 HRESULT hr;
10639 VARIANT v;
10640 HWND hwnd;
10641
10643 cls.style = 0;
10645 cls.cbClsExtra = 0;
10646 cls.cbWndExtra = 0;
10648 cls.hIcon = 0;
10649 cls.hCursor = NULL;
10650 cls.hbrBackground = NULL;
10651 cls.lpszMenuName = NULL;
10652 cls.lpszClassName = "UiaNavigate class";
10653
10654 RegisterClassA(&cls);
10655
10656 hwnd = CreateWindowA("UiaNavigate class", "Test window", WS_OVERLAPPEDWINDOW,
10657 0, 0, 100, 100, NULL, NULL, NULL, NULL);
10658
10660 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
10661 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
10662
10663 set_provider_nav_ifaces(&Provider_nc, NULL, NULL, NULL, NULL, &Provider_nc_child, &Provider_nc_child2);
10664 set_provider_nav_ifaces(&Provider_nc_child, &Provider_nc, &Provider_nc, NULL,
10665 &Provider_nc_child2, NULL, NULL);
10666 set_provider_nav_ifaces(&Provider_nc_child2, &Provider_nc, &Provider_nc, &Provider_nc_child,
10667 NULL, NULL, NULL);
10668
10669 set_provider_nav_ifaces(&Provider_hwnd, NULL, NULL, NULL, NULL, &Provider_hwnd_child, &Provider_hwnd_child2);
10670 set_provider_nav_ifaces(&Provider_hwnd_child, &Provider_hwnd, &Provider_hwnd, NULL,
10671 &Provider_hwnd_child2, NULL, NULL);
10672 set_provider_nav_ifaces(&Provider_hwnd_child2, &Provider_hwnd, &Provider_hwnd, &Provider_hwnd_child,
10673 NULL, NULL, NULL);
10674
10675 /*
10676 * Show navigation behavior for multi-provider nodes. Navigation order is:
10677 * HWND provider children.
10678 * Non-Client provider children.
10679 * Main provider children.
10680 * Override provider children.
10681 */
10683 Provider.hwnd = Provider_hwnd.hwnd = Provider_nc.hwnd = hwnd;
10684 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = TRUE;
10686 node = (void *)0xdeadbeef;
10687 /* Only sent on Win7. */
10688 SET_EXPECT(winproc_GETOBJECT_CLIENT);
10689 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10690 SET_EXPECT(prov_callback_base_hwnd);
10691 SET_EXPECT(prov_callback_nonclient);
10693 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10694 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10695 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
10696 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
10697 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10698 CHECK_CALLED(prov_callback_base_hwnd);
10699 CHECK_CALLED(prov_callback_nonclient);
10700 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
10701
10702 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
10703 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10705 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
10706 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
10707 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
10708 VariantClear(&v);
10709
10710 ok_method_sequence(nav_seq1, "nav_seq1");
10711
10712 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10714 idx[0] = idx[1] = 0;
10715
10716 /* Navigate to Provider_hwnd_child. */
10717 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child", TRUE);
10719 tree_struct = NULL; out_req = NULL;
10720 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10721 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10722 ok(!!out_req, "out_req == NULL\n");
10723 ok(!!tree_struct, "tree_struct == NULL\n");
10724 ok(Provider_hwnd_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10725
10726 node2 = node3 = NULL;
10727 hr = SafeArrayGetElement(out_req, idx, &v);
10728 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10729
10730 hr = UiaHUiaNodeFromVariant(&v, &node2);
10731 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10732 IUnknown_AddRef((IUnknown *)node2);
10733
10734 exp_lbound[0] = exp_lbound[1] = 0;
10735 exp_elems[0] = exp_elems[1] = 1;
10736 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10737
10738 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10739 ok_method_sequence(nav_seq2, "nav_seq2");
10740
10741 SafeArrayDestroy(out_req);
10742 SysFreeString(tree_struct);
10743
10744 /* Navigate to Provider_hwnd_child2. */
10745 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10746 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10747 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10748 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10749 ok(!!out_req, "out_req == NULL\n");
10750 ok(!!tree_struct, "tree_struct == NULL\n");
10751 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10752
10753 hr = SafeArrayGetElement(out_req, idx, &v);
10754 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10755
10756 hr = UiaHUiaNodeFromVariant(&v, &node3);
10757 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10758 IUnknown_AddRef((IUnknown *)node3);
10759
10760 exp_lbound[0] = exp_lbound[1] = 0;
10761 exp_elems[0] = exp_elems[1] = 1;
10762 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10763
10764 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10765 ok_method_sequence(nav_seq3, "nav_seq3");
10766
10767 SafeArrayDestroy(out_req);
10768 SysFreeString(tree_struct);
10769
10770 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10771 ok(Provider_hwnd_child.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10772 node2 = node3;
10773
10774 /* Navigate to Provider_nc_child. */
10775 SET_EXPECT(prov_callback_nonclient);
10776 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10777 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10778 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child", TRUE);
10779 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10780 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10781 ok(!!out_req, "out_req == NULL\n");
10782 ok(!!tree_struct, "tree_struct == NULL\n");
10783 ok(Provider_nc_child.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
10784 CHECK_CALLED(prov_callback_nonclient);
10785 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10786
10787 hr = SafeArrayGetElement(out_req, idx, &v);
10788 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10789
10790 hr = UiaHUiaNodeFromVariant(&v, &node3);
10791 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10792 IUnknown_AddRef((IUnknown *)node3);
10793
10794 exp_lbound[0] = exp_lbound[1] = 0;
10795 exp_elems[0] = exp_elems[1] = 1;
10796 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10797
10798 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10799 ok_method_sequence(nav_seq4, "nav_seq4");
10800
10801 SafeArrayDestroy(out_req);
10802 SysFreeString(tree_struct);
10803
10804 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10805 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10806 node2 = node3;
10807
10808 /* Navigate back to Provider_hwnd_child2. */
10809 SET_EXPECT(prov_callback_base_hwnd);
10810 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10811 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10812 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10813 hr = UiaNavigate(node2, NavigateDirection_PreviousSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10814 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10815 ok(!!out_req, "out_req == NULL\n");
10816 ok(!!tree_struct, "tree_struct == NULL\n");
10817 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10818 CHECK_CALLED(prov_callback_base_hwnd);
10819 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10820
10821 hr = SafeArrayGetElement(out_req, idx, &v);
10822 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10823
10824 hr = UiaHUiaNodeFromVariant(&v, &node3);
10825 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10826 IUnknown_AddRef((IUnknown *)node3);
10827
10828 exp_lbound[0] = exp_lbound[1] = 0;
10829 exp_elems[0] = exp_elems[1] = 1;
10830 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10831
10832 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10833 ok_method_sequence(nav_seq5, "nav_seq5");
10834
10835 SafeArrayDestroy(out_req);
10836 SysFreeString(tree_struct);
10837
10838 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
10839 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10840
10841 /* Navigate to Provider_nc_child2. */
10842 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10843 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child2", TRUE);
10844 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10845 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10846 ok(!!out_req, "out_req == NULL\n");
10847 ok(!!tree_struct, "tree_struct == NULL\n");
10848 ok(Provider_nc_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
10849
10850 hr = SafeArrayGetElement(out_req, idx, &v);
10851 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10852
10853 hr = UiaHUiaNodeFromVariant(&v, &node3);
10854 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10855 IUnknown_AddRef((IUnknown *)node3);
10856
10857 exp_lbound[0] = exp_lbound[1] = 0;
10858 exp_elems[0] = exp_elems[1] = 1;
10859 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10860
10861 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10862 ok_method_sequence(nav_seq6, "nav_seq6");
10863
10864 SafeArrayDestroy(out_req);
10865 SysFreeString(tree_struct);
10866
10867 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10868 ok(Provider_nc_child.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
10869 node2 = node3;
10870
10871 /* Navigate to Provider_child. */
10872 SET_EXPECT(prov_callback_base_hwnd);
10873 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10874 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10875 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10876 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10877 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10878 ok(!!out_req, "out_req == NULL\n");
10879 ok(!!tree_struct, "tree_struct == NULL\n");
10880 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10881 CHECK_CALLED(prov_callback_base_hwnd);
10882 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10883
10884 hr = SafeArrayGetElement(out_req, idx, &v);
10885 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10886
10887 hr = UiaHUiaNodeFromVariant(&v, &node3);
10888 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10889 IUnknown_AddRef((IUnknown *)node3);
10890
10891 exp_lbound[0] = exp_lbound[1] = 0;
10892 exp_elems[0] = exp_elems[1] = 1;
10893 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10894
10895 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10896 ok_method_sequence(nav_seq7, "nav_seq7");
10897
10898 SafeArrayDestroy(out_req);
10899 SysFreeString(tree_struct);
10900
10901 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10902 ok(Provider_nc_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
10903 node2 = node3;
10904
10905 /* Navigate to Provider_child2. */
10906 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10907 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
10908 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10909 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10910 ok(!!out_req, "out_req == NULL\n");
10911 ok(!!tree_struct, "tree_struct == NULL\n");
10912 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
10913
10914 hr = SafeArrayGetElement(out_req, idx, &v);
10915 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10916
10917 hr = UiaHUiaNodeFromVariant(&v, &node3);
10918 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10919 IUnknown_AddRef((IUnknown *)node3);
10920
10921 exp_lbound[0] = exp_lbound[1] = 0;
10922 exp_elems[0] = exp_elems[1] = 1;
10923 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10924
10925 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10926 ok_method_sequence(nav_seq8, "nav_seq8");
10927
10928 SafeArrayDestroy(out_req);
10929 SysFreeString(tree_struct);
10930
10931 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10932 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10933 node2 = node3;
10934
10935 /* Try navigating to next sibling on the final child of the node. */
10936 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
10937 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
10938 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
10939 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10940 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10941 ok_method_sequence(nav_seq9, "nav_seq9");
10942 ok(!out_req, "out_req != NULL\n");
10943 ok(!tree_struct, "tree_struct != NULL\n");
10944 todo_wine CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
10945 todo_wine CHECK_CALLED_MULTI(prov_callback_base_hwnd, 2);
10946 todo_wine CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, 2);
10947
10948 SafeArrayDestroy(out_req);
10949 SysFreeString(tree_struct);
10950 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10951 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
10952
10953 /* Navigate to Provider_child2, last child. */
10954 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10955 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
10957 tree_struct = NULL;
10958 out_req = NULL;
10959 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10960 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10961 ok(!!out_req, "out_req == NULL\n");
10962 ok(!!tree_struct, "tree_struct == NULL\n");
10963 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10964
10965 exp_lbound[0] = exp_lbound[1] = 0;
10966 exp_elems[0] = exp_elems[1] = 1;
10967 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10968
10969 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10970 ok_method_sequence(nav_seq10, "nav_seq10");
10971
10972 SafeArrayDestroy(out_req);
10973 SysFreeString(tree_struct);
10974
10975 /*
10976 * If the child we navigate to from a parent isn't considered the "parent
10977 * link" of it's HUIANODE, it is skipped. Here, we set Provider_hwnd_child
10978 * to an HWND provider, and set its main provider as Provider, which is
10979 * the parent link of the node.
10980 */
10981 Provider_hwnd_child.hwnd = hwnd;
10982 Provider_hwnd_child.prov_opts = ProviderOptions_ClientSideProvider;
10983 Provider.parent = &Provider2.IRawElementProviderFragment_iface;
10984 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10985 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10986 tree_struct = NULL;
10987 out_req = NULL;
10988 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10989 SET_EXPECT(prov_callback_nonclient);
10990 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10991 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10992 ok(!!out_req, "out_req == NULL\n");
10993 ok(!!tree_struct, "tree_struct == NULL\n");
10994 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10995 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10996 CHECK_CALLED(prov_callback_nonclient);
10997
10998 hr = SafeArrayGetElement(out_req, idx, &v);
10999 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11000
11001 hr = UiaHUiaNodeFromVariant(&v, &node2);
11002 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11003 IUnknown_AddRef((IUnknown *)node2);
11004
11005 exp_lbound[0] = exp_lbound[1] = 0;
11006 exp_elems[0] = exp_elems[1] = 1;
11007 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11008
11009 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11010 ok_method_sequence(nav_seq11, "nav_seq11");
11011
11012 SafeArrayDestroy(out_req);
11013 SysFreeString(tree_struct);
11014
11015 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11016 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
11017
11018 /*
11019 * Same test as before, except with NavigateDirection_LastChild. This will
11020 * end up with Provider_nc as the parent link for the node instead of
11021 * Provider_child2.
11022 */
11023 Provider_child2.hwnd = hwnd;
11024 Provider_child2.ignore_hwnd_prop = TRUE;
11025 Provider_child2.parent = NULL;
11026 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
11028 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11029 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11030 tree_struct = NULL;
11031 out_req = NULL;
11032 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
11033 SET_EXPECT(prov_callback_nonclient);
11034 SET_EXPECT(prov_callback_base_hwnd);
11035 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
11036 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11037 ok(!!out_req, "out_req == NULL\n");
11038 ok(!!tree_struct, "tree_struct == NULL\n");
11039 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
11040 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
11041 CHECK_CALLED(prov_callback_nonclient);
11042 CHECK_CALLED(prov_callback_base_hwnd);
11043
11044 hr = SafeArrayGetElement(out_req, idx, &v);
11045 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11046
11047 hr = UiaHUiaNodeFromVariant(&v, &node2);
11048 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11049 IUnknown_AddRef((IUnknown *)node2);
11050
11051 exp_lbound[0] = exp_lbound[1] = 0;
11052 exp_elems[0] = exp_elems[1] = 1;
11053 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11054
11055 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11056 ok_method_sequence(nav_seq12, "nav_seq12");
11057
11058 SafeArrayDestroy(out_req);
11059 SysFreeString(tree_struct);
11060
11061 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11062 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
11063
11064 Provider_child2.hwnd = NULL;
11065 Provider_child2.ignore_hwnd_prop = FALSE;
11067
11068 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11069 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11070 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
11071 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
11072
11073 /* Create a node with Provider_nc as the parent link. */
11074 Provider.parent = Provider_hwnd.parent = NULL;
11075 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
11077 Provider2.hwnd = NULL;
11078
11079 node = (void *)0xdeadbeef;
11080 /* Only sent on Win7. */
11081 SET_EXPECT(winproc_GETOBJECT_CLIENT);
11082 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
11083 SET_EXPECT(prov_callback_base_hwnd);
11084 SET_EXPECT(prov_callback_nonclient);
11086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11087 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11088 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
11089 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
11090 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
11091 CHECK_CALLED(prov_callback_base_hwnd);
11092 CHECK_CALLED(prov_callback_nonclient);
11093 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
11094
11095 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
11096 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11098 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
11099 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
11100 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
11101 VariantClear(&v);
11102
11103 ok_method_sequence(nav_seq13, "nav_seq13");
11104
11105 /* Navigate to Provider2, parent of Provider_nc. */
11106 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11107 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider2", TRUE);
11109 tree_struct = NULL;
11110 out_req = NULL;
11111 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
11112 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11113 ok(!!out_req, "out_req == NULL\n");
11114 ok(!!tree_struct, "tree_struct == NULL\n");
11115 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
11116
11117 exp_lbound[0] = exp_lbound[1] = 0;
11118 exp_elems[0] = exp_elems[1] = 1;
11119 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11120
11121 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11122
11123 SafeArrayDestroy(out_req);
11124 SysFreeString(tree_struct);
11125 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
11126 ok_method_sequence(nav_seq14, "nav_seq14");
11127
11128 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11129 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11130 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
11131 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
11132
11133 Provider_hwnd_child.hwnd = NULL;
11134 Provider_hwnd_child.prov_opts = ProviderOptions_ServerSideProvider;
11135 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = FALSE;
11137 prov_root = NULL;
11139
11140 /*
11141 * Conditional navigation for conditions other than ConditionType_True.
11142 */
11146 provider_add_child(&Provider_child2, &Provider_child2_child);
11147 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
11148
11149 hr = UiaNodeFromProvider(&Provider_child2_child_child.IRawElementProviderSimple_iface, &node);
11150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11151 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
11152
11153 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
11154 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11156 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child2_child_child", TRUE);
11157 VariantClear(&v);
11158
11159 ok_method_sequence(nav_seq15, "nav_seq15");
11160
11161 /*
11162 * Navigate from Provider_child2_child_child to a parent that has
11163 * UIA_IsControlElementPropertyId set to FALSE.
11164 */
11165 V_VT(&v) = VT_BOOL;
11166 V_BOOL(&v) = VARIANT_FALSE;
11167 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
11168
11169 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11170 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11172 tree_struct = NULL;
11173 out_req = NULL;
11174 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&prop_cond, &cache_req, &out_req, &tree_struct);
11175 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11176 ok(!out_req, "out_req != NULL\n");
11177 ok(!tree_struct, "tree_struct != NULL\n");
11178 ok_method_sequence(nav_seq16, "nav_seq16");
11179
11180 /* Provider will now return FALSE for UIA_IsControlElementPropertyId. */
11181 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
11182 set_provider_prop_override(&Provider, &prop_override, 1);
11183
11184 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
11185 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11186 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11188 tree_struct = NULL;
11189 out_req = NULL;
11190 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&prop_cond, &cache_req, &out_req, &tree_struct);
11191 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11192 ok(!!out_req, "out_req == NULL\n");
11193 ok(!!tree_struct, "tree_struct == NULL\n");
11194 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11195
11196 exp_lbound[0] = exp_lbound[1] = 0;
11197 exp_elems[0] = exp_elems[1] = 1;
11198 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11199
11200 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11201 ok_method_sequence(nav_seq17, "nav_seq17");
11202 SafeArrayDestroy(out_req);
11203 SysFreeString(tree_struct);
11204
11205 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11206 ok(Provider_child2_child_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
11207
11210 UnregisterClassA("UiaNavigate class", NULL);
11211}
11212
11213static void set_find_params(struct UiaFindParams *params, int max_depth, BOOL find_first, BOOL exclude_root,
11214 struct UiaCondition *find_cond)
11215{
11216 params->MaxDepth = max_depth;
11217 params->FindFirst = find_first;
11218 params->ExcludeRoot = exclude_root;
11219 params->pFindCondition = find_cond;
11220}
11221
11222static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count)
11223{
11224 prov->prop_override = override;
11225 prov->prop_override_count = count;
11226}
11227
11228static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val)
11229{
11230 override->prop_id = prop_id;
11231 override->val = *val;
11232}
11233
11234static void set_provider_win_event_handler_respond_prov(struct Provider *prov, IRawElementProviderSimple *responder_prov,
11235 int responder_event)
11236{
11238
11239 data->responder_prov = responder_prov;
11240 data->responder_event = responder_event;
11241}
11242
11245{
11247
11248 data->exp_win_event_id = exp_win_event_id;
11249 data->exp_win_event_hwnd = exp_win_event_hwnd;
11250 data->exp_win_event_obj_id = exp_win_event_obj_id;
11251 data->exp_win_event_child_id = exp_win_event_child_id;
11252}
11253
11254static void set_provider_runtime_id(struct Provider *prov, int val, int val2)
11255{
11256 prov->runtime_id[0] = val;
11257 prov->runtime_id[1] = val2;
11258}
11259
11260static void set_provider_method_event_data(struct Provider *prov, HANDLE event_handle, int method_id)
11261{
11263 prov->method_call_event_method_id = method_id;
11264}
11265
11267{
11269}
11270
11271static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links)
11272{
11273 prov->prov_opts = prov_opts;
11274 prov->hwnd = hwnd;
11276 prov->expected_tid = 0;
11277 prov->runtime_id[0] = prov->runtime_id[1] = 0;
11278 prov->last_call_tid = 0;
11279 prov->ignore_hwnd_prop = FALSE;
11280 prov->override_hwnd = NULL;
11281 prov->prop_override = NULL;
11282 prov->prop_override_count = 0;
11283 memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect));
11284 memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data));
11285 memset(&prov->legacy_acc_pattern_data, 0, sizeof(prov->legacy_acc_pattern_data));
11286 prov->focus_prov = NULL;
11287 prov->embedded_frag_roots = NULL;
11288 prov->embedded_frag_roots_count = 0;
11290 memset(&prov->win_event_handler_data, 0, sizeof(prov->win_event_handler_data));
11292 prov->method_call_event_method_id = -1;
11293 if (initialize_nav_links)
11294 {
11295 prov->frag_root = NULL;
11296 prov->parent = prov->prev_sibling = prov->next_sibling = prov->first_child = prov->last_child = NULL;
11297 }
11298}
11299
11300static void initialize_provider_tree(BOOL initialize_nav_links)
11301{
11304 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11305 initialize_provider(&Provider_child_child2, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11307 initialize_provider(&Provider_child2_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11308 initialize_provider(&Provider_child2_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11309}
11310
11311static void provider_add_child(struct Provider *prov, struct Provider *child)
11312{
11313 if (!prov->first_child)
11314 {
11315 prov->first_child = prov->last_child = &child->IRawElementProviderFragment_iface;
11316 child->next_sibling = child->prev_sibling = NULL;
11317 }
11318 else
11319 {
11320 struct Provider *tmp = impl_from_ProviderFragment(prov->last_child);
11321
11322 tmp->next_sibling = &child->IRawElementProviderFragment_iface;
11323 child->prev_sibling = prov->last_child;
11324 prov->last_child = &child->IRawElementProviderFragment_iface;
11325 }
11326
11328 child->frag_root = prov->frag_root;
11329}
11330
11331#define test_find_sa_results( tree_structs, offsets, exp_elems, exp_tree_struct, exp_offsets ) \
11332 test_find_sa_results_( (tree_structs), (offsets), (exp_elems), (exp_tree_struct), (exp_offsets), __FILE__, __LINE__)
11333static void test_find_sa_results_(SAFEARRAY *tree_structs, SAFEARRAY *offsets, LONG exp_elems,
11334 const WCHAR **exp_tree_struct, int *exp_offset, const char *file, int line)
11335{
11336 LONG lbound, ubound, elems;
11337 HRESULT hr;
11338 VARTYPE vt;
11339 UINT dims;
11340 LONG i;
11341
11342 /* Tree structures SA. */
11343 hr = SafeArrayGetVartype(tree_structs, &vt);
11344 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11345 ok_(file, line)(vt == VT_BSTR, "Unexpected tree structures sa vt %d\n", vt);
11346 dims = SafeArrayGetDim(tree_structs);
11347 ok_(file, line)(dims == 1, "Unexpected tree structures sa dims %d\n", dims);
11348
11349 lbound = ubound = elems = 0;
11350 hr = SafeArrayGetLBound(tree_structs, 1, &lbound);
11351 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
11352 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
11353
11354 hr = SafeArrayGetUBound(tree_structs, 1, &ubound);
11355 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
11356
11357 elems = (ubound - lbound) + 1;
11358 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
11359
11360 /* Offsets SA. */
11362 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11363 ok_(file, line)(vt == VT_I4, "Unexpected offsets sa vt %d\n", vt);
11364 dims = SafeArrayGetDim(offsets);
11365 ok_(file, line)(dims == 1, "Unexpected offsets sa dims %d\n", dims);
11366
11367 lbound = ubound = elems = 0;
11368 hr = SafeArrayGetLBound(offsets, 1, &lbound);
11369 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
11370 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
11371
11372 hr = SafeArrayGetUBound(offsets, 1, &ubound);
11373 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
11374
11375 elems = (ubound - lbound) + 1;
11376 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
11377
11378 for (i = 0; i < exp_elems; i++)
11379 {
11380 BSTR tree_struct;
11381 int offset;
11382
11383 hr = SafeArrayGetElement(tree_structs, &i, &tree_struct);
11384 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
11385 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct[i]), "Unexpected tree structure %s\n", debugstr_w(tree_struct));
11386 SysFreeString(tree_struct);
11387
11389 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
11390 ok_(file, line)(exp_offset[i] == offset, "Unexpected offset %d\n", offset);
11391 }
11392}
11393
11394static const struct prov_method_sequence find_seq1[] = {
11396 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11398 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11399 NODE_CREATE_SEQ(&Provider_child_child),
11400 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11401 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11402 NODE_CREATE_SEQ(&Provider_child_child2),
11403 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11404 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11405 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11407 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11409 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11410 NODE_CREATE_SEQ(&Provider_child2_child),
11411 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11412 NODE_CREATE_SEQ(&Provider_child2_child_child),
11413 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11414 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11415 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11416 NODE_CREATE_SEQ(&Provider_child2_child),
11417 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11418 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11420 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11421 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11423 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11424 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11425 /* Only done on Win10v1507 and below. */
11426 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11429 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11430 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11432 { &Provider_child2_child, FRAG_GET_RUNTIME_ID },
11433 { &Provider_child2_child_child, FRAG_GET_RUNTIME_ID },
11434 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11435 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11436 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11437 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11438 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11439 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11440 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11441 { 0 },
11442};
11443
11444static const struct prov_method_sequence find_seq2[] = {
11446 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11448 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11450 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11451 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11453 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11454 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11455 /* Only done on Win10v1507 and below. */
11456 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11460 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11461 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11462 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11463 { 0 },
11464};
11465
11466static const struct prov_method_sequence find_seq3[] = {
11468 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11470 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11472 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11473 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11475 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11476 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11477 /* Only done on Win10v1507 and below. */
11478 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11481 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11482 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11483 { 0 },
11484};
11485
11486static const struct prov_method_sequence find_seq4[] = {
11488 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11491 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11492 { 0 },
11493};
11494
11495static const struct prov_method_sequence find_seq5[] = {
11497 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11499 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11500 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11502 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11506 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11507 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11508 { 0 },
11509};
11510
11511static const struct prov_method_sequence find_seq6[] = {
11515 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11516 { 0 },
11517};
11518
11519static const struct prov_method_sequence find_seq7[] = {
11521 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11522 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11523 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11525 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11526 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11527 NODE_CREATE_SEQ(&Provider_child_child),
11528 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11529 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11530 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11531 NODE_CREATE_SEQ(&Provider_child_child2),
11532 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11533 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11534 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11535 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11537 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11539 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11540 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11541 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11542 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11544 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11545 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11546 /* Only done on Win10v1507 and below. */
11547 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11549 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11550 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11552 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11553 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11554 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11555 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11556 { 0 },
11557};
11558
11559static const struct prov_method_sequence find_seq8[] = {
11561 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11562 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11563 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11565 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11566 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11567 NODE_CREATE_SEQ(&Provider_child_child),
11568 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11569 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11570 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11571 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11572 NODE_CREATE_SEQ(&Provider_child_child2),
11573 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11574 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11575 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11576 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11577 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11580 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11582 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11583 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11585 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11586 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11590 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11591 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11593 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11594 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11595 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11596 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11597 { 0 },
11598};
11599
11600static const struct prov_method_sequence find_seq9[] = {
11601 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11602 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11603 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11604 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11605 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11606 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11608 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11610 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11611 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11613 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11614 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11615 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11616 NODE_CREATE_SEQ(&Provider_child2_child),
11617 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11618 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11619 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11620 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11622 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11623 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11625 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11627 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11628 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11629 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11630 /* Only done on Win10v1507 and below. */
11631 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11632 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11634 { &Provider_child2_child, FRAG_GET_RUNTIME_ID },
11635 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11636 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11637 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11638 { 0 },
11639};
11640
11641static const struct prov_method_sequence find_seq10[] = {
11643 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11644 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11646 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11647 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11648 NODE_CREATE_SEQ(&Provider_child_child),
11649 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11650 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11651 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11652 NODE_CREATE_SEQ(&Provider_child_child2),
11653 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11654 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11655 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11656 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11658 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11660 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11661 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11662 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11663 NODE_CREATE_SEQ(&Provider_child2_child),
11664 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11665 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11666 NODE_CREATE_SEQ(&Provider_child2_child_child),
11667 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11668 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11669 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11670 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11671 NODE_CREATE_SEQ(&Provider_child2_child),
11672 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11673 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11675 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11676 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11678 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11679 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11680 /* Only done on Win10v1507 and below. */
11681 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11683 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11684 { 0 },
11685};
11686
11687static const struct prov_method_sequence find_seq11[] = {
11689 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11690 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11692 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11693 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11694 NODE_CREATE_SEQ(&Provider_child_child),
11695 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11696 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11697 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11698 NODE_CREATE_SEQ(&Provider_child_child2),
11699 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11700 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11701 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11702 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11703 { 0 },
11704};
11705
11706static void test_UiaFind(void)
11707{
11708 struct Provider_prop_override prop_override;
11709 LONG exp_lbound[2], exp_elems[2], idx[2], i;
11710 SAFEARRAY *out_req, *offsets, *tree_structs;
11711 struct node_provider_desc exp_node_desc[7];
11712 struct UiaPropertyCondition prop_cond[2];
11713 struct UiaCacheRequest cache_req;
11714 struct UiaFindParams find_params;
11715 const WCHAR *exp_tree_struct[7];
11716 int exp_offset[7], cache_prop;
11717 HUIANODE node, node2;
11718 HRESULT hr;
11719 VARIANT v;
11720
11722
11727 provider_add_child(&Provider_child, &Provider_child_child);
11728 provider_add_child(&Provider_child, &Provider_child_child2);
11729 provider_add_child(&Provider_child2, &Provider_child2_child);
11730 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
11731
11732 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11734
11736 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11737 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11738
11739 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
11740 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11742 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
11743 VariantClear(&v);
11744
11746
11747 /*
11748 * Maximum find depth of -1, find first is FALSE, exclude root is FALSE. A
11749 * maximum depth of -1 will search the entire tree.
11750 */
11751 out_req = offsets = tree_structs = NULL;
11752 cache_prop = UIA_RuntimeIdPropertyId;
11753 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11755 set_find_params(&find_params, -1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11756 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11757 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11758 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11759 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
11760 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
11761 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11762 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
11763 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
11764
11765 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11766 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
11767 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child", TRUE);
11768 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child_child2", TRUE);
11769 add_provider_desc(&exp_node_desc[4], L"Main", L"Provider_child2", TRUE);
11770 add_provider_desc(&exp_node_desc[5], L"Main", L"Provider_child2_child", TRUE);
11771 add_provider_desc(&exp_node_desc[6], L"Main", L"Provider_child2_child_child", TRUE);
11772 exp_lbound[0] = exp_lbound[1] = 0;
11773 exp_elems[0] = 7;
11774 exp_elems[1] = 2;
11775
11776 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11777
11778 for (i = 0; i < exp_elems[0]; i++)
11779 {
11780 exp_offset[i] = i;
11781 exp_tree_struct[i] = L"P)";
11782 }
11783 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11784 ok_method_sequence(find_seq1, "find_seq1");
11785
11786 SafeArrayDestroy(out_req);
11788 SafeArrayDestroy(tree_structs);
11789
11790 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11792
11793 /*
11794 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
11795 */
11796 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11798 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11799 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11801 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11802 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11803
11804 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11805 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
11806 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2", TRUE);
11807 exp_lbound[0] = exp_lbound[1] = 0;
11808 exp_elems[0] = 3;
11809 exp_elems[1] = 2;
11810
11811 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11812
11813 for (i = 0; i < exp_elems[0]; i++)
11814 {
11815 exp_offset[i] = i;
11816 exp_tree_struct[i] = L"P)";
11817 }
11818
11819 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11820 ok_method_sequence(find_seq2, "find_seq2");
11821
11822 SafeArrayDestroy(out_req);
11824 SafeArrayDestroy(tree_structs);
11825
11826 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11828
11829 /*
11830 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
11831 */
11832 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11834 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
11835 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11836 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11837 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11838 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11839
11840 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11841 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
11842 exp_lbound[0] = exp_lbound[1] = 0;
11843 exp_elems[0] = 2;
11844 exp_elems[1] = 2;
11845
11846 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11847
11848 for (i = 0; i < exp_elems[0]; i++)
11849 {
11850 exp_offset[i] = i;
11851 exp_tree_struct[i] = L"P)";
11852 }
11853 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11854 ok_method_sequence(find_seq3, "find_seq3");
11855
11856 SafeArrayDestroy(out_req);
11858 SafeArrayDestroy(tree_structs);
11859
11860 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11862
11863 /*
11864 * Maximum find depth of 1, find first is TRUE, exclude root is TRUE. Will
11865 * retrieve only Provider_child.
11866 */
11867 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11869 set_find_params(&find_params, 1, TRUE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
11870 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11872 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11873
11874 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11875 exp_lbound[0] = exp_lbound[1] = 0;
11876 exp_elems[0] = 1;
11877 exp_elems[1] = 2;
11878
11879 idx[0] = idx[1] = 0;
11880 hr = SafeArrayGetElement(out_req, idx, &v);
11881 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11882
11883 /* node2 is now set as Provider_child. */
11884 hr = UiaHUiaNodeFromVariant(&v, &node2);
11885 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11886 IUnknown_AddRef((IUnknown *)node2);
11887
11888 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11889
11890 for (i = 0; i < exp_elems[0]; i++)
11891 {
11892 exp_offset[i] = i;
11893 exp_tree_struct[i] = L"P)";
11894 }
11895 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11896 ok_method_sequence(find_seq4, "find_seq4");
11897
11898 SafeArrayDestroy(out_req);
11900 SafeArrayDestroy(tree_structs);
11901
11902 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11904
11905 /*
11906 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
11907 * Provider_child doesn't have a runtime id for UI Automation to use as a
11908 * way to check if it has navigated back to the node that began the
11909 * search, so it will get siblings.
11910 */
11911 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11913 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11914 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11916 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11917
11918 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11919 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
11920 exp_lbound[0] = exp_lbound[1] = 0;
11921 exp_elems[0] = 2;
11922 exp_elems[1] = 2;
11923
11924 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11925
11926 for (i = 0; i < exp_elems[0]; i++)
11927 {
11928 exp_offset[i] = i;
11929 exp_tree_struct[i] = L"P)";
11930 }
11931 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11932 ok_method_sequence(find_seq5, "find_seq5");
11933
11934 SafeArrayDestroy(out_req);
11936 SafeArrayDestroy(tree_structs);
11937
11938 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11940
11941 /*
11942 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
11943 * Provider_child has a runtime id for UI Automation to use as a
11944 * way to check if it has navigated back to the node that began the
11945 * search, so it will stop at Provider_child.
11946 */
11947 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
11948 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11950 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11951 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11952 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11953
11954 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11955 exp_lbound[0] = exp_lbound[1] = 0;
11956 exp_elems[0] = 1;
11957 exp_elems[1] = 2;
11958
11959 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11960
11961 for (i = 0; i < exp_elems[0]; i++)
11962 {
11963 exp_offset[i] = i;
11964 exp_tree_struct[i] = L"P)";
11965 }
11966 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11967 ok_method_sequence(find_seq6, "find_seq6");
11968
11969 SafeArrayDestroy(out_req);
11971 SafeArrayDestroy(tree_structs);
11972
11973 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11974 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
11975
11977 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11979
11980 /*
11981 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
11982 * The cache request view condition is used to determine tree depth, if an
11983 * element matches the cache request view condition, depth is incremented.
11984 * Since Provider_child does not, Provider_child_child, Provider_child_child2,
11985 * and Provider_child2 are all considered to be at depth 1.
11986 */
11987 V_VT(&v) = VT_BOOL;
11988 V_BOOL(&v) = VARIANT_FALSE;
11989 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11990 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
11991
11992 V_VT(&v) = VT_BOOL;
11993 V_BOOL(&v) = VARIANT_TRUE;
11994 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11995
11996 set_provider_prop_override(&Provider, &prop_override, 1);
11997 set_provider_prop_override(&Provider_child2, &prop_override, 1);
11998 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
11999 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12000
12001 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12003 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12004 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12005 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12006 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
12007 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12008 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12009
12010 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
12011 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
12012 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
12013 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
12014 exp_lbound[0] = exp_lbound[1] = 0;
12015 exp_elems[0] = 4;
12016 exp_elems[1] = 2;
12017
12018 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12019
12020 for (i = 0; i < exp_elems[0]; i++)
12021 {
12022 exp_offset[i] = i;
12023 exp_tree_struct[i] = L"P)";
12024 }
12025 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12026 ok_method_sequence(find_seq7, "find_seq7");
12027
12028 SafeArrayDestroy(out_req);
12030 SafeArrayDestroy(tree_structs);
12031
12033 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12035
12036 /*
12037 * Same test as before, except Provider has a runtime id.
12038 */
12039 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
12040 V_VT(&v) = VT_BOOL;
12041 V_BOOL(&v) = VARIANT_FALSE;
12042 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12043 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12044
12045 V_VT(&v) = VT_BOOL;
12046 V_BOOL(&v) = VARIANT_TRUE;
12047 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12048
12049 set_provider_prop_override(&Provider, &prop_override, 1);
12050 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12051 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
12052 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12053
12054 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12056 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12057 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12058 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12059 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
12060 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12061 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12062
12063 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
12064 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
12065 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
12066 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
12067 exp_lbound[0] = exp_lbound[1] = 0;
12068 exp_elems[0] = 4;
12069 exp_elems[1] = 2;
12070
12071 idx[0] = 2;
12072 idx[1] = 0;
12073 hr = SafeArrayGetElement(out_req, idx, &v);
12074 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12075
12076 /* node2 is now set as Provider_child_child2. */
12077 hr = UiaHUiaNodeFromVariant(&v, &node2);
12078 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12079 IUnknown_AddRef((IUnknown *)node2);
12080
12081 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12082
12083 for (i = 0; i < exp_elems[0]; i++)
12084 {
12085 exp_offset[i] = i;
12086 exp_tree_struct[i] = L"P)";
12087 }
12088 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12089 ok_method_sequence(find_seq8, "find_seq8");
12090
12091 SafeArrayDestroy(out_req);
12093 SafeArrayDestroy(tree_structs);
12094
12096 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12098
12099 /*
12100 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
12101 * Starting at Provider_child_child2, find will be able to traverse the
12102 * tree in the same order as it would if we had started at the tree root
12103 * Provider, retrieving Provider_child2 as a sibling and
12104 * Provider_child2_child as a node at depth 1.
12105 */
12106 V_VT(&v) = VT_BOOL;
12107 V_BOOL(&v) = VARIANT_FALSE;
12108 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12109
12110 V_VT(&v) = VT_BOOL;
12111 V_BOOL(&v) = VARIANT_TRUE;
12112 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12113
12114 prop_override.prop_id = UIA_IsContentElementPropertyId;
12115 V_VT(&prop_override.val) = VT_BOOL;
12116 V_BOOL(&prop_override.val) = VARIANT_FALSE;
12117 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12118 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12119 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
12120
12121 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12123 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12124 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12125 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12126 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12127 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
12128
12129 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
12130 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
12131 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2_child", TRUE);
12132 exp_lbound[0] = exp_lbound[1] = 0;
12133 exp_elems[0] = 3;
12134 exp_elems[1] = 2;
12135
12136 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12137
12138 for (i = 0; i < exp_elems[0]; i++)
12139 {
12140 exp_offset[i] = i;
12141 exp_tree_struct[i] = L"P)";
12142 }
12143 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12144 ok_method_sequence(find_seq9, "find_seq9");
12145
12146 SafeArrayDestroy(out_req);
12148 SafeArrayDestroy(tree_structs);
12149
12151 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12153
12154 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
12155 ok(Provider_child_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12156
12157 /*
12158 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
12159 * Exclude root applies to the first node that matches the view
12160 * condition, and not the node that is passed into UiaFind(). Since
12161 * Provider doesn't match our view condition here, Provider_child will be
12162 * excluded.
12163 */
12164 V_VT(&v) = VT_BOOL;
12165 V_BOOL(&v) = VARIANT_FALSE;
12166 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12167 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12168
12169 V_VT(&v) = VT_BOOL;
12170 V_BOOL(&v) = VARIANT_TRUE;
12171 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12172
12173 set_provider_prop_override(&Provider_child, &prop_override, 1);
12174 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12175
12176 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12178 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&prop_cond[1]);
12179 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12180 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12181 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12182
12183 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
12184 exp_lbound[0] = exp_lbound[1] = 0;
12185 exp_elems[0] = 1;
12186 exp_elems[1] = 2;
12187
12188 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12189
12190 for (i = 0; i < exp_elems[0]; i++)
12191 {
12192 exp_offset[i] = i;
12193 exp_tree_struct[i] = L"P)";
12194 }
12195 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12196
12197 ok_method_sequence(find_seq10, "find_seq10");
12198
12199 SafeArrayDestroy(out_req);
12201 SafeArrayDestroy(tree_structs);
12202
12204 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12206
12207 /*
12208 * Maximum find depth of -1, find first is TRUE, exclude root is FALSE.
12209 * Provider_child_child2 is the only element in the tree to match our
12210 * condition.
12211 */
12212 V_VT(&v) = VT_BOOL;
12213 V_BOOL(&v) = VARIANT_FALSE;
12214 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12215 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12216
12217 V_VT(&v) = VT_BOOL;
12218 V_BOOL(&v) = VARIANT_TRUE;
12219 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12220
12221 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12222
12223 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12225 set_find_params(&find_params, -1, TRUE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12226 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12228 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12229
12230 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
12231 exp_lbound[0] = exp_lbound[1] = 0;
12232 exp_elems[0] = 1;
12233 exp_elems[1] = 2;
12234
12235 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12236
12237 for (i = 0; i < exp_elems[0]; i++)
12238 {
12239 exp_offset[i] = i;
12240 exp_tree_struct[i] = L"P)";
12241 }
12242 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12243 ok_method_sequence(find_seq11, "find_seq11");
12244
12245 SafeArrayDestroy(out_req);
12247 SafeArrayDestroy(tree_structs);
12248
12250
12251 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
12252 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12253
12255}
12256
12261 const char *file;
12262 int line;
12263
12265};
12266
12268{
12270 IUnknown *proxy_iface, *unk, *unk2;
12271 HRESULT hr;
12272
12274
12275 proxy_iface = unk = unk2 = NULL;
12276 hr = CoGetInterfaceAndReleaseStream(data->marshal_stream, data->iface_iid, (void **)&proxy_iface);
12277 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12278
12279 hr = IUnknown_QueryInterface(data->iface, &IID_IUnknown, (void **)&unk);
12280 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12281 ok_(data->file, data->line)(!!unk, "unk == NULL\n");
12282
12283 hr = IUnknown_QueryInterface(proxy_iface, &IID_IUnknown, (void **)&unk2);
12284 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12285 ok_(data->file, data->line)(!!unk2, "unk2 == NULL\n");
12286
12287 if (data->expect_proxy)
12288 ok_(data->file, data->line)(unk != unk2, "unk == unk2\n");
12289 else
12290 ok_(data->file, data->line)(unk == unk2, "unk != unk2\n");
12291
12292 IUnknown_Release(proxy_iface);
12293 IUnknown_Release(unk);
12294 IUnknown_Release(unk2);
12295
12297 return 0;
12298}
12299
12301 int line)
12302{
12303 struct marshal_thread_data data = { NULL, iid, expect_proxy, file, line };
12304 HANDLE thread;
12305 HRESULT hr;
12306
12307 hr = IUnknown_QueryInterface(iface, data.iface_iid, (void **)&data.iface);
12308 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12309
12310 hr = CoMarshalInterThreadInterfaceInStream(data.iface_iid, data.iface, &data.marshal_stream);
12311 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12312
12315 {
12316 MSG msg;
12317 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
12318 {
12321 }
12322 }
12324
12325 IUnknown_Release(data.iface);
12326}
12327
12328static HWND create_test_hwnd(const char *class_name)
12329{
12330 WNDCLASSA cls = { 0 };
12331
12334 cls.lpszClassName = class_name;
12335 RegisterClassA(&cls);
12336
12337 return CreateWindowA(class_name, "Test window", WS_OVERLAPPEDWINDOW,
12338 0, 0, 100, 100, NULL, NULL, NULL, NULL);
12339}
12340
12341static HWND create_child_test_hwnd(const char *class_name, HWND parent)
12342{
12343 WNDCLASSA cls = { 0 };
12344
12347 cls.lpszClassName = class_name;
12348 RegisterClassA(&cls);
12349
12350 return CreateWindowA(class_name, "Test child window", WS_CHILD,
12351 0, 0, 50, 50, parent, NULL, NULL, NULL);
12352}
12353
12354static void destroy_test_hwnd(HWND hwnd, const char *class_name, const char *child_class_name)
12355{
12357 UnregisterClassA(class_name, NULL);
12358 if (child_class_name)
12359 UnregisterClassA(child_class_name, NULL);
12360}
12361
12362static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd, BOOL block_hwnd_provs)
12363{
12364 IUIAutomationElement *element;
12365 HRESULT hr;
12366 VARIANT v;
12367
12368 if (block_hwnd_provs)
12369 {
12370 SET_EXPECT(prov_callback_base_hwnd);
12371 SET_EXPECT(prov_callback_nonclient);
12374 }
12375 else
12377
12380 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
12381 /* Only sent on Win7. */
12382 SET_EXPECT(winproc_GETOBJECT_CLIENT);
12383 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &element);
12384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12385 ok(!!element, "element == NULL\n");
12386 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
12387 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
12388 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
12389 if (block_hwnd_provs)
12390 {
12391 CHECK_CALLED(prov_callback_base_hwnd);
12392 CHECK_CALLED(prov_callback_nonclient);
12393 }
12394
12395 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
12396 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12397
12399 if (!block_hwnd_provs)
12400 {
12401 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
12404 }
12405 else
12406 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
12407
12408 VariantClear(&v);
12409 ok_method_sequence(node_from_hwnd2, "create_test_element");
12411
12412 return element;
12413}
12414
12415static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8)
12416{
12417 HWND hwnd = create_test_hwnd("test_ElementFromHandle class");
12418 IUIAutomationElement2 *element_2;
12419 IUIAutomationElement *element;
12420 HRESULT hr;
12421
12423 hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2);
12424 if (is_cui8)
12425 {
12426 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12427 ok(!!element_2, "element_2 == NULL\n");
12428 IUIAutomationElement2_Release(element_2);
12429 }
12430 else
12431 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
12432
12433 /*
12434 * The IUIAutomationElement interface uses the free threaded marshaler, so
12435 * no actual proxy interface will be created.
12436 */
12437 check_interface_marshal_proxy_creation((IUnknown *)element, &IID_IUIAutomationElement, FALSE);
12438
12439 IUIAutomationElement_Release(element);
12440 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12441
12443 UnregisterClassA("test_ElementFromHandle class", NULL);
12444 prov_root = NULL;
12445}
12446
12447static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
12448{
12449 HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class");
12450 const struct uia_element_property *elem_prop;
12451 struct Provider_prop_override prop_override;
12452 IUIAutomationElement *element, *element2;
12453 IUIAutomationElementArray *element_arr;
12454 int i, len, prop_id, tmp_int;
12455 struct UiaRect uia_rect;
12456 IUnknown *unk_ns;
12457 BSTR tmp_bstr;
12458 HRESULT hr;
12459 RECT rect;
12460 VARIANT v;
12461
12466
12468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12469
12470 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ControlTypePropertyId, TRUE, NULL);
12471 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12472
12473 VariantInit(&v);
12474 V_VT(&v) = VT_BOOL;
12475 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, 1, TRUE, &v);
12476 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12477 ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
12478
12479 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
12480 {
12481 elem_prop = &element_properties[i];
12482
12484 VariantClear(&v);
12485 if (!(prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid)))
12486 {
12487 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
12488 break;
12489 }
12490
12491 winetest_push_context("Element prop_id %d", prop_id);
12492 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
12493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12494 check_uia_prop_val(prop_id, elem_prop->type, &v, TRUE);
12495
12496 /*
12497 * Some properties have special behavior if an invalid value is
12498 * returned, skip them here.
12499 */
12500 if (!elem_prop->skip_invalid)
12501 {
12503 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
12504 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12505 if (SUCCEEDED(hr))
12506 {
12508 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12509 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
12510 VariantClear(&v);
12511 }
12512 }
12513
12515 }
12516
12517 /* Test IUIAutomationElementArray interface behavior. */
12519 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ControllerForPropertyId, TRUE, &v);
12520 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12521 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12522 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
12523 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12524
12525 element_arr = NULL;
12526 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&element_arr);
12527 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12528 ok(!!element_arr, "element_arr == NULL\n");
12529 VariantClear(&v);
12530
12531 hr = IUIAutomationElementArray_get_Length(element_arr, &len);
12532 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12533 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
12534
12535 /* Invalid argument tests. */
12536 hr = IUIAutomationElementArray_get_Length(element_arr, NULL);
12537 ok(hr == E_POINTER, "Unexpected hr %#lx\n", hr);
12538
12539 element2 = (void *)0xdeadbeef;
12540 hr = IUIAutomationElementArray_GetElement(element_arr, len, &element2);
12541 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
12542 /* Pointer isn't cleared. */
12543 ok(!!element2, "element2 == NULL\n");
12544
12545 hr = IUIAutomationElementArray_GetElement(element_arr, -1, &element2);
12546 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
12547 /* Pointer isn't cleared. */
12548 ok(!!element2, "element2 == NULL\n");
12549
12550 hr = IUIAutomationElementArray_GetElement(element_arr, 0, NULL);
12551 ok(hr == E_POINTER, "Unexpected hr %#lx\n", hr);
12552
12553 for (i = 0; i < len; i++)
12554 {
12555 element2 = NULL;
12556 hr = IUIAutomationElementArray_GetElement(element_arr, i, &element2);
12557 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12558 ok(!!element2, "element2 == NULL\n");
12559
12560 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ControlTypePropertyId, TRUE, &v);
12561 ok(hr == S_OK, "element[%d] Unexpected hr %#lx\n", i, hr);
12562 ok(V_VT(&v) == VT_I4, "element[%d] Unexpected VT %d\n", i, V_VT(&v));
12563 ok(V_I4(&v) == uia_i4_prop_val, "element[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
12564
12565 IUIAutomationElement_Release(element2);
12566 VariantClear(&v);
12567 }
12568
12569 IUIAutomationElementArray_Release(element_arr);
12570 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
12571 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
12573
12574 /*
12575 * IUIAutomationElement_get_CurrentControlType tests. If the value
12576 * returned for UIA_ControlTypePropertyId is not a registered control
12577 * type ID, we'll get back UIA_CustomControlTypeId.
12578 */
12579 tmp_int = 0xdeadb33f;
12580 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
12581 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12582
12583 /*
12584 * Win10v1507 and below don't check whether or not the returned control
12585 * type ID is valid.
12586 */
12587 ok(tmp_int == UIA_CustomControlTypeId || broken(tmp_int == 0xdeadbeef), "Unexpected control type %#x\n", tmp_int);
12589
12591 tmp_int = 0xdeadbeef;
12592 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
12593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12594 ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
12597
12598 /* Finally, a valid control type. */
12599 V_VT(&v) = VT_I4;
12600 V_I4(&v) = UIA_HyperlinkControlTypeId;
12601 set_property_override(&prop_override, UIA_ControlTypePropertyId, &v);
12602 set_provider_prop_override(&Provider, &prop_override, 1);
12603 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
12604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12605 ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
12608
12609 /*
12610 * IUIAutomationElement_get_CurrentName tests.
12611 */
12612 tmp_bstr = NULL;
12613 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
12614 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12615 ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
12616 SysFreeString(tmp_bstr);
12618
12619 tmp_bstr = NULL;
12621 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
12622 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12623 ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
12624 SysFreeString(tmp_bstr);
12627
12628 /*
12629 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
12630 * It's the only version with this behavior.
12631 */
12632 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
12633 {
12634 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
12635 goto exit;
12636 }
12637
12638 /*
12639 * IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests.
12640 */
12641 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
12642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12643 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12644 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
12645
12646 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
12647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12648 ok(!!element2, "element2 == NULL\n");
12649 VariantClear(&v);
12650
12651 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
12652 set_uia_rect(&uia_rect, 0, 0, 50, 50);
12653 Provider_child.bounds_rect = uia_rect;
12654 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
12655 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12656 check_uia_rect_val(&v, &uia_rect);
12657 VariantClear(&v);
12658 ok_method_sequence(get_bounding_rect_seq2, "get_bounding_rect_seq2");
12659
12660 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
12661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12662 check_uia_rect_rect_val(&rect, &uia_rect);
12663 memset(&rect, 0, sizeof(rect));
12664 ok_method_sequence(get_bounding_rect_seq3, "get_bounding_rect_seq3");
12665
12666 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
12667 set_uia_rect(&uia_rect, 0, 0, 0, 0);
12668 Provider_child.bounds_rect = uia_rect;
12669 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
12670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12671 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12672 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
12673 VariantClear(&v);
12674 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
12675
12676 /* Returns an all 0 rect. */
12677 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
12678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12679 check_uia_rect_rect_val(&rect, &uia_rect);
12680 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
12681
12682 IUIAutomationElement_Release(element2);
12683 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
12685
12686exit:
12687 IUIAutomationElement_Release(element);
12688 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12689
12691 UnregisterClassA("test_Element_GetPropertyValue class", NULL);
12692}
12693
12695{
12696 static const VARTYPE invalid_int_vts[] = { VT_I8, VT_INT };
12697 int in_arr[3] = { 0xdeadbeef, 0xfeedbeef, 0x1337b33f };
12698 int *out_arr, out_arr_count, i;
12699 LONG lbound, ubound;
12700 SAFEARRAY *sa;
12701 VARTYPE vt;
12702 HRESULT hr;
12703 UINT dims;
12704
12705 /*
12706 * Conversion from VT_I4 SAFEARRAY to native int array.
12707 */
12708 for (i = 0; i < ARRAY_SIZE(invalid_int_vts); i++)
12709 {
12710 vt = invalid_int_vts[i];
12711 sa = SafeArrayCreateVector(vt, 0, 2);
12712 ok(!!sa, "sa == NULL\n");
12713
12714 out_arr_count = 0xdeadbeef;
12715 out_arr = (int *)0xdeadbeef;
12716 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
12717 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12718 ok(!out_arr, "out_arr != NULL\n");
12719 ok(out_arr_count == 0xdeadbeef, "Unexpected out_arr_count %#x\n", out_arr_count);
12721 }
12722
12723 /* Only accepts VT_I4 as an input array type. */
12725 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
12726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12727 ok(out_arr_count == ARRAY_SIZE(uia_i4_arr_prop_val), "Unexpected out_arr_count %#x\n", out_arr_count);
12728 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val); i++)
12729 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]);
12730
12732 CoTaskMemFree(out_arr);
12733
12734 /*
12735 * Conversion from native int array to VT_I4 SAFEARRAY.
12736 */
12737 sa = NULL;
12738 hr = IUIAutomation_IntNativeArrayToSafeArray(uia_iface, in_arr, ARRAY_SIZE(in_arr), &sa);
12739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12740
12742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12743 ok(vt == VT_I4, "Unexpected vt %d.\n", vt);
12744
12745 dims = SafeArrayGetDim(sa);
12746 ok(dims == 1, "Unexpected array dims %d\n", dims);
12747
12748 hr = SafeArrayGetLBound(sa, 1, &lbound);
12749 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
12750 ok(lbound == 0, "Unexpected LBound %#lx\n", lbound);
12751
12752 hr = SafeArrayGetUBound(sa, 1, &ubound);
12753 ok(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
12754 ok(((ubound - lbound) + 1) == ARRAY_SIZE(in_arr), "Unexpected array size %#lx\n", ((ubound - lbound) + 1));
12755
12756 for (i = 0; i < ARRAY_SIZE(in_arr); i++)
12757 {
12758 LONG idx = lbound + i;
12759 int tmp_val;
12760
12761 hr = SafeArrayGetElement(sa, &idx, &tmp_val);
12762 ok(hr == S_OK, "Failed to get element at idx %ld, hr %#lx\n", idx, hr);
12763 ok(tmp_val == in_arr[i], "Expected %d at idx %d, got %d\n", in_arr[i], i, tmp_val);
12764 }
12765
12767}
12768
12770{
12771 *ppv = NULL;
12773 *ppv = iface;
12774 else
12775 return E_NOINTERFACE;
12776
12777 return S_OK;
12778}
12779
12781{
12782 return 2;
12783}
12784
12786{
12787 return 1;
12788}
12789
12790static IUnknownVtbl ObjectVtbl = {
12794};
12796
12798{
12799 IUIAutomationPropertyCondition *prop_cond, *prop_cond2;
12800 IUIAutomationCondition *cond, **cond_arr;
12801 enum PropertyConditionFlags prop_flags;
12802 IUIAutomationBoolCondition *bool_cond;
12803 IUIAutomationNotCondition *not_cond;
12804 IUIAutomationOrCondition *or_cond;
12805 PROPERTYID prop_id;
12806 int child_count;
12807 BOOL tmp_b;
12808 HRESULT hr;
12809 VARIANT v;
12810 ULONG ref;
12811
12812 hr = IUIAutomation_CreateTrueCondition(uia_iface, NULL);
12813 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12814
12815 cond = NULL;
12816 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
12817 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12818 ok(!!cond, "cond == NULL\n");
12819
12820 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
12821 IUIAutomationCondition_Release(cond);
12822 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12823 ok(!!bool_cond, "bool_cond == NULL\n");
12824
12825 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, NULL);
12826 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12827
12828 tmp_b = FALSE;
12829 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
12830 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12831 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
12832 IUIAutomationBoolCondition_Release(bool_cond);
12833
12834 hr = IUIAutomation_CreateFalseCondition(uia_iface, NULL);
12835 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12836
12837 cond = NULL;
12838 hr = IUIAutomation_CreateFalseCondition(uia_iface, &cond);
12839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12840 ok(!!cond, "cond == NULL\n");
12841
12842 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
12843 IUIAutomationCondition_Release(cond);
12844 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12845 ok(!!bool_cond, "bool_cond == NULL\n");
12846
12847 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, NULL);
12848 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12849
12850 tmp_b = TRUE;
12851 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
12852 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12853 ok(tmp_b == FALSE, "tmp_b != FALSE\n");
12854 IUIAutomationBoolCondition_Release(bool_cond);
12855
12856 /*
12857 * IUIAutomationPropertyCondition tests.
12858 */
12859 cond = (void *)0xdeadbeef;
12860 VariantInit(&v);
12861 /* Invalid property ID. */
12862 hr = IUIAutomation_CreatePropertyCondition(uia_iface, 0, v, &cond);
12863 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12864 ok(!cond, "cond != NULL\n");
12865
12866 /* Invalid variant type for property ID. */
12867 cond = (void *)0xdeadbeef;
12868 VariantInit(&v);
12869 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond);
12870 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12871 ok(!cond, "cond != NULL\n");
12872
12873 /* NULL Condition argument. */
12874 V_VT(&v) = VT_I4 | VT_ARRAY;
12876 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, NULL);
12877 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12878
12879 /* Finally, create property condition interface. */
12880 cond = NULL;
12881 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond);
12882 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12883 ok(!!cond, "cond == NULL\n");
12884
12885 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
12886 IUIAutomationCondition_Release(cond);
12887 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12888 ok(!!prop_cond, "prop_cond == NULL\n");
12889
12890 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, NULL);
12891 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12892
12893 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
12894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12895 ok(prop_id == UIA_RuntimeIdPropertyId, "Unexpected prop_id %d.\n", prop_id);
12896
12897 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, NULL);
12898 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12899
12900 VariantClear(&v);
12901 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
12902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12903 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d.\n", V_VT(&v));
12904 ok(!!V_ARRAY(&v), "V_ARRAY(&v) == NULL\n");
12905 VariantClear(&v);
12906
12907 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, NULL);
12908 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12909
12910 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
12911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12912 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
12913
12914 /*
12915 * IUIAutomationNotCondition tests.
12916 */
12917 cond = (void *)0xdeadbeef;
12918
12919 /*
12920 * Passing in an interface that isn't a valid IUIAutomationCondition
12921 * interface.
12922 */
12923 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)&Object, &cond);
12924 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
12925 ok(!cond, "cond != NULL\n");
12926
12927 /* NULL input argument tests. */
12928 cond = (void *)0xdeadbeef;
12929 hr = IUIAutomation_CreateNotCondition(uia_iface, NULL, &cond);
12930 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12931 ok(!cond, "cond != NULL\n");
12932
12933 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)prop_cond, NULL);
12934 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12935
12936 /* Create the IUIAutomationNotCondition with our property condition. */
12937 cond = NULL;
12938 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)prop_cond, &cond);
12939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12940 ok(!!cond, "cond == NULL\n");
12941
12942 /* IUIAutomationNotCondition holds a reference to the passed in condition. */
12943 ref = IUIAutomationPropertyCondition_Release(prop_cond);
12944 ok(ref == 1, "Unexpected ref %ld\n", ref);
12945
12946 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
12947 IUIAutomationCondition_Release(cond);
12948 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12949 ok(!!not_cond, "not_cond == NULL\n");
12950
12951 hr = IUIAutomationNotCondition_GetChild(not_cond, NULL);
12952 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12953
12954 cond = NULL;
12955 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
12956 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12957 ok(iface_cmp((IUnknown *)cond, (IUnknown *)prop_cond), "cond != prop_cond\n");
12958 IUIAutomationCondition_Release(cond);
12959
12960 IUIAutomationNotCondition_Release(not_cond);
12961
12962 /*
12963 * IUIAutomationOrCondition tests.
12964 */
12965 cond = NULL;
12966 VariantInit(&v);
12967 V_VT(&v) = VT_BOOL;
12968 V_BOOL(&v) = VARIANT_FALSE;
12969 /* Create two condition interfaces to use for our IUIAutomationOrCondition. */
12970 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsControlElementPropertyId, v, &cond);
12971 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12972 ok(!!cond, "cond == NULL\n");
12973
12974 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
12975 IUIAutomationCondition_Release(cond);
12976 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12977 ok(!!prop_cond, "prop_cond == NULL\n");
12978
12979 cond = NULL;
12980 VariantInit(&v);
12981 V_VT(&v) = VT_BOOL;
12982 V_BOOL(&v) = VARIANT_TRUE;
12983 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &cond);
12984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12985 ok(!!cond, "cond == NULL\n");
12986
12987 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond2);
12988 IUIAutomationCondition_Release(cond);
12989 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12990 ok(!!prop_cond2, "prop_cond2 == NULL\n");
12991
12992 /* NULL input argument tests. */
12993 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
12994 (IUIAutomationCondition *)prop_cond2, NULL);
12995 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12996
12997 cond = (void *)0xdeadbeef;
12998 hr = IUIAutomation_CreateOrCondition(uia_iface, NULL, (IUIAutomationCondition *)prop_cond2, &cond);
12999 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13000 ok(!cond, "cond != NULL\n");
13001
13002 cond = (void *)0xdeadbeef;
13003 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond, NULL, &cond);
13004 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13005 ok(!cond, "cond != NULL\n");
13006
13007 /* One of the IUIAutomationCondition interfaces are invalid. */
13008 cond = (void *)0xdeadbeef;
13009 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
13010 (IUIAutomationCondition *)&Object, &cond);
13011 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
13012 ok(!cond, "cond != NULL\n");
13013
13014 cond = NULL;
13015 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
13016 (IUIAutomationCondition *)prop_cond2, &cond);
13017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13018 ok(!!cond, "cond == NULL\n");
13019
13020 or_cond = NULL;
13021 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationOrCondition, (void **)&or_cond);
13022 IUIAutomationCondition_Release(cond);
13023 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13024 ok(!!or_cond, "or_cond == NULL\n");
13025
13026 /* References held to both passed in interfaces. */
13027 ref = IUIAutomationPropertyCondition_Release(prop_cond);
13028 ok(ref == 1, "Unexpected ref %ld\n", ref);
13029
13030 ref = IUIAutomationPropertyCondition_Release(prop_cond2);
13031 ok(ref == 1, "Unexpected ref %ld\n", ref);
13032
13033 hr = IUIAutomationOrCondition_get_ChildCount(or_cond, NULL);
13034 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13035
13036 child_count = 0;
13037 hr = IUIAutomationOrCondition_get_ChildCount(or_cond, &child_count);
13038 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13039 ok(child_count == 2, "Unexpected child_count %d.\n", child_count);
13040
13041 child_count = 10;
13042 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, NULL, &child_count);
13043 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13044 ok(child_count == 10, "Unexpected child_count %d.\n", child_count);
13045
13046 cond_arr = (void *)0xdeadbeef;
13047 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, &cond_arr, NULL);
13048 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13049 ok(!cond_arr, "cond_arr != NULL\n");
13050
13051 child_count = 0;
13052 cond_arr = NULL;
13053 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, &cond_arr, &child_count);
13054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13055 ok(child_count == 2, "Unexpected child_count %d.\n", child_count);
13056 ok(!!cond_arr, "cond_arr == NULL\n");
13057
13058 ok(iface_cmp((IUnknown *)cond_arr[0], (IUnknown *)prop_cond), "cond_arr[0] != prop_cond\n");
13059 IUIAutomationCondition_Release(cond_arr[0]);
13060
13061 ok(iface_cmp((IUnknown *)cond_arr[1], (IUnknown *)prop_cond2), "cond_arr[1] != prop_cond2\n");
13062 IUIAutomationCondition_Release(cond_arr[1]);
13063
13064 CoTaskMemFree(cond_arr);
13065 IUIAutomationOrCondition_Release(or_cond);
13066
13067 /*
13068 * Condition used to get the control TreeView. Equivalent to:
13069 * if (!(UIA_IsControlElementPropertyId == VARIANT_FALSE))
13070 */
13071 hr = IUIAutomation_get_ControlViewCondition(uia_iface, NULL);
13072 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13073
13074 cond = NULL;
13075 hr = IUIAutomation_get_ControlViewCondition(uia_iface, &cond);
13076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13077 ok(!!cond, "cond == NULL\n");
13078
13079 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
13080 IUIAutomationCondition_Release(cond);
13081 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13082 ok(!!not_cond, "not_cond == NULL\n");
13083
13084 cond = NULL;
13085 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
13086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13087 ok(!!cond, "cond == NULL\n");
13088
13089 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
13090 IUIAutomationCondition_Release(cond);
13091 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13092 ok(!!prop_cond, "prop_cond == NULL\n");
13093
13094 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
13095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13096 ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
13097
13098 VariantInit(&v);
13099 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
13100 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13101 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
13102 VariantClear(&v);
13103
13104 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
13105 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13106 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
13107
13108 IUIAutomationPropertyCondition_Release(prop_cond);
13109 IUIAutomationNotCondition_Release(not_cond);
13110
13111 /*
13112 * Condition used to get the raw TreeView. Equivalent to:
13113 * if (1)
13114 */
13115 hr = IUIAutomation_get_RawViewCondition(uia_iface, NULL);
13116 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13117
13118 cond = NULL;
13119 hr = IUIAutomation_get_RawViewCondition(uia_iface, &cond);
13120 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13121 ok(!!cond, "cond == NULL\n");
13122
13123 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
13124 IUIAutomationCondition_Release(cond);
13125 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13126 ok(!!bool_cond, "bool_cond == NULL\n");
13127
13128 tmp_b = FALSE;
13129 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
13130 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13131 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
13132 IUIAutomationBoolCondition_Release(bool_cond);
13133}
13134
13136{
13137 IUIAutomationPropertyCondition *prop_cond;
13138 enum PropertyConditionFlags prop_flags;
13139 IUIAutomationCacheRequest *cache_req;
13140 enum AutomationElementMode elem_mode;
13141 IUIAutomationCondition *cond, *cond2;
13142 IUIAutomationNotCondition *not_cond;
13143 enum TreeScope scope;
13144 PROPERTYID prop_id;
13145 HRESULT hr;
13146 VARIANT v;
13147
13148 hr = IUIAutomation_CreateCacheRequest(uia_iface, NULL);
13149 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13150
13151 /*
13152 * CreateCacheRequest returns an IUIAutomationCacheRequest with the
13153 * default cache request values set.
13154 */
13155 cache_req = NULL;
13156 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13157 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13158 ok(!!cache_req, "cache_req == NULL\n");
13159
13160 /*
13161 * TreeScope tests.
13162 */
13163 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, NULL);
13164 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13165
13166 scope = 0;
13167 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
13168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13169 ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
13170
13171 /* Set it to something invalid. */
13172 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, 0);
13173 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13174
13175 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent);
13176 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13177
13178 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors);
13179 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13180
13181 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent | TreeScope_Element);
13182 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13183
13184 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors | TreeScope_Element);
13185 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13186
13187 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, ~(TreeScope_Subtree | TreeScope_Parent | TreeScope_Ancestors));
13188 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13189
13190 /* Invalid values don't change anything. */
13191 scope = 0;
13192 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
13193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13194 ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
13195
13196 /* Now set it to TreeScope_Children. */
13197 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Children);
13198 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13199
13200 scope = 0;
13201 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
13202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13203 todo_wine ok(scope == TreeScope_Children, "Unexpected scope %#x\n", scope);
13204
13205 /*
13206 * TreeFilter tests.
13207 */
13208 cond = NULL;
13209 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, NULL);
13210 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13211
13212 cond = NULL;
13213 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, NULL);
13214 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13215
13216 cond = NULL;
13217 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, (IUIAutomationCondition *)&Object);
13218 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
13219
13220 /* Default IUIAutomationCacheRequest has the ControlView condition. */
13221 cond = NULL;
13222 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond);
13223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13224 ok(!!cond, "cond == NULL\n");
13225
13226 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
13227 IUIAutomationCondition_Release(cond);
13228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13229 ok(!!not_cond, "not_cond == NULL\n");
13230
13231 cond = NULL;
13232 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
13233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13234 ok(!!cond, "cond == NULL\n");
13235
13236 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
13237 IUIAutomationCondition_Release(cond);
13238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13239 ok(!!prop_cond, "prop_cond == NULL\n");
13240
13241 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
13242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13243 ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
13244
13245 VariantInit(&v);
13246 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
13247 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13248 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
13249 VariantClear(&v);
13250
13251 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
13252 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13253 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
13254
13255 IUIAutomationPropertyCondition_Release(prop_cond);
13256 IUIAutomationNotCondition_Release(not_cond);
13257
13258 /* Set a new TreeFilter condition. */
13259 cond = NULL;
13260 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
13261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13262 ok(!!cond, "cond == NULL\n");
13263
13264 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, cond);
13265 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13266
13267 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond2);
13268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13269 ok(!!cond2, "cond2 == NULL\n");
13270 ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
13271 IUIAutomationCondition_Release(cond);
13272 IUIAutomationCondition_Release(cond2);
13273
13274 /*
13275 * AutomationElementMode tests.
13276 */
13277 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, NULL);
13278 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13279
13280 elem_mode = 0;
13281 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
13282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13283 ok(elem_mode == AutomationElementMode_Full, "Unexpected element mode %#x\n", elem_mode);
13284
13285 /* Invalid value - maximum is AutomationElementMode_Full, 0x01. */
13286 hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, 0x02);
13287 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13288
13289 hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, AutomationElementMode_None);
13290 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13291
13292 elem_mode = 0;
13293 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
13294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13295 todo_wine ok(elem_mode == AutomationElementMode_None, "Unexpected element mode %#x\n", elem_mode);
13296
13297 /*
13298 * AddProperty tests.
13299 */
13300 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_IsContentElementPropertyId);
13301 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13302
13303 /* Invalid property ID. */
13304 hr = IUIAutomationCacheRequest_AddProperty(cache_req, 1);
13305 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13306
13307 IUIAutomationCacheRequest_Release(cache_req);
13308}
13309
13313 { 0 },
13314};
13315
13318 { 0 },
13319};
13320
13323 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13324 { 0 },
13325};
13326
13333 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13334 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
13335 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
13336 { 0 },
13337};
13338
13339static void test_Element_cache_methods(IUIAutomation *uia_iface)
13340{
13341 static const int cache_test_props[] = { UIA_IsKeyboardFocusablePropertyId, UIA_NamePropertyId, UIA_ControlTypePropertyId,
13342 UIA_BoundingRectanglePropertyId, UIA_HasKeyboardFocusPropertyId, };
13343 HWND hwnd = create_test_hwnd("test_Element_cache_methods class");
13344 IUIAutomationElement *element, *element2, *element3;
13345 struct Provider_prop_override prop_override;
13346 IUIAutomationCacheRequest *cache_req;
13347 IUIAutomationElementArray *elem_arr;
13348 int tmp_rt_id[2], i, len, tmp_int;
13349 IUnknown *unk_ns;
13350 BSTR tmp_bstr;
13351 BOOL tmp_bool;
13352 HRESULT hr;
13353 RECT rect;
13354 VARIANT v;
13355
13360
13362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13363
13364 cache_req = NULL;
13365 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13366 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13367 ok(!!cache_req, "cache_req == NULL\n");
13368
13369 /*
13370 * Run these tests on Provider_child, it doesn't have an HWND so it will
13371 * get UIA_RuntimeIdPropertyId from GetRuntimeId.
13372 */
13373 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
13374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13375 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13376 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13377 ok_method_sequence(get_elem_cache_seq, "get_elem_cache_seq");
13378
13379 IUIAutomationElement_Release(element);
13380 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
13381
13382 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element);
13383 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13384 ok(!!element, "element == NULL\n");
13385 VariantClear(&v);
13386
13387 /*
13388 * Passing in an invalid COM interface for IUIAutomationCacheRequest will
13389 * cause an access violation on Windows.
13390 */
13391 if (0)
13392 {
13393 IUIAutomationElement_BuildUpdatedCache(element, (IUIAutomationCacheRequest *)&Object, &element2);
13394 }
13395
13396 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, NULL);
13397 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13398
13399 element2 = (void *)0xdeadbeef;
13400 hr = IUIAutomationElement_BuildUpdatedCache(element, NULL, &element2);
13401 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13402 ok(!element2, "element2 != NULL\n");
13403
13404 /*
13405 * Test cached property values. The default IUIAutomationCacheRequest
13406 * always caches UIA_RuntimeIdPropertyId.
13407 */
13408 element2 = NULL;
13409 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13410 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13411 ok(!!element2, "element2 == NULL\n");
13412 ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
13413
13414 /* RuntimeId is currently unset, so we'll get the NotSupported value. */
13415 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13416 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13417 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13418 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
13419 VariantClear(&v);
13420
13421 /* Attempting to get a cached value for a non-cached property. */
13422 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
13423 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13424 ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
13425 VariantClear(&v);
13426
13427 IUIAutomationElement_Release(element2);
13428
13429 /* RuntimeId is now set. */
13430 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
13431 element2 = NULL;
13432 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13434 ok(!!element2, "element2 == NULL\n");
13435 ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
13436
13437 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13438 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13439 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
13441 VariantClear(&v);
13442 IUIAutomationElement_Release(element2);
13443
13444 /*
13445 * Add UIA_IsControlElementPropertyId to the list of cached property
13446 * values.
13447 */
13448 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_IsControlElementPropertyId);
13449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13450
13451 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadb33f;
13452 element2 = NULL;
13453 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13454 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13455 ok(!!element2, "element2 == NULL\n");
13456 ok_method_sequence(get_cached_prop_val_seq2, "get_cached_prop_val_seq2");
13457
13458 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13459 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13460 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
13462 VariantClear(&v);
13463
13464 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
13465 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13466 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
13467 VariantClear(&v);
13468
13469 IUIAutomationElement_Release(element2);
13470 IUIAutomationCacheRequest_Release(cache_req);
13471
13472 IUIAutomationElement_Release(element);
13473 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13474
13475 /* Test cached UIAutomationType_Element properties. */
13477
13478 cache_req = NULL;
13479 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13480 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13481 ok(!!cache_req, "cache_req == NULL\n");
13482
13483 /* UIAutomationType_Element property. */
13484 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_LabeledByPropertyId);
13485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13486
13487 /* UIAutomationType_ElementArray property. */
13488 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_ControllerForPropertyId);
13489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13490
13491 element2 = NULL;
13492 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13494 ok(!!element2, "element2 == NULL\n");
13495 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
13496 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13497
13498 tmp_rt_id[0] = UIA_RUNTIME_ID_PREFIX;
13499 tmp_rt_id[1] = HandleToULong(hwnd);
13500 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13502 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
13503 check_runtime_id(tmp_rt_id, ARRAY_SIZE(tmp_rt_id), V_ARRAY(&v));
13504 VariantClear(&v);
13505
13506 /* Cached IUIAutomationElement. */
13507 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_LabeledByPropertyId, TRUE, &v);
13508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13509 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13510
13511 element3 = NULL;
13512 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element3);
13513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13514 ok(!!element3, "element3 == NULL\n");
13515 VariantClear(&v);
13516
13517 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_IsControlElementPropertyId, TRUE, &v);
13518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13519 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
13520 IUIAutomationElement_Release(element3);
13521 VariantClear(&v);
13522
13523 /* Cached IUIAutomationElementArray. */
13524 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_ControllerForPropertyId, TRUE, &v);
13525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13526 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13527
13528 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
13529 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13530 ok(!!elem_arr, "elem_arr == NULL\n");
13531 VariantClear(&v);
13532
13533 hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
13534 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13535 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
13536
13537 for (i = 0; i < ARRAY_SIZE(uia_unk_arr_prop_val); i++)
13538 {
13539 hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element3);
13540 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13541 ok(!!element3, "element3 == NULL\n");
13542
13543 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_ControlTypePropertyId, TRUE, &v);
13544 ok(hr == S_OK, "elem[%d] Unexpected hr %#lx\n", i, hr);
13545 ok(V_VT(&v) == VT_I4, "elem[%d] Unexpected VT %d\n", i, V_VT(&v));
13546 ok(V_I4(&v) == uia_i4_prop_val, "elem[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
13547
13548 IUIAutomationElement_Release(element3);
13549 VariantClear(&v);
13550 }
13551
13552 IUIAutomationElementArray_Release(elem_arr);
13553 IUIAutomationCacheRequest_Release(cache_req);
13554
13555 /*
13556 * Reference isn't released until the element holding the cache is
13557 * destroyed.
13558 */
13559 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
13560 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13561
13562 IUIAutomationElement_Release(element2);
13563 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13564 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
13565 ok_method_sequence(get_cached_prop_val_seq3, "get_cached_prop_val_seq3");
13566
13567 IUIAutomationElement_Release(element);
13568 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
13569 IUnknown_Release(unk_ns);
13570
13571 /*
13572 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
13573 * It's the only version with this behavior.
13574 */
13575 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
13576 {
13577 win_skip("Skipping cached UIA_BoundingRectanglePropertyId tests for Win7\n");
13578 goto exit;
13579 }
13580
13581 /*
13582 * Cached property value helper function tests.
13583 */
13586
13587 /*
13588 * element has no cached values, element2 has cached values but they're
13589 * all the equivalent of VT_EMPTY, element3 has valid cached values.
13590 */
13591 cache_req = NULL;
13592 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13594 ok(!!cache_req, "cache_req == NULL\n");
13595
13596 for (i = 0; i < ARRAY_SIZE(cache_test_props); i++)
13597 {
13598 hr = IUIAutomationCacheRequest_AddProperty(cache_req, cache_test_props[i]);
13599 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13600 }
13601
13602 /* element2, invalid values for all cached properties. */
13603 element2 = NULL;
13605 set_uia_rect(&Provider.bounds_rect, 0, 0, 0, 0);
13606 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13607 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13608 ok(!!element2, "element2 == NULL\n");
13610
13611 /* element3, valid values for all cached properties. */
13612 V_VT(&v) = VT_I4;
13613 V_I4(&v) = UIA_HyperlinkControlTypeId;
13614 set_property_override(&prop_override, UIA_ControlTypePropertyId, &v);
13615 set_provider_prop_override(&Provider, &prop_override, 1);
13616 set_uia_rect(&Provider.bounds_rect, 0, 0, 50, 50);
13617
13618 element3 = NULL;
13619 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element3);
13620 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13621 ok(!!element3, "element3 == NULL\n");
13623
13624 IUIAutomationCacheRequest_Release(cache_req);
13625
13626 /* Cached UIA_HasKeyboardFocusPropertyId helper. */
13627 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, NULL);
13628 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13629
13630 tmp_bool = 0xdeadbeef;
13631 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, &tmp_bool);
13632 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13633 ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool);
13634
13635 tmp_bool = 0xdeadbeef;
13636 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element2, &tmp_bool);
13637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13638 ok(!tmp_bool, "tmp_bool != FALSE\n");
13639
13640 tmp_bool = FALSE;
13641 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element3, &tmp_bool);
13642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13643 ok(!!tmp_bool, "tmp_bool == FALSE\n");
13644
13645 /* Cached UIA_IsKeyboardFocusablePropertyId helper. */
13646 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, NULL);
13647 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13648
13649 tmp_bool = 0xdeadbeef;
13650 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, &tmp_bool);
13651 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13652 ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool);
13653
13654 tmp_bool = 0xdeadbeef;
13655 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element2, &tmp_bool);
13656 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13657 ok(!tmp_bool, "tmp_bool != FALSE\n");
13658
13659 tmp_bool = FALSE;
13660 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element3, &tmp_bool);
13661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13662 ok(!!tmp_bool, "tmp_bool == FALSE\n");
13663
13664 /* Cached UIA_NamePropertyId helper. */
13665 hr = IUIAutomationElement_get_CachedName(element, NULL);
13666 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13667
13668 tmp_bstr = (void *)0xdeadbeef;
13669 hr = IUIAutomationElement_get_CachedName(element, &tmp_bstr);
13670 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13671 ok(tmp_bstr == (void *)0xdeadbeef, "Unexpected BSTR ptr %p\n", tmp_bstr);
13672
13673 tmp_bstr = NULL;
13674 hr = IUIAutomationElement_get_CachedName(element2, &tmp_bstr);
13675 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13676 ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
13677 SysFreeString(tmp_bstr);
13678
13679 tmp_bstr = NULL;
13680 hr = IUIAutomationElement_get_CachedName(element3, &tmp_bstr);
13681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13682 ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
13683 SysFreeString(tmp_bstr);
13684
13685 /* Cached UIA_ControlTypePropertyId. */
13686 hr = IUIAutomationElement_get_CachedControlType(element, NULL);
13687 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13688
13689 tmp_int = 0xdeadbeef;
13690 hr = IUIAutomationElement_get_CachedControlType(element, &tmp_int);
13691 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13692 ok(tmp_int == 0xdeadbeef, "Unexpected control type %#x\n", tmp_int);
13693
13694 tmp_int = 0;
13695 hr = IUIAutomationElement_get_CachedControlType(element2, &tmp_int);
13696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13697 ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
13698
13699 tmp_int = 0;
13700 hr = IUIAutomationElement_get_CachedControlType(element3, &tmp_int);
13701 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13702 ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
13703
13704 /* Cached UIA_BoundingRectanglePropertyId helper. */
13705 hr = IUIAutomationElement_get_CachedBoundingRectangle(element, NULL);
13706 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13707
13708 rect.left = rect.top = rect.bottom = rect.right = 1;
13709 hr = IUIAutomationElement_get_CachedBoundingRectangle(element, &rect);
13710 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13711 ok(rect.left == 1, "Unexpected rect left %ld\n", rect.left);
13712 ok(rect.top == 1, "Unexpected rect top %ld\n", rect.top);
13713 ok(rect.right == 1, "Unexpected rect right %ld\n", rect.right);
13714 ok(rect.bottom == 1, "Unexpected rect bottom %ld\n", rect.bottom);
13715
13716 rect.left = rect.top = rect.bottom = rect.right = 1;
13717 hr = IUIAutomationElement_get_CachedBoundingRectangle(element2, &rect);
13718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13719 ok(!rect.left, "Unexpected rect left %ld\n", rect.left);
13720 ok(!rect.top, "Unexpected rect top %ld\n", rect.top);
13721 ok(!rect.right, "Unexpected rect right %ld\n", rect.right);
13722 ok(!rect.bottom, "Unexpected rect bottom %ld\n", rect.bottom);
13723
13724 memset(&rect, 0, sizeof(rect));
13725 hr = IUIAutomationElement_get_CachedBoundingRectangle(element3, &rect);
13726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13728
13729 IUIAutomationElement_Release(element3);
13730 IUIAutomationElement_Release(element2);
13731 IUIAutomationElement_Release(element);
13732
13733 set_uia_rect(&Provider.bounds_rect, 0, 0, 0, 0);
13735
13736exit:
13738 UnregisterClassA("test_Element_cache_methods class", NULL);
13739}
13740
13742 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
13744 { 0 }
13745};
13746
13747/*
13748 * Identical to find_seq7, except default cache request used by FindAll
13749 * doesn't cache UIA_RuntimeIdPropertyId.
13750 */
13753 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13754 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13755 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13757 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13758 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13759 NODE_CREATE_SEQ(&Provider_child_child),
13760 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13761 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13762 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13763 NODE_CREATE_SEQ(&Provider_child_child2),
13764 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13765 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13766 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13767 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13769 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13771 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13772 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13773 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13774 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13776 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13777 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13778 /* Only done on Win10v1507 and below. */
13779 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
13780 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13781 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13782 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13783 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13784 { 0 },
13785};
13786
13787/*
13788 * Identical to find_seq11, except default cache request used by FindFirst
13789 * doesn't cache UIA_RuntimeIdPropertyId.
13790 */
13793 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13794 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13796 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13797 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13798 NODE_CREATE_SEQ(&Provider_child_child),
13799 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13800 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13801 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13802 NODE_CREATE_SEQ(&Provider_child_child2),
13803 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13804 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13805 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13806 { 0 },
13807};
13808
13814};
13815
13816static void set_elem_desc(struct exp_elem_desc *desc, struct Provider *prov, HWND hwnd, DWORD pid, ULONG exp_refcnt,
13817 ULONG exp_release_refcnt)
13818{
13819 desc->elem_prov = prov;
13820 init_node_provider_desc(&desc->prov_desc, pid, hwnd);
13821 desc->exp_refcnt = exp_refcnt;
13822 desc->exp_release_refcnt = exp_release_refcnt;
13823}
13824
13825#define test_uia_element_arr( elem_arr, exp_elems, exp_elems_count ) \
13826 test_uia_element_arr_( (elem_arr), (exp_elems), (exp_elems_count), __FILE__, __LINE__)
13827static void test_uia_element_arr_(IUIAutomationElementArray *elem_arr, struct exp_elem_desc *exp_elems, int exp_elems_count,
13828 const char *file, int line)
13829{
13830 int i, arr_length;
13831 HRESULT hr;
13832
13833 hr = IUIAutomationElementArray_get_Length(elem_arr, &arr_length);
13834 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13835 ok_(file, line)(hr == S_OK, "IUIAutomationElementArray_get_Length: Unexpected hr %#lx\n", hr);
13836 ok_(file, line)(arr_length == exp_elems_count, "Unexpected arr_length %d.\n", arr_length);
13837
13838 for (i = 0; i < arr_length; i++)
13839 {
13840 struct exp_elem_desc *desc = &exp_elems[i];
13841 IUIAutomationElement *element;
13842 VARIANT v;
13843
13844 ok_(file, line)(desc->elem_prov->ref == desc->exp_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
13845
13846 VariantInit(&v);
13847 element = NULL;
13848 hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element);
13849 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13850 ok(!!element, "element == NULL\n");
13851
13852 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13853 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
13855 VariantClear(&v);
13856 IUIAutomationElement_Release(element);
13857 }
13858
13859 IUIAutomationElementArray_Release(elem_arr);
13860
13861 for (i = 0; i < arr_length; i++)
13862 {
13863 struct exp_elem_desc *desc = &exp_elems[i];
13864
13865 ok_(file, line)(desc->elem_prov->ref == desc->exp_release_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
13866 }
13867}
13868
13869static void test_Element_Find(IUIAutomation *uia_iface)
13870{
13871 HWND hwnd = create_test_hwnd("test_Element_Find class");
13872 IUIAutomationCondition *condition, *condition2;
13873 struct Provider_prop_override prop_override;
13874 struct exp_elem_desc exp_elems[7] = { 0 };
13875 IUIAutomationElement *element, *element2;
13876 IUIAutomationElementArray *element_arr;
13877 IUIAutomationCacheRequest *cache_req;
13878 HRESULT hr;
13879 VARIANT v;
13880
13882
13883 /*
13884 * The COM API has no equivalent to UiaNodeFromProvider, so the only way
13885 * we can get an initial element is with ElementFromHandle. This means our
13886 * element representing Provider will have an HWND associated, which
13887 * doesn't match our old UiaFind tests. To work around this, make Provider
13888 * return itself for the UIA_LabeledByPropertyId to get an element without
13889 * an HWND associated.
13890 */
13891 VariantInit(&v);
13892 V_VT(&v) = VT_UNKNOWN;
13894 set_property_override(&prop_override, UIA_LabeledByPropertyId, &v);
13895 set_provider_prop_override(&Provider, &prop_override, 1);
13896 Provider.hwnd = NULL;
13897
13898 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
13899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13900 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13901 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
13902
13903 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
13904 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13905 ok(!!element2, "element2 == NULL\n");
13906 VariantClear(&v);
13907 ok_method_sequence(element_find_start_seq, "element_find_start_seq");
13909
13910 IUIAutomationElement_Release(element);
13911 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
13912
13913 element = element2;
13914 element2 = NULL;
13915
13920 provider_add_child(&Provider_child, &Provider_child_child);
13921 provider_add_child(&Provider_child, &Provider_child_child2);
13922 provider_add_child(&Provider_child2, &Provider_child2_child);
13923 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
13924
13925 /*
13926 * In order to match the tests from test_UiaFind(), we need to create a
13927 * custom IUIAutomationCacheRequest with a ConditionType_True treeview.
13928 * The default cache request also caches the RuntimeId property.
13929 */
13930 cache_req = NULL;
13931 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13932 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13933 ok(!!cache_req, "cache_req == NULL\n");
13934
13935 /* Set view condition to ConditionType_True. */
13936 condition = NULL;
13937 hr = IUIAutomation_CreateTrueCondition(uia_iface, &condition);
13938 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13939 ok(!!condition, "condition == NULL\n");
13940
13941 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, condition);
13942 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13943
13944 /*
13945 * Equivalent to: Maximum find depth of -1, find first is FALSE, exclude
13946 * root is FALSE.
13947 */
13948 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Subtree, condition, cache_req, &element_arr);
13949 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13950
13951 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
13952 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
13953 set_elem_desc(&exp_elems[1], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
13954 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child", TRUE);
13955 set_elem_desc(&exp_elems[2], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
13956 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child", TRUE);
13957 set_elem_desc(&exp_elems[3], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
13958 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child_child2", TRUE);
13959 set_elem_desc(&exp_elems[4], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13960 add_provider_desc(&exp_elems[4].prov_desc, L"Main", L"Provider_child2", TRUE);
13961 set_elem_desc(&exp_elems[5], &Provider_child2_child, NULL, GetCurrentProcessId(), 2, 1);
13962 add_provider_desc(&exp_elems[5].prov_desc, L"Main", L"Provider_child2_child", TRUE);
13963 set_elem_desc(&exp_elems[6], &Provider_child2_child_child, NULL, GetCurrentProcessId(), 2, 1);
13964 add_provider_desc(&exp_elems[6].prov_desc, L"Main", L"Provider_child2_child_child", TRUE);
13965
13966 test_uia_element_arr(element_arr, exp_elems, 7);
13967 ok_method_sequence(find_seq1, "find_seq1");
13968
13969 /*
13970 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
13971 * is FALSE.
13972 */
13973 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition, cache_req, &element_arr);
13974 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13975
13976 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
13977 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
13978 set_elem_desc(&exp_elems[1], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
13979 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child", TRUE);
13980 set_elem_desc(&exp_elems[2], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13981 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child2", TRUE);
13982
13983 test_uia_element_arr(element_arr, exp_elems, 3);
13984 ok_method_sequence(find_seq2, "find_seq2");
13985
13986 /*
13987 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
13988 * is TRUE.
13989 */
13990 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Children, condition, cache_req, &element_arr);
13991 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13992
13993 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
13994 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
13995 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13996 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
13997
13998 test_uia_element_arr(element_arr, exp_elems, 2);
13999 ok_method_sequence(find_seq3, "find_seq3");
14000
14001 /*
14002 * Equivalent to: Maximum find depth of 1, find first is TRUE, exclude
14003 * root is TRUE. element2 now represents Provider_child.
14004 */
14005 hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Children, condition, cache_req, &element2);
14006 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14007 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14008
14009 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14010 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14012 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
14013 VariantClear(&v);
14014
14015 ok_method_sequence(find_seq4, "find_seq4");
14016
14017 /*
14018 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
14019 * root is FALSE. Provider_child doesn't have a runtime id for UI
14020 * Automation to use as a way to check if it has navigated back to the
14021 * node that began the search, so it will get siblings.
14022 */
14023 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
14024 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14025
14026 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 2);
14027 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
14028 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14029 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
14030
14031 test_uia_element_arr(element_arr, exp_elems, 2);
14032 ok_method_sequence(find_seq5, "find_seq5");
14033
14034 /*
14035 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
14036 * root is FALSE. Provider_child now has a runtime ID, so we don't get
14037 * its sibling.
14038 */
14039 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
14040 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
14041 IUIAutomationElement_Release(element2);
14042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14043
14044 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
14045 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
14046
14047 test_uia_element_arr(element_arr, exp_elems, 1);
14048 ok_method_sequence(find_seq6, "find_seq6");
14050
14051 IUIAutomationCondition_Release(condition);
14052
14053 /* condition is now UIA_IsContentElementPropertyId == FALSE. */
14054 condition = NULL;
14056 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &condition);
14057 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14058 ok(!!condition, "condition == NULL\n");
14059
14060 /* Set view condition to this property condition. */
14061 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, condition);
14062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14063
14064 /* condition2 is UIA_IsControlElementPropertyId == TRUE. */
14065 condition2 = NULL;
14067 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsControlElementPropertyId, v, &condition2);
14068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14069 ok(!!condition2, "condition2 == NULL\n");
14070
14071 /* Override UIA_IsContentElementPropertyId, set it to FALSE. */
14073 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14074 set_provider_prop_override(&Provider, &prop_override, 1);
14075 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14076 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14077 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14078
14079 /*
14080 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
14081 * root is FALSE. The cache request view condition is used to determine
14082 * tree depth, if an element matches the cache request view condition,
14083 * depth is incremented. Since Provider_child does not, Provider_child_child,
14084 * Provider_child_child2, and Provider_child2 are all considered to be at
14085 * depth 1.
14086 */
14087 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
14088 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14089
14090 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
14091 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
14092 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
14093 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
14094 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
14095 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14096 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14097 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
14098
14099 test_uia_element_arr(element_arr, exp_elems, 4);
14100 ok_method_sequence(find_seq7, "find_seq7");
14102
14103 /*
14104 * Same test as before, except now Provider has a runtime ID.
14105 */
14106 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
14108 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14109 set_provider_prop_override(&Provider, &prop_override, 1);
14110 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14111 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14112 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14113
14114 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
14115 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14116
14117 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
14118 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
14119 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
14120 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
14121 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 2);
14122 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14123 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14124 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
14125
14126 /* element2 now represents Provider_child_child2. */
14127 hr = IUIAutomationElementArray_GetElement(element_arr, 2, &element2);
14128 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14129
14130 test_uia_element_arr(element_arr, exp_elems, 4);
14131 ok_method_sequence(find_seq8, "find_seq8");
14133
14135 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14136 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14137 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14138 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
14139
14140 /*
14141 * Equivalent to: Maximum find depth of 1, find first is FALSE,
14142 * exclude root is FALSE. Starting at Provider_child_child2, find
14143 * will be able to traverse the tree in the same order as it would
14144 * if we had started at the tree root Provider, retrieving
14145 * Provider_child2 as a sibling and Provider_child2_child as a node
14146 * at depth 1.
14147 */
14148 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
14149 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14150 IUIAutomationElement_Release(element2);
14151
14152 set_elem_desc(&exp_elems[0], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
14153 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14154 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14155 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
14156 set_elem_desc(&exp_elems[2], &Provider_child2_child, NULL, GetCurrentProcessId(), 2, 1);
14157 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child2_child", TRUE);
14158
14159 test_uia_element_arr(element_arr, exp_elems, 3);
14160 ok_method_sequence(find_seq9, "find_seq9");
14162
14163 /*
14164 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
14165 * root is TRUE. Exclude root applies to the first node that matches the
14166 * view condition, and not the node that is passed into UiaFind(). Since
14167 * Provider doesn't match our view condition here, Provider_child will be
14168 * excluded.
14169 */
14171 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14172 set_provider_prop_override(&Provider_child, &prop_override, 1);
14173 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14174 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Children, condition2, cache_req, &element_arr);
14175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14176
14177 set_elem_desc(&exp_elems[0], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14178 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child2", TRUE);
14179
14180 test_uia_element_arr(element_arr, exp_elems, 1);
14181 ok_method_sequence(find_seq10, "find_seq10");
14183
14185 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14186 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14187
14188 /*
14189 * Equivalent to: Maximum find depth of -1, find first is TRUE, exclude
14190 * root is FALSE. Provider_child_child2 is the only element in the tree
14191 * to match our condition.
14192 */
14193 hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Subtree, condition, cache_req, &element2);
14194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14195 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
14196
14197 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14198 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14200 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
14201 VariantClear(&v);
14202
14203 IUIAutomationElement_Release(element2);
14204 ok_method_sequence(find_seq11, "find_seq11");
14206
14207 IUIAutomationCondition_Release(condition);
14208 IUIAutomationCondition_Release(condition2);
14209 IUIAutomationCacheRequest_Release(cache_req);
14210
14211 /*
14212 * Equivalent to: Maximum find depth of 1, find first is FALSE,
14213 * exclude root is FALSE. FindAll() uses the default
14214 * IUIAutomationCacheRequest, which uses the ControlView condition
14215 * as its view condition. Since Provider_child doesn't match this view
14216 * condition, it isn't a child of Provider in this treeview. No property
14217 * values are cached by the default internal cache request, so we need to
14218 * use a separate method sequence.
14219 */
14221 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14222 set_provider_prop_override(&Provider_child, &prop_override, 1);
14223
14224 /* condition is now UIA_IsContentElementPropertyId == TRUE. */
14226 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &condition);
14227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14228 ok(!!condition, "cond == NULL\n");
14229
14230 hr = IUIAutomationElement_FindAll(element, TreeScope_Element | TreeScope_Children, condition, &element_arr);
14231 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14232
14233 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
14234 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
14235 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
14236 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
14237 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
14238 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14239 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14240 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
14241
14242 test_uia_element_arr(element_arr, exp_elems, 4);
14243 ok_method_sequence(element_find_seq1, "element_find_seq1");
14245
14246 /*
14247 * Equivalent to: Maximum find depth of -1, find first is TRUE,
14248 * exclude root is FALSE. FindFirst() also uses the default cache request.
14249 * Provider_child_child2 will be the first provider in the tree to match
14250 * this view condition, so it will be returned.
14251 */
14253 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14254 set_provider_prop_override(&Provider, &prop_override, 1);
14255 set_provider_prop_override(&Provider_child, &prop_override, 1);
14256 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14257
14258 hr = IUIAutomationElement_FindFirst(element, TreeScope_Subtree, condition, &element2);
14259 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14260 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
14261
14262 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14263 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14265 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
14266 VariantClear(&v);
14267
14268 IUIAutomationElement_Release(element2);
14269 ok_method_sequence(element_find_seq2, "element_find_seq2");
14271
14272 IUIAutomationCondition_Release(condition);
14273 IUIAutomationElement_Release(element);
14274 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14275
14277 UnregisterClassA("test_Element_Find class", NULL);
14278}
14279
14280static const struct prov_method_sequence treewalker_seq1[] = {
14281 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
14283 { 0 }
14284};
14285
14286static const struct prov_method_sequence treewalker_seq2[] = {
14287 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
14290 { 0 }
14291};
14292
14293static const struct prov_method_sequence treewalker_seq3[] = {
14294 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
14296 { 0 }
14297};
14298
14299static const struct prov_method_sequence treewalker_seq4[] = {
14300 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
14303 { 0 }
14304};
14305
14306static const struct prov_method_sequence treewalker_seq5[] = {
14307 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
14309 { 0 }
14310};
14311
14312static const struct prov_method_sequence treewalker_seq6[] = {
14313 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
14316 { 0 }
14317};
14318
14319static const struct prov_method_sequence treewalker_seq7[] = {
14320 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
14322 { 0 }
14323};
14324
14325static const struct prov_method_sequence treewalker_seq8[] = {
14326 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
14329 { 0 }
14330};
14331
14332static const struct prov_method_sequence treewalker_seq9[] = {
14333 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
14335 { 0 }
14336};
14337
14339 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
14342 { 0 }
14343};
14344
14346{
14347 HWND hwnd = create_test_hwnd("test_CUIAutomation_TreeWalker_ifaces class");
14348 IUIAutomationElement *element, *element2, *element3;
14349 IUIAutomationCacheRequest *cache_req;
14350 IUIAutomationCondition *cond, *cond2;
14351 IUIAutomationTreeWalker *walker;
14352 HRESULT hr;
14353
14354 cond = NULL;
14355 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
14356 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14357 ok(!!cond, "cond == NULL\n");
14358
14359 /* NULL input argument tests. */
14360 walker = (void *)0xdeadbeef;
14361 hr = IUIAutomation_CreateTreeWalker(uia_iface, NULL, &walker);
14362 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14363 ok(!walker, "walker != NULL\n");
14364
14365 hr = IUIAutomation_CreateTreeWalker(uia_iface, cond, NULL);
14366 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14367
14368 /* Actually create TreeWalker. */
14369 walker = NULL;
14370 hr = IUIAutomation_CreateTreeWalker(uia_iface, cond, &walker);
14371 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14372 ok(!!walker, "walker == NULL\n");
14373
14374 hr = IUIAutomationTreeWalker_get_Condition(walker, &cond2);
14375 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14376 ok(!!cond2, "cond2 == NULL\n");
14377
14378 ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
14379 IUIAutomationCondition_Release(cond);
14380 IUIAutomationCondition_Release(cond2);
14381
14382 cache_req = NULL;
14383 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
14384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14385 ok(!!cache_req, "cache_req == NULL\n");
14386
14393
14394 /* NULL input argument tests. */
14395 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, element, NULL);
14396 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14397
14398 element2 = (void *)0xdeadbeef;
14399 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, NULL, &element2);
14400 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14401 ok(!element2, "element2 != NULL\n");
14402
14403 /* NavigateDirection_FirstChild. */
14404 element2 = NULL;
14405 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, element, &element2);
14406 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14407 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14408 ok(!!element2, "element2 == NULL\n");
14409 ok_method_sequence(treewalker_seq1, "treewalker_seq1");
14410
14411 IUIAutomationElement_Release(element2);
14412 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14413
14414 element2 = NULL;
14415 hr = IUIAutomationTreeWalker_GetFirstChildElementBuildCache(walker, element, cache_req, &element2);
14416 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14417 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14418 ok(!!element2, "element2 == NULL\n");
14419 ok_method_sequence(treewalker_seq2, "treewalker_seq2");
14420
14421 /* NavigateDirection_NextSibling. */
14422 element3 = NULL;
14423 hr = IUIAutomationTreeWalker_GetNextSiblingElement(walker, element2, &element3);
14424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14425 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14426 ok(!!element3, "element3 == NULL\n");
14427 ok_method_sequence(treewalker_seq5, "treewalker_seq5");
14428 IUIAutomationElement_Release(element3);
14429 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14430
14431 element3 = NULL;
14432 hr = IUIAutomationTreeWalker_GetNextSiblingElementBuildCache(walker, element2, cache_req, &element3);
14433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14434 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14435 ok(!!element3, "element3 == NULL\n");
14436 ok_method_sequence(treewalker_seq6, "treewalker_seq6");
14437 IUIAutomationElement_Release(element3);
14438 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14439
14440 IUIAutomationElement_Release(element2);
14441 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14442
14443 /* NavigateDirection_LastChild. */
14444 element2 = NULL;
14445 hr = IUIAutomationTreeWalker_GetLastChildElement(walker, element, &element2);
14446 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14447 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14448 ok(!!element2, "element2 == NULL\n");
14449 ok_method_sequence(treewalker_seq3, "treewalker_seq3");
14450
14451 IUIAutomationElement_Release(element2);
14452 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14453
14454 element2 = NULL;
14455 hr = IUIAutomationTreeWalker_GetLastChildElementBuildCache(walker, element, cache_req, &element2);
14456 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14457 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14458 ok(!!element2, "element2 == NULL\n");
14459 ok_method_sequence(treewalker_seq4, "treewalker_seq4");
14460
14461 /* NavigateDirection_PreviousSibling. */
14462 element3 = NULL;
14463 hr = IUIAutomationTreeWalker_GetPreviousSiblingElement(walker, element2, &element3);
14464 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14465 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14466 ok(!!element3, "element3 == NULL\n");
14467 ok_method_sequence(treewalker_seq7, "treewalker_seq7");
14468 IUIAutomationElement_Release(element3);
14469 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14470
14471 element3 = NULL;
14472 hr = IUIAutomationTreeWalker_GetPreviousSiblingElementBuildCache(walker, element2, cache_req, &element3);
14473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14474 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14475 ok(!!element3, "element3 == NULL\n");
14476 ok_method_sequence(treewalker_seq8, "treewalker_seq8");
14477 IUIAutomationElement_Release(element3);
14478 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14479
14480 /* NavigateDirection_Parent. */
14481 element3 = NULL;
14482 Provider.hwnd = NULL;
14483 hr = IUIAutomationTreeWalker_GetParentElement(walker, element2, &element3);
14484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14485 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
14486 ok(!!element3, "element3 == NULL\n");
14487 ok_method_sequence(treewalker_seq9, "treewalker_seq9");
14488 IUIAutomationElement_Release(element3);
14489 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14490
14491 element3 = NULL;
14492 hr = IUIAutomationTreeWalker_GetParentElementBuildCache(walker, element2, cache_req, &element3);
14493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14494 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
14495 ok(!!element3, "element3 == NULL\n");
14496 ok_method_sequence(treewalker_seq10, "treewalker_seq10");
14497 IUIAutomationElement_Release(element3);
14498 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14499
14500 IUIAutomationElement_Release(element2);
14501 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14502
14503 IUIAutomationElement_Release(element);
14504 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14505
14506 IUIAutomationCacheRequest_Release(cache_req);
14507 IUIAutomationTreeWalker_Release(walker);
14508
14510 UnregisterClassA("test_CUIAutomation_TreeWalker_ifaces class", NULL);
14511}
14512
14514 struct Provider *hwnd_prov, HWND hwnd)
14515{
14516 if (proxy_prov)
14517 {
14519 proxy_prov->frag_root = &proxy_prov->IRawElementProviderFragmentRoot_iface;
14520 proxy_prov->ignore_hwnd_prop = TRUE;
14521 }
14522
14525 hwnd_prov->frag_root = &hwnd_prov->IRawElementProviderFragmentRoot_iface;
14526 nc_prov->frag_root = &nc_prov->IRawElementProviderFragmentRoot_iface;
14527 nc_prov->ignore_hwnd_prop = TRUE;
14528}
14529
14530static void test_GetRootElement(IUIAutomation *uia_iface)
14531{
14532 IUIAutomationElement *element;
14533 HRESULT hr;
14534 VARIANT v;
14535
14536 hr = IUIAutomation_GetRootElement(uia_iface, NULL);
14537 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14538
14540
14542 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14543 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14544 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14545
14546 /* Retrieve an element representing the desktop HWND. */
14548 SET_EXPECT(prov_callback_base_hwnd);
14549 SET_EXPECT(prov_callback_nonclient);
14550 SET_EXPECT(prov_callback_proxy);
14551 hr = IUIAutomation_GetRootElement(uia_iface, &element);
14552 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14553 ok(!!element, "Node == NULL.\n");
14554 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
14555 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
14556 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
14557 CHECK_CALLED(prov_callback_base_hwnd);
14558 CHECK_CALLED(prov_callback_nonclient);
14559 CHECK_CALLED(prov_callback_proxy);
14560
14561 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14562 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14564 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
14565 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
14566 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
14567 VariantClear(&v);
14568
14569 IUIAutomationElement_Release(element);
14570 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
14571 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
14572 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
14573
14576 TRUE);
14579
14582}
14583
14584#define test_get_focused_elem( uia_iface, cache_req, exp_hr, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, \
14585 nc_cback_count, win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, \
14586 base_hwnd_cback_todo, nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo ) \
14587 test_get_focused_elem_( (uia_iface), (cache_req), (exp_hr), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), \
14588 (nc_cback_count), (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), \
14589 (base_hwnd_cback_todo), (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
14590static void test_get_focused_elem_(IUIAutomation *uia_iface, IUIAutomationCacheRequest *cache_req, HRESULT exp_hr,
14591 struct node_provider_desc *exp_node_desc, int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
14592 int win_get_obj_count, int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo,
14593 BOOL nc_cback_todo, BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
14594{
14595 IUIAutomationElement *element = NULL;
14596 HRESULT hr;
14597 VARIANT v;
14598
14599 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14600 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
14601 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
14602 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
14603 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
14604 if (cache_req)
14605 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, &element);
14606 else
14607 hr = IUIAutomation_GetFocusedElement(uia_iface, &element);
14608 ok_(file, line)(hr == exp_hr, "Unexpected hr %#lx.\n", hr);
14609 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14610 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
14611 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
14612 todo_wine_if(win_get_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
14613 todo_wine_if(child_win_get_obj_todo) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
14614
14615 if (exp_node_desc->prov_count)
14616 {
14617 ok_(file, line)(!!element, "element == NULL\n");
14618
14619 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14620 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14621 test_node_provider_desc_(exp_node_desc, V_BSTR(&v), file, line);
14622 VariantClear(&v);
14623
14624 IUIAutomationElement_Release(element);
14625 }
14626 else
14627 ok_(file, line)(!element, "element != NULL\n");
14628}
14629
14630static void test_GetFocusedElement(IUIAutomation *uia_iface)
14631{
14632 struct Provider_prop_override prop_override;
14633 struct node_provider_desc exp_node_desc;
14634 IUIAutomationCacheRequest *cache_req;
14635 IUIAutomationElement *element;
14636 HWND hwnd, hwnd_child;
14637 HRESULT hr;
14638 VARIANT v;
14639
14640 hwnd = create_test_hwnd("test_GetFocusedElement class");
14641 hwnd_child = create_child_test_hwnd("test_GetFocusedElement child class", hwnd);
14643
14644 cache_req = NULL;
14645 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
14646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14647 ok(!!cache_req, "cache_req == NULL\n");
14648
14649 /*
14650 * Set clientside providers for our test windows and the desktop. Same
14651 * tests as UiaNodeFromFocus, just with COM methods.
14652 */
14654 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14655 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14656 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14657
14658 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
14663
14664 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, hwnd_child);
14666 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
14667 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
14668 Provider2.ignore_hwnd_prop = TRUE;
14669
14670 /* NULL input argument tests. */
14671 hr = IUIAutomation_GetFocusedElement(uia_iface, NULL);
14672 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14673
14674 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, NULL);
14675 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14676
14677 element = (void *)0xdeadbeef;
14678 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, NULL, &element);
14679 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14680 ok(!element, "element != NULL\n");
14681
14682 /*
14683 * None of the providers for the desktop node return a provider from
14684 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
14685 * desktop node.
14686 */
14689 add_provider_desc(&exp_node_desc, L"Main", L"Provider_proxy", TRUE);
14690 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc", FALSE);
14691 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd", FALSE);
14692
14693 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14694 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14695
14696 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
14697 Provider_hwnd.focus_prov = &Provider_hwnd2.IRawElementProviderFragment_iface;
14698
14700 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
14701 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
14702 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
14703
14704 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14705 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14706
14707 /*
14708 * Provider_proxy returns Provider from GetFocus. The provider that
14709 * creates the node will not have GetFocus called on it to avoid returning
14710 * the same provider twice. Similarly, on nodes other than the desktop
14711 * node, the HWND provider will not have GetFocus called on it.
14712 */
14713 Provider_hwnd.focus_prov = NULL;
14715 Provider.focus_prov = Provider_hwnd2.focus_prov = &Provider2.IRawElementProviderFragment_iface;
14716
14718 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
14719 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
14720 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
14721
14722 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14723 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14724
14725 /*
14726 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
14727 * Provider2, Provider_nc3 returns Provider_child.
14728 */
14730 Provider_proxy.focus_prov = Provider_hwnd.focus_prov = NULL;
14731 Provider_nc.focus_prov = &Provider_nc2.IRawElementProviderFragment_iface;
14732 Provider.focus_prov = &Provider2.IRawElementProviderFragment_iface;
14733 Provider_nc3.focus_prov = &Provider_child.IRawElementProviderFragment_iface;
14734
14736 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
14737
14738 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
14739 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
14740
14741 /*
14742 * Provider_proxy returns Provider_child_child from GetFocus. The focus
14743 * provider is normalized against the cache request view condition.
14744 * Provider_child_child and its ancestors don't match the cache request
14745 * view condition, so we'll get no provider.
14746 */
14750 provider_add_child(&Provider_child, &Provider_child_child);
14751 Provider_proxy.focus_prov = &Provider_child_child.IRawElementProviderFragment_iface;
14752 Provider_nc.focus_prov = Provider_hwnd.focus_prov = NULL;
14753
14755 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14756 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14757 set_provider_prop_override(&Provider_child, &prop_override, 1);
14758 set_provider_prop_override(&Provider, &prop_override, 1);
14759
14760 /*
14761 * GetFocusedElement returns UIA_E_ELEMENTNOTAVAILABLE when no provider
14762 * matches our view condition, GetFocusedElementBuildCache returns E_FAIL.
14763 */
14764 init_node_provider_desc(&exp_node_desc, 0, NULL);
14766 &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14768 &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14769
14770 /* This time, Provider_child matches our view condition. */
14772
14774 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
14775
14776 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14777
14782
14784 IUIAutomationCacheRequest_Release(cache_req);
14787 UnregisterClassA("test_GetFocusedElement class", NULL);
14788 UnregisterClassA("test_GetFocusedElement child class", NULL);
14789}
14790
14791static void set_uia_hwnd_expects(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
14792 int win_get_uia_obj_count, int win_get_client_obj_count)
14793{
14794 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14795 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
14796 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
14797 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14798 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14799}
14800
14801static void check_uia_hwnd_expects(int proxy_cback_count, BOOL proxy_cback_todo,
14802 int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo,
14803 int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
14804{
14805 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
14806 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14807 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
14808 todo_wine_if(win_get_uia_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14809 if (win_get_client_obj_count)
14810 todo_wine_if(win_get_client_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14811}
14812
14813static void check_uia_hwnd_expects_at_most(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
14814 int win_get_uia_obj_count, int win_get_client_obj_count)
14815{
14816 CHECK_CALLED_AT_MOST(prov_callback_proxy, proxy_cback_count);
14817 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, base_hwnd_cback_count);
14818 CHECK_CALLED_AT_MOST(prov_callback_nonclient, nc_cback_count);
14819 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14820 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14821}
14822
14823static void check_uia_hwnd_expects_at_least(int proxy_cback_count, BOOL proxy_cback_todo,
14824 int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo,
14825 int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
14826{
14827 todo_wine_if(proxy_cback_todo) CHECK_CALLED_AT_LEAST(prov_callback_proxy, proxy_cback_count);
14828 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_AT_LEAST(prov_callback_base_hwnd, base_hwnd_cback_count);
14829 todo_wine_if(nc_cback_todo) CHECK_CALLED_AT_LEAST(prov_callback_nonclient, nc_cback_count);
14830 todo_wine_if(win_get_uia_obj_todo) CHECK_CALLED_AT_LEAST(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14831 todo_wine_if(win_get_client_obj_todo) CHECK_CALLED_AT_LEAST(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14832}
14833
14834#define MAX_EVENT_QUEUE_COUNT 4
14840};
14841
14842static void push_event_queue_event(struct ExpectedEventQueue *queue, struct node_provider_desc *exp_node_desc)
14843{
14844 const int idx = queue->exp_event_count;
14845
14847
14848 if (exp_node_desc)
14849 {
14850 int i;
14851
14852 queue->exp_node_desc[idx] = *exp_node_desc;
14853 for (i = 0; i < exp_node_desc->prov_count; i++)
14854 {
14855 if (exp_node_desc->nested_desc[i])
14856 {
14857 queue->exp_nested_node_desc[idx] = *exp_node_desc->nested_desc[i];
14858 queue->exp_node_desc[idx].nested_desc[i] = &queue->exp_nested_node_desc[idx];
14859 break;
14860 }
14861 }
14862 }
14863 else
14864 memset(&queue->exp_node_desc[idx], 0, sizeof(queue->exp_node_desc[idx]));
14865 queue->exp_event_count++;
14866}
14867
14869{
14870 if (!queue->exp_event_count || queue->exp_event_pos >= queue->exp_event_count)
14871 {
14872 ok(0, "Failed to pop expected event from queue\n");
14873 return NULL;
14874 }
14875
14876 return &queue->exp_node_desc[queue->exp_event_pos++];
14877}
14878
14879static struct ComEventData {
14881
14886
14888{
14891
14894}
14895
14897{
14900}
14901
14902#define test_com_event_data( sender ) \
14903 test_com_event_data_( (sender), __FILE__, __LINE__)
14904static void test_com_event_data_(IUIAutomationElement *sender, const char *file, int line)
14905{
14907 HRESULT hr;
14908 VARIANT v;
14909
14911
14912 VariantInit(&v);
14913 hr = IUIAutomationElement_GetCurrentPropertyValueEx(sender, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14914 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14915 test_node_provider_desc_(exp_desc, V_BSTR(&v), file, line);
14916 VariantClear(&v);
14917
14919 if (ComEventData.event_handle && (ComEventData.exp_events.exp_event_count == ComEventData.exp_events.exp_event_pos))
14921}
14922
14923/*
14924 * IUIAutomationEventHandler.
14925 */
14927{
14928 IUIAutomationEventHandler IUIAutomationEventHandler_iface;
14931
14932static inline struct AutomationEventHandler *impl_from_AutomationEventHandler(IUIAutomationEventHandler *iface)
14933{
14935}
14936
14937static HRESULT WINAPI AutomationEventHandler_QueryInterface(IUIAutomationEventHandler *iface, REFIID riid, void **ppv)
14938{
14939 *ppv = NULL;
14940 if (IsEqualIID(riid, &IID_IUIAutomationEventHandler) || IsEqualIID(riid, &IID_IUnknown))
14941 *ppv = iface;
14942 else
14943 return E_NOINTERFACE;
14944
14945 IUIAutomationEventHandler_AddRef(iface);
14946 return S_OK;
14947}
14948
14949static ULONG WINAPI AutomationEventHandler_AddRef(IUIAutomationEventHandler* iface)
14950{
14952 return InterlockedIncrement(&handler->ref);
14953}
14954
14955static ULONG WINAPI AutomationEventHandler_Release(IUIAutomationEventHandler* iface)
14956{
14958 return InterlockedDecrement(&handler->ref);
14959}
14960
14961static HRESULT WINAPI AutomationEventHandler_HandleAutomationEvent(IUIAutomationEventHandler *iface,
14962 IUIAutomationElement *sender, EVENTID event_id)
14963{
14964 test_com_event_data(sender);
14965
14966 return S_OK;
14967}
14968
14969static const IUIAutomationEventHandlerVtbl AutomationEventHandlerVtbl = {
14974};
14975
14977{
14979 1,
14980};
14981
14982/*
14983 * IUIAutomationFocusChangedEventHandler.
14984 */
14986{
14987 IUIAutomationFocusChangedEventHandler IUIAutomationFocusChangedEventHandler_iface;
14989
14992
14993static inline struct FocusChangedHandler *impl_from_FocusChangedHandler(IUIAutomationFocusChangedEventHandler *iface)
14994{
14996}
14997
14998static HRESULT WINAPI FocusChangedHandler_QueryInterface(IUIAutomationFocusChangedEventHandler *iface,
14999 REFIID riid, void **ppv)
15000{
15001 *ppv = NULL;
15002 if (IsEqualIID(riid, &IID_IUIAutomationFocusChangedEventHandler) || IsEqualIID(riid, &IID_IUnknown))
15003 *ppv = iface;
15004 else
15005 return E_NOINTERFACE;
15006
15007 IUIAutomationFocusChangedEventHandler_AddRef(iface);
15008 return S_OK;
15009}
15010
15011static ULONG WINAPI FocusChangedHandler_AddRef(IUIAutomationFocusChangedEventHandler* iface)
15012{
15014 return InterlockedIncrement(&handler->ref);
15015}
15016
15017static ULONG WINAPI FocusChangedHandler_Release(IUIAutomationFocusChangedEventHandler* iface)
15018{
15020 return InterlockedDecrement(&handler->ref);
15021}
15022
15023static HRESULT WINAPI FocusChangedHandler_HandleFocusChangedEvent(IUIAutomationFocusChangedEventHandler *iface,
15024 IUIAutomationElement *sender)
15025{
15027
15028 if (handler->event_handler_added)
15029 test_com_event_data(sender);
15030
15031 return S_OK;
15032}
15033
15034static const IUIAutomationFocusChangedEventHandlerVtbl FocusChangedHandlerVtbl = {
15039};
15040
15042{
15044 1,
15045};
15046
15048{
15049 struct node_provider_desc exp_node_desc;
15050 HRESULT hr;
15051
15052 /*
15053 * Raise an event from inside of an MTA - the event handler proxy will be
15054 * called from the current thread because it was registered in an MTA.
15055 */
15057
15059 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15060 set_com_event_data(&exp_node_desc);
15061 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15064 ok(ComEventData.last_call_tid == GetCurrentThreadId(), "Event handler called on unexpected thread %ld\n",
15067
15068 /*
15069 * Raise an event from inside of an STA - an event handler proxy will be
15070 * created, and our handler will be invoked from another thread.
15071 */
15073
15074 set_com_event_data(&exp_node_desc);
15075 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15078 ok(ComEventData.last_call_tid != GetCurrentThreadId(), "Event handler called on unexpected thread %ld\n",
15081
15082 return 0;
15083}
15084
15085static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomationElement *elem)
15086{
15087 struct Provider_prop_override prop_override;
15088 struct node_provider_desc exp_node_desc;
15089 IUIAutomationElement *elem2;
15090 HANDLE thread;
15091 HRESULT hr;
15092 VARIANT v;
15093
15094 /*
15095 * Invalid input argument tests.
15096 */
15097 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, NULL, TreeScope_Subtree, NULL,
15099 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
15100
15101 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15102 NULL);
15103 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
15104
15105 /*
15106 * Passing in a NULL element to this method results in an access violation
15107 * on Windows.
15108 */
15109 if (0)
15110 {
15111 IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, NULL, &AutomationEventHandler.IUIAutomationEventHandler_iface);
15112 }
15113
15114 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, elem, NULL);
15115 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15116
15117 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem,
15119 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15120
15121 /*
15122 * UIA_AutomationFocusChangedEventId can only be listened for with
15123 * AddFocusChangedEventHandler. Trying to register it on a regular event
15124 * handler returns E_INVALIDARG.
15125 */
15126 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem, TreeScope_Subtree, NULL,
15128 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15129
15130 /* Windows 11 queries the HWND for the element when adding a new handler. */
15131 set_uia_hwnd_expects(3, 2, 2, 3, 0);
15132 /* All other event IDs are fine, only focus events are blocked. */
15133 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, 1, elem, TreeScope_Subtree, NULL,
15135 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15136 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15137 check_uia_hwnd_expects_at_most(3, 2, 2, 3, 0);
15138
15139 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, elem,
15141 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15142 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15143
15144 /*
15145 * Test event raising behavior.
15146 */
15147 set_uia_hwnd_expects(3, 2, 2, 3, 0);
15148 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15151 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15152 check_uia_hwnd_expects_at_most(3, 2, 2, 3, 0);
15153
15154 /* Same behavior as HUIAEVENTs, events are matched by runtime ID. */
15156 Provider2.runtime_id[0] = 0x2a;
15158
15160 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15161 set_com_event_data(&exp_node_desc);
15162 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15165
15166 /*
15167 * If no cache request is provided by the user in
15168 * AddAutomationEventHandler, the default cache request is used. If no
15169 * elements match the view condition, the event handler isn't invoked.
15170 */
15172 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
15173 set_provider_prop_override(&Provider2, &prop_override, 1);
15174 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15176
15180 {
15181 MSG msg;
15182
15183 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
15184 {
15187 }
15188 }
15190
15191 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15194 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15195
15196 VariantInit(&v);
15198 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_LabeledByPropertyId, TRUE, &v);
15199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15200 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
15201 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
15202
15203 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&elem2);
15204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15205 ok(!!elem2, "elem2 == NULL\n");
15206 VariantClear(&v);
15207
15208 /*
15209 * Register an event on an element that has no runtime ID. The only way to
15210 * remove an individual event handler is by matching a combination of
15211 * runtime-id, property ID, and event handler interface pointer. Without a
15212 * runtime-id, the only way to unregister the event handler is to call
15213 * RemoveAllEventHandlers().
15214 */
15215 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem2, TreeScope_Subtree, NULL,
15217 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15218 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15219
15220 /* No removal will occur due to a lack of a runtime ID to match. */
15221 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem2,
15223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15224 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15225
15226 hr = IUIAutomation_RemoveAllEventHandlers(uia_iface);
15227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15228 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15229
15230 IUIAutomationElement_Release(elem2);
15231}
15232
15234{
15235 struct node_provider_desc exp_node_desc;
15236 IUIAutomationElement *elem;
15237 HRESULT hr;
15238
15240
15241 /*
15242 * FocusChangedEventHandlers are always registered on the desktop node
15243 * with a scope of the entire desktop.
15244 *
15245 * All versions of Windows query the currently focused HWND when adding a
15246 * new focus changed event handler, but behavior differs between versions:
15247 *
15248 * Win7-Win10v1507 queries for the focused provider and raises an event
15249 * while also advising of events.
15250 *
15251 * Win10v1809+ will query the focused HWND, but doesn't advise of events
15252 * or raise a focus event. Windows 11 will advise the provider of the
15253 * focused HWND of events, but not any clientside providers.
15254 */
15255 set_uia_hwnd_expects(6, 6, 6, 3, 0);
15256 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15258 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15259 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15260 check_uia_hwnd_expects_at_most(6, 6, 6, 3, 0);
15262
15263 /*
15264 * Focus changed event handlers are registered on the desktop with a scope
15265 * of all elements, so all elements match regardless of runtime ID.
15266 */
15269 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15270 set_com_event_data(&exp_node_desc);
15271 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15274
15275 /*
15276 * Removing the focus changed event handler creates a desktop node -
15277 * presumably to use to get a runtime ID for removal.
15278 */
15279 set_uia_hwnd_expects(1, 1, 1, 0, 0);
15280 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
15282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15283 ok(FocusChangedHandler.ref == 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15285 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15286
15287 /*
15288 * The focus changed event handler can also be removed by called
15289 * RemoveAutomationEventHandler, which isn't documented.
15290 */
15291 set_uia_hwnd_expects(6, 6, 6, 3, 0);
15292 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15295 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15296 check_uia_hwnd_expects_at_most(6, 6, 6, 3, 0);
15298
15299 set_uia_hwnd_expects(1, 1, 1, 0, 0);
15300 hr = IUIAutomation_GetRootElement(uia_iface, &elem);
15301 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15302 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15303
15304 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem,
15306 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15307 ok(FocusChangedHandler.ref == 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15308
15309 IUIAutomationElement_Release(elem);
15310}
15311
15313{
15314 IUIAutomation *uia_iface;
15317};
15318
15320 HANDLE *handles, int method)
15321{
15322 if (!handles || method < 0)
15323 {
15327 }
15328 else
15329 {
15333 }
15334}
15335
15337{
15341}
15342
15343#define test_hwnd_providers_event_advise_added( main, hwnd, nc, event_id, todo) \
15344 test_hwnd_providers_event_advise_added_( (main), (hwnd), (nc), (event_id), (todo), __FILE__, __LINE__)
15346 int event_id, BOOL todo, const char *file, int line)
15347{
15351}
15352
15353static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface, HWND test_hwnd, HWND test_child_hwnd)
15354{
15355 GUITHREADINFO info = { .cbSize = sizeof(info) };
15356 IUIAutomationElement *elem;
15357 HANDLE method_event[4];
15358 int event_handle_count;
15359 DWORD wait_res;
15360 BOOL is_win11;
15361 HRESULT hr;
15362 int i;
15363
15364 for (i = 0; i < ARRAY_SIZE(method_event); i++)
15365 method_event[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
15366
15367 /* Only sends WM_GETOBJECT twice on Win11. */
15368 set_uia_hwnd_expects(0, 1, 1, 2, 0);
15369 hr = IUIAutomation_ElementFromHandle(uia_iface, test_hwnd, &elem);
15370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15371 ok(!!elem, "elem == NULL\n");
15372 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
15373 ok(Provider_hwnd2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd2.ref);
15374 ok(Provider_nc2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc2.ref);
15376
15377 /*
15378 * The COM API has no equivalent to UiaEventAddWindow, which means all
15379 * event advisement has to be done by the COM API itself. It does this by
15380 * using EVENT_OBJECT_SHOW as a way to find HWNDs that need to be advised.
15381 */
15382 set_uia_hwnd_expects(0, 1, 1, 4, 0); /* Only done on Win11. */
15383 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15385 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15386 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15387 is_win11 = !!CALLED_COUNT(prov_callback_base_hwnd);
15388 check_uia_hwnd_expects_at_most(0, 1, 1, 4, 0);
15389
15390 set_provider_method_event_data(&Provider_hwnd2, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
15391 set_provider_method_event_data(&Provider_nc2, method_event[1], ADVISE_EVENTS_EVENT_ADDED);
15393 event_handle_count = 3;
15394
15395 /*
15396 * Raise EVENT_OBJECT_SHOW on a non-visible HWND. Its providers will not
15397 * be advised of events being listened for.
15398 */
15399 ok(!IsWindowVisible(test_hwnd), "Test HWND is visible\n");
15400 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15401 ok(msg_wait_for_all_events(method_event, event_handle_count, 500) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
15402
15403 /*
15404 * This fires off EVENT_OBJECT_SHOW, our providers will be advised of
15405 * events.
15406 */
15410
15411 set_uia_hwnd_expects(0, 2, 2, 6, 0); /* Only done more than one of each on Win11. */
15412 ShowWindow(test_hwnd, SW_SHOW);
15413 wait_res = msg_wait_for_all_events(method_event, event_handle_count, 3000);
15414 if ((wait_res == WAIT_TIMEOUT) && (Provider_nc2.advise_events_added_event_id && Provider_hwnd2.advise_events_added_event_id) &&
15416 {
15417 /*
15418 * Windows 7 won't advise a nested node provider from the current
15419 * process of events being listened for.
15420 */
15421 win_skip("Windows 7 only advises clientside providers of events, skipping further tests.\n");
15422 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15425 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15426 IUIAutomationElement_Release(elem);
15427
15428 set_provider_method_event_data(&Provider_hwnd2, NULL, -1);
15429 set_provider_method_event_data(&Provider_nc2, NULL, -1);
15431 goto exit;
15432 }
15433 ok(wait_res != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15435
15436 /*
15437 * Manually fire off EVENT_OBJECT_SHOW, providers will be advised of
15438 * events being added again.
15439 */
15440 set_uia_hwnd_expects(0, 2, 2, 6, 0); /* Only done more than one of each on Win11. */
15441 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15442 ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15444
15445 /*
15446 * Providers are only advised of events being listened for if an event is
15447 * raised with an objid of OBJID_WINDOW.
15448 */
15449 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15450 ok(msg_wait_for_all_events(method_event, event_handle_count, 500) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
15451
15452 set_provider_method_event_data(&Provider_hwnd2, NULL, -1);
15453 set_provider_method_event_data(&Provider_nc2, NULL, -1);
15455
15456 /*
15457 * Show our child HWND. Navigation is done to confirm it is within the
15458 * scope of our event handler, and it is only advised if it is.
15459 */
15460 set_provider_method_event_data(&Provider_hwnd3, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
15461 set_provider_method_event_data(&Provider_nc3, method_event[1], ADVISE_EVENTS_EVENT_ADDED);
15463
15464 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 6); /* Only done more than once on Win11. */
15465 set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
15466 ShowWindow(test_child_hwnd, SW_SHOW);
15467 ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15469 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
15470
15471 /* Same deal as before, it will advise multiple times. */
15472 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 6); /* Only done more than once on Win11. */
15473 set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
15474 NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15475 ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15477 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
15478
15479 /* Break navigation chain, can't reach our test element so no advisement. */
15480 Provider_hwnd3.parent = NULL;
15481 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only done more than once on Win11. */
15482 set_uia_hwnd_expects(0, 1, 1, 1, 0);
15483 NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15484 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
15485 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
15486 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
15487
15488 set_provider_method_event_data(&Provider_hwnd3, NULL, -1);
15489 set_provider_method_event_data(&Provider_nc3, NULL, -1);
15491
15492 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15495
15496 IUIAutomationElement_Release(elem);
15497
15498 /*
15499 * Register event handler on desktop element with a scope of
15500 * TreeScope_Subtree. All EVENT_OBJECT_SHOW events will result in event
15501 * advisement regardless of navigation.
15502 */
15503 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15504 hr = IUIAutomation_GetRootElement(uia_iface, &elem);
15505 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15506 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15507
15508 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
15509 set_uia_hwnd_expects(0, 2, 2, 3, 0); /* Only done on Win11. */
15510 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15513 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15514 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15515 check_uia_hwnd_expects_at_most(0, 2, 2, 3, 0);
15516
15520
15521 /*
15522 * Windows 11 always advises all HWNDs on the desktop, so we wait for our
15523 * child window provider to be advised as well.
15524 */
15525 if (is_win11)
15526 {
15528 event_handle_count++;
15529 }
15530
15531 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
15532 set_uia_hwnd_expects(0, 3, 3, 1, 0); /* Only done more than once on Win11. */
15534 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15535 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, 1);
15536 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15538
15542
15543 /*
15544 * Test window isn't connected to desktop element through navigation, but
15545 * still gets advised of events on a desktop HWND event.
15546 */
15547 set_provider_method_event_data(&Provider_hwnd2, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
15548 set_provider_method_event_data(&Provider_nc2, method_event[1], ADVISE_EVENTS_EVENT_ADDED);
15550 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
15551 set_uia_hwnd_expects(0, 2, 2, 7, 0); /* Only done more than once on Win11. */
15552 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15553 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15554 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15555 check_uia_hwnd_expects_at_most(0, 2, 2, 7, 0);
15556
15557 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15559 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15560
15561 IUIAutomationElement_Release(elem);
15562
15563 set_provider_method_event_data(&Provider_hwnd2, NULL, -1);
15564 set_provider_method_event_data(&Provider_nc2, NULL, -1);
15566 if (is_win11)
15568
15569 /*
15570 * IUIAutomationFocusChangedEventHandler is treated differently than all
15571 * other event handlers - it only advises providers of events the first
15572 * time it encounters an EVENT_OBJECT_FOCUS WinEvent for an HWND.
15573 */
15575 reset_event_advise_values_for_hwnd_providers(&Provider, &Provider_hwnd2, &Provider_nc2);
15576 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15577
15578 set_uia_hwnd_expects(0, 6, 6, 5, 0);
15579 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15581 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15583 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15584 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15585 check_uia_hwnd_expects_at_most(0, 6, 6, 5, 0);
15586 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15587
15588 /*
15589 * Windows 10 version 1507 and below only advise the currently focused
15590 * HWNDs providers of events being added - newer versions instead advise
15591 * the desktop HWND's providers of events being added. We're matching the
15592 * newer behavior, so skip the tests on older versions.
15593 */
15594 if (!Provider_nc.advise_events_added_event_id && !Provider_hwnd.advise_events_added_event_id &&
15595 !Provider_proxy.advise_events_added_event_id)
15596 {
15597 win_skip("Win10v1507 and below advise the currently focused HWND and not the desktop HWND, skipping tests.\n");
15598
15599 test_hwnd_providers_event_advise_added(&Provider, &Provider_hwnd2, &Provider_nc2, UIA_AutomationFocusChangedEventId, FALSE);
15600 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15601 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
15603 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15604 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15605 goto exit;
15606 }
15607
15608 /*
15609 * Currently focused HWND is not advised, it's expected that the desktop
15610 * providers will advise it using GetEmbeddedFragmentRoots.
15611 */
15612 test_provider_event_advise_added(&Provider_hwnd2, 0, FALSE);
15613 test_provider_event_advise_added(&Provider_nc2, 0, FALSE);
15615
15616 /*
15617 * EVENT_OBJECT_SHOW doesn't advise events on anything other than the
15618 * desktop HWND for focus changed event handlers.
15619 */
15620 event_handle_count = 3;
15621 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Win11 sends WM_GETOBJECT twice. */
15622 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, method_event, ADVISE_EVENTS_EVENT_ADDED);
15623 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15624 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15625 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15626 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15627 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, NULL, -1);
15628
15629 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, method_event, ADVISE_EVENTS_EVENT_ADDED);
15630 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only done twice on Win11. */
15631 set_uia_hwnd_expects(0, 1, 1, 1, 0);
15632 NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15633 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15634 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15635 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, NULL, -1);
15636 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
15637 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 2);
15638
15639 /*
15640 * This will advise events.
15641 */
15644 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15645 set_uia_hwnd_expects(0, 3, 3, 1, 0); /* Only Win11 sends WM_GETOBJECT. */
15646
15648 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15649 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15650
15653 check_uia_hwnd_expects_at_most(0, 3, 3, 1, 0);
15654 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15655
15656 /*
15657 * The HWND that was focused when adding the event handler is ignored,
15658 * EVENT_OBJECT_FOCUS only advises of events the first time
15659 * EVENT_OBJECT_FOCUS is raised on an HWND, and it tracks if it has
15660 * encountered a particular HWND before.
15661 */
15662 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, method_event, ADVISE_EVENTS_EVENT_ADDED);
15663 set_uia_hwnd_expects(0, 1, 1, 3, 0); /* Only Win11 sends WM_GETOBJECT 3 times. */
15664
15665 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15666 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15667 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15668
15669 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, NULL, -1);
15670 check_uia_hwnd_expects_at_most(0, 1, 1, 3, 0);
15671
15672 /* Only OBJID_CLIENT is listened for, all other OBJIDs are ignored. */
15673 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, method_event, ADVISE_EVENTS_EVENT_ADDED);
15674
15675 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15676 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15677 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15678
15679 /*
15680 * First time EVENT_OBJECT_FOCUS is fired for this HWND, it will be
15681 * advised of UIA_AutomationFocusChangedEventId being listened for.
15682 * But only the serverside provider.
15683 */
15684 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, NULL, -1);
15685 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15687 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
15688 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
15689
15690 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15691 ok(msg_wait_for_all_events(method_event, 1, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15692 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15693
15694 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15695 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
15696 test_provider_event_advise_added(&Provider2, UIA_AutomationFocusChangedEventId, FALSE);
15697 test_provider_event_advise_added(&Provider_hwnd3, 0, FALSE);
15698 test_provider_event_advise_added(&Provider_nc3, 0, FALSE);
15699
15700 /* Doing it again has no effect, it has already been advised. */
15701 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15702 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
15703 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
15704
15705 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15706 ok(msg_wait_for_all_events(method_event, 1, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15707 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15708
15710 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15711 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
15712 test_hwnd_providers_event_advise_added(&Provider2, &Provider_hwnd3, &Provider_nc3, 0, FALSE);
15713
15714 /*
15715 * Same deal here - we've already encountered this HWND and advised it
15716 * when the event handler was added initially, so it too is ignored.
15717 */
15718 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, method_event, ADVISE_EVENTS_EVENT_ADDED);
15719 reset_event_advise_values_for_hwnd_providers(&Provider, &Provider_hwnd2, &Provider_nc2);
15720 set_uia_hwnd_expects(0, 1, 1, 3, 0); /* Only Win11 sends WM_GETOBJECT 3 times. */
15721
15722 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15723 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15724 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15725
15726 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, NULL, -1);
15727 check_uia_hwnd_expects_at_most(0, 1, 1, 3, 0);
15728 test_hwnd_providers_event_advise_added(&Provider, &Provider_hwnd2, &Provider_nc2, 0, FALSE);
15729
15730 /* HWND destruction is tracked with EVENT_OBJECT_DESTROY/OBJID_WINDOW. */
15731 NotifyWinEvent(EVENT_OBJECT_DESTROY, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15732 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15733
15734 /*
15735 * EVENT_OBJECT_DESTROY removed this HWND, EVENT_OBJECT_FOCUS will now
15736 * advise it again.
15737 */
15738 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15740 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
15741 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
15742
15743 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15744 wait_res = msg_wait_for_all_events(method_event, 1, 2000);
15745 ok(wait_res != WAIT_TIMEOUT || broken(wait_res == WAIT_TIMEOUT), /* Win10v1709 */
15746 "Wait for method_event(s) timed out.\n");
15747 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15748
15750 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15751 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
15752 if (!winetest_platform_is_wine && (wait_res == WAIT_TIMEOUT)) /* Win10v1709 */
15754 else
15755 test_provider_event_advise_added(&Provider2, UIA_AutomationFocusChangedEventId, FALSE);
15756 test_provider_event_advise_added(&Provider_hwnd3, 0, FALSE);
15757 test_provider_event_advise_added(&Provider_nc3, 0, FALSE);
15758
15759 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15760 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
15762 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15763 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15764
15765exit:
15766 Provider_hwnd3.parent = &Provider_hwnd2.IRawElementProviderFragment_iface;
15767 for (i = 0; i < ARRAY_SIZE(method_event); i++)
15768 CloseHandle(method_event[i]);
15769}
15770
15771static struct MultiEventData {
15773
15777
15779{
15782
15784}
15785
15787{
15790}
15791
15792static void WINAPI multi_uia_event_callback(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
15793{
15794 struct node_provider_desc *exp_desc;
15795 LONG exp_lbound[2], exp_elems[2];
15796
15798 return;
15799
15801
15802 exp_lbound[0] = exp_lbound[1] = 0;
15803 exp_elems[0] = exp_elems[1] = 1;
15805 test_cache_req_sa(req_data, exp_lbound, exp_elems, exp_desc);
15806
15807 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
15808 if (MultiEventData.event_handle && (MultiEventData.exp_events.exp_event_count == MultiEventData.exp_events.exp_event_pos))
15810}
15811
15813 HWND test_child_hwnd)
15814{
15815 struct UiaCacheRequest cache_req = { (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15817 struct node_provider_desc exp_node_desc, exp_nested_node_desc;
15818 struct Provider_prop_override prop_override;
15819 HANDLE event_handles[2];
15820 HUIAEVENT event;
15821 HUIANODE node;
15822 HRESULT hr;
15823 VARIANT v;
15824 int i;
15825
15826 for (i = 0; i < ARRAY_SIZE(event_handles); i++)
15827 event_handles[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
15828
15829 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15832 ok(!!node, "Node == NULL.\n");
15833 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15834
15835 set_uia_hwnd_expects(0, 6, 6, 5, 0);
15836 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15837 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, multi_uia_event_callback, TreeScope_Subtree, NULL, 0, &cache_req,
15838 &event);
15839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15840 ok(!!event, "event == NULL.\n");
15841 check_uia_hwnd_expects_at_most(0, 6, 6, 5, 0);
15842 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15843
15845
15846 MultiEventData.event_handle = event_handles[0];
15847 ComEventData.event_handle = event_handles[1];
15848
15849 /*
15850 * No IUIAutomationFocusChangedEventHandler is installed, and no
15851 * IProxyProviderWinEventHandler interfaces were returned from our
15852 * clientside desktop providers. This WinEvent will be ignored.
15853 */
15854 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15855 ok(msg_wait_for_all_events(event_handles, 1, 750) == WAIT_TIMEOUT, "Wait for event_handle(s) didn't time out.\n");
15856
15857 /* Add our IUIAutomationFocusChangedEventHandler. */
15858 set_uia_hwnd_expects(0, 6, 6, 5, 0);
15859 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15862 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15864 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15865 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15866 check_uia_hwnd_expects_at_most(0, 6, 6, 5, 0);
15867 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15868
15869 /*
15870 * Now that we have an IUIAutomationFocusChangedEventHandler installed,
15871 * EVENT_OBJECT_FOCUS events will be translated into native UIA events on
15872 * our serverside provider. This is done for both HUIAEVENTs and COM
15873 * events, unlike event advisement which only applies to COM event
15874 * handlers.
15875 */
15878 init_node_provider_desc(&exp_nested_node_desc, GetCurrentProcessId(), test_hwnd);
15879 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider", TRUE);
15880
15881 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_hwnd);
15882 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
15883 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
15884 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, TRUE, &exp_nested_node_desc);
15885
15886 set_multi_event_data(&exp_node_desc);
15887 set_com_event_data(&exp_node_desc);
15888
15889 set_uia_hwnd_expects(0, 2, 2, 4, 0); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15890 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15891 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15892 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15896
15897 /*
15898 * Child ID is ignored when translating EVENT_OBJECT_FOCUS events into
15899 * native UIA events on our serverside provider.
15900 */
15901 set_multi_event_data(&exp_node_desc);
15902 set_com_event_data(&exp_node_desc);
15903 set_uia_hwnd_expects(0, 2, 2, 4, 0); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15904
15905 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, -1);
15906 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15907 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15911
15912 /*
15913 * UIA queries the serverside provider for UIA_HasKeyboardFocusPropertyId.
15914 * If this is anything other than TRUE, it won't raise an event for our
15915 * serverside provider.
15916 */
15918 set_property_override(&prop_override, UIA_HasKeyboardFocusPropertyId, &v);
15919 set_provider_prop_override(&Provider, &prop_override, 1);
15920
15921 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2); /* Only done twice on Win11. */
15922 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15923 ok(msg_wait_for_all_events(event_handles, 2, 750) == WAIT_TIMEOUT, "Wait for event_handle(s) didn't time out.\n");
15924 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15925 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
15927
15928 /*
15929 * The first time EVENT_OBJECT_FOCUS is raised for an HWND with a
15930 * serverside provider UIA will query for the currently focused provider
15931 * and raise a focus change event for it, alongside advising the root
15932 * provider of focus change events being listened for. All subsequent
15933 * EVENT_OBJECT_FOCUS events on the same HWND only query the root
15934 * provider.
15935 */
15937 Provider_child2.parent = &Provider2.IRawElementProviderFragment_iface;
15938 Provider_child2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
15939 Provider2.focus_prov = &Provider_child2.IRawElementProviderFragment_iface;
15942
15944 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child2", TRUE);
15945
15946 set_multi_event_data(&exp_node_desc);
15947 set_com_event_data(&exp_node_desc);
15948
15949 /* Second event. */
15950 init_node_provider_desc(&exp_nested_node_desc, GetCurrentProcessId(), test_child_hwnd);
15951 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider2", TRUE);
15952
15953 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_child_hwnd);
15954 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd3", TRUE);
15955 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc3", FALSE);
15956 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, FALSE, &exp_nested_node_desc);
15957
15958 push_expected_event(&exp_node_desc);
15959 push_expected_com_event(&exp_node_desc);
15960 set_uia_hwnd_expects(0, 2, 2, 3, 0); /* Win11 sends 3 WM_GETOBJECT messages, normally only 2. */
15961 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15962 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15963 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15964 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15966 CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 3);
15969
15970 /*
15971 * Second time EVENT_OBJECT_FOCUS is raised for this HWND, only the root
15972 * provider will have an event raised.
15973 */
15974 init_node_provider_desc(&exp_nested_node_desc, GetCurrentProcessId(), test_child_hwnd);
15975 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider2", TRUE);
15976
15977 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_child_hwnd);
15978 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd3", TRUE);
15979 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc3", FALSE);
15980 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, FALSE, &exp_nested_node_desc);
15981
15982 set_multi_event_data(&exp_node_desc);
15983 set_com_event_data(&exp_node_desc);
15984 set_uia_hwnd_expects(0, 2, 2, 3, 0); /* Win11 sends 3 WM_GETOBJECT messages, normally only 2. */
15985 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15986 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15987 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15988 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15990 CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 3);
15993
15994 /*
15995 * Windows 7 has quirky behavior around MSAA proxy creation, skip tests.
15996 */
15997 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
15998 {
15999 win_skip("Skipping focus MSAA proxy tests for Win7\n");
16000 goto exit;
16001 }
16002
16003 /*
16004 * Creates an MSAA proxy, raises event on that.
16005 */
16006 prov_root = NULL;
16007 set_accessible_props(&Accessible, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
16008 Accessible.ow_hwnd = test_hwnd;
16011
16012 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_hwnd);
16013 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
16014 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
16015 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16016
16017 set_multi_event_data(&exp_node_desc);
16018 set_com_event_data(&exp_node_desc);
16019
16020 set_uia_hwnd_expects(0, 1, 1, 4, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 2. */
16021 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 3);
16022 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accParent, 3);
16023 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
16024 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
16025 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
16026 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16027 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16029 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, QI_IAccIdentity);
16031 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
16032 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
16035
16036 /*
16037 * Return Accessible_child2 from get_accFocus.
16038 */
16039 set_accessible_props(&Accessible, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
16040 Accessible.focus_child_id = 4; /* 4 gets us Accessible_child2. */
16041 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSED, 0, L"acc_child2", 0, 0, 0, 0);
16042
16044 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16045
16046 set_multi_event_data(&exp_node_desc);
16047 set_com_event_data(&exp_node_desc);
16048 set_uia_hwnd_expects(0, 0, 0, 2, 3); /* Win11 sends 2/3 WM_GETOBJECT messages, normally only 1/2. */
16049 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 4); /* Only done 4 times on Win11, normally 3. */
16050 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accParent, 3); /* Only done 3 times on Win11, normally 2. */
16051 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
16052 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
16053 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
16054 SET_ACC_METHOD_EXPECT(&Accessible_child2, QI_IAccIdentity);
16057 SET_ACC_METHOD_EXPECT(&Accessible_child2, accNavigate); /* Wine only, Windows doesn't pass this through the DA wrapper. */
16060 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
16061 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16062 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16066 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
16067 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
16068 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
16077
16078 /*
16079 * accFocus returns Accessible_child2, however it has
16080 * STATE_SYSTEM_INVISIBLE set. Falls back to Accessible.
16081 */
16082 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_FOCUSED, 0, L"acc_child2", 0, 0, 0, 0);
16083 set_accessible_props(&Accessible, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
16084
16085 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_hwnd);
16086 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
16087 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
16088 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16089
16090 set_multi_event_data(&exp_node_desc);
16091 set_com_event_data(&exp_node_desc);
16092 set_uia_hwnd_expects(0, 1, 1, 4, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 2. */
16093 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 4); /* Only done 4 times on Win11, normally 2. */
16094 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accParent, 3); /* Only done 3 times on Win11, normally 1. */
16095 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
16096 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
16097 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
16098 SET_ACC_METHOD_EXPECT(&Accessible_child2, accNavigate); /* Wine only, Windows doesn't pass this through the DA wrapper. */
16099 SET_ACC_METHOD_EXPECT(&Accessible_child2, QI_IAccIdentity);
16102 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
16103 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16104 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16108 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
16109 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
16110 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
16117
16118 /*
16119 * Get Accessible_child2 by raising an event with its child ID directly.
16120 * It will have its get_accFocus method called.
16121 */
16123 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16124
16125 set_multi_event_data(&exp_node_desc);
16126 set_com_event_data(&exp_node_desc);
16127 set_uia_hwnd_expects(0, 0, 0, 2, 2); /* Win11 sends 2/2 WM_GETOBJECT messages, normally only 1/1. */
16128 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 2); /* Only done 2 times on Win11, normally 1. */
16129 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent); /* Only done on Win11. */
16130 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
16131 SET_ACC_METHOD_EXPECT(&Accessible_child2, QI_IAccIdentity);
16135 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, 4);
16136 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16137 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16139 CHECK_ACC_METHOD_CALLED_AT_MOST(&Accessible, get_accParent, 1); /* Only done on Win11. */
16140 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, QI_IAccIdentity);
16141 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
16148 acc_client = NULL;
16149
16150exit:
16151 set_uia_hwnd_expects(0, 1, 1, 0, 0);
16152 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
16154 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16155 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
16156
16158 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16159
16161 for (i = 0; i < ARRAY_SIZE(event_handles); i++)
16162 CloseHandle(event_handles[i]);
16163}
16164
16166{
16168 IUIAutomation *uia_iface = test_data->uia_iface;
16169
16172
16175
16176 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16179
16180 return 0;
16181}
16182
16184{
16186 IUIAutomationElement *elem;
16187 HANDLE thread;
16188 HRESULT hr;
16189 HWND hwnd;
16190
16191 test_data.test_hwnd = ComEventData.event_hwnd = hwnd = create_test_hwnd("test_CUIAutomation_event_handlers class");
16192
16193 /* Set up providers for the desktop window and our test HWND. */
16195 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
16196 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
16197 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
16198
16199 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
16204
16206 set_uia_hwnd_expects(1, 1, 1, 1, 1);
16208 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &elem);
16209 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16210 ok(!!elem, "elem == NULL\n");
16211 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
16212 ok(Provider_hwnd2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd2.ref);
16213 ok(Provider_nc2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc2.ref);
16214 check_uia_hwnd_expects(1, TRUE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
16215
16218 IUIAutomationElement_Release(elem);
16219
16220 /* Create a test child window. */
16221 test_data.test_child_hwnd = create_child_test_hwnd("test_CUIAutomation_event_handlers child class", hwnd);
16222 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, test_data.test_child_hwnd);
16224 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
16225 Provider2.ignore_hwnd_prop = TRUE;
16226 Provider_hwnd3.parent = &Provider_hwnd2.IRawElementProviderFragment_iface;
16227 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
16228
16229 hr = IUIAutomation_RemoveAllEventHandlers(uia_iface);
16230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16231
16232 /*
16233 * Particular versions of Windows 7 trigger access violations when doing
16234 * WinEvent tests, just skip them for Windows 7.
16235 */
16236 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
16237 {
16238 win_skip("Skipping COM API WinEvent translation tests for Win7\n");
16239 goto exit;
16240 }
16241
16244 {
16245 MSG msg;
16246
16247 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
16248 {
16251 }
16252 }
16254
16255exit:
16258 UnregisterClassA("test_CUIAutomation_event_handlers class", NULL);
16259 UnregisterClassA("test_CUIAutomation_event_handlers child class", NULL);
16261}
16262
16264 const GUID *clsid;
16265 const GUID *iid;
16266};
16267
16268static const struct uia_com_classes com_classes[] = {
16269 { &CLSID_CUIAutomation, &IID_IUnknown },
16270 { &CLSID_CUIAutomation, &IID_IUIAutomation },
16271 { &CLSID_CUIAutomation8, &IID_IUnknown },
16272 { &CLSID_CUIAutomation8, &IID_IUIAutomation },
16273 { &CLSID_CUIAutomation8, &IID_IUIAutomation2 },
16274 { &CLSID_CUIAutomation8, &IID_IUIAutomation3 },
16275 { &CLSID_CUIAutomation8, &IID_IUIAutomation4 },
16276 { &CLSID_CUIAutomation8, &IID_IUIAutomation5 },
16277 { &CLSID_CUIAutomation8, &IID_IUIAutomation6 },
16278};
16279
16280static void test_CUIAutomation(void)
16281{
16282 BOOL has_cui8 = TRUE, tmp_b;
16283 IUIAutomation *uia_iface;
16284 IUnknown *unk1, *unk2;
16285 HRESULT hr;
16286 VARIANT v;
16287 int i;
16288
16290
16291 for (i = 0; i < ARRAY_SIZE(com_classes); i++)
16292 {
16293 IUnknown *iface = NULL;
16294
16295 hr = CoCreateInstance(com_classes[i].clsid, NULL, CLSCTX_INPROC_SERVER, com_classes[i].iid,
16296 (void **)&iface);
16297
16298 if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG))
16299 {
16300 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
16301 has_cui8 = FALSE;
16302 break;
16303 }
16304 else if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == E_NOINTERFACE) &&
16305 (com_classes[i].iid != &IID_IUIAutomation2) && (com_classes[i].iid != &IID_IUIAutomation) &&
16307 {
16308 win_skip("No object for clsid %s, iid %s, skipping further tests.\n", debugstr_guid(com_classes[i].clsid),
16310 break;
16311 }
16312
16313 ok(hr == S_OK, "Failed to create interface for clsid %s, iid %s, hr %#lx\n",
16315 ok(!!iface, "iface == NULL\n");
16316 IUnknown_Release(iface);
16317 }
16318
16319 if (has_cui8)
16320 hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
16321 (void **)&uia_iface);
16322 else
16323 hr = CoCreateInstance(&CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
16324 (void **)&uia_iface);
16325 ok(hr == S_OK, "Failed to create IUIAutomation interface, hr %#lx\n", hr);
16326 ok(!!uia_iface, "uia_iface == NULL\n");
16327
16328 /* Reserved value retrieval methods. */
16330 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16331
16332 hr = IUIAutomation_get_ReservedNotSupportedValue(uia_iface, &unk2);
16333 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16334 ok(unk1 == unk2, "unk1 != unk2\n");
16335
16336 V_VT(&v) = VT_UNKNOWN;
16337 V_UNKNOWN(&v) = unk1;
16338 hr = IUIAutomation_CheckNotSupported(uia_iface, v, &tmp_b);
16339 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16340 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
16341
16342 IUnknown_Release(unk1);
16343 IUnknown_Release(unk2);
16344
16346 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16347
16348 hr = IUIAutomation_get_ReservedMixedAttributeValue(uia_iface, &unk2);
16349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16350 ok(unk1 == unk2, "unk1 != unk2\n");
16351
16352 V_VT(&v) = VT_UNKNOWN;
16353 V_UNKNOWN(&v) = unk1;
16354 hr = IUIAutomation_CheckNotSupported(uia_iface, v, &tmp_b);
16355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16356 ok(tmp_b == FALSE, "tmp_b != FALSE\n");
16357
16358 IUnknown_Release(unk1);
16359 IUnknown_Release(unk2);
16360
16372
16373 IUIAutomation_Release(uia_iface);
16375}
16376
16378 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
16379 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16380 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
16381 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16382 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NamePropertyId */
16383 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16384 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_NamePropertyId */
16385 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16386 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ClassNamePropertyId */
16387 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16388 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ClassNamePropertyId */
16389 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16390 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProcessIdPropertyId */
16392 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProcessIdPropertyId */
16394 { 0 }
16395};
16396
16397#define test_node_hwnd_provider( node, hwnd ) \
16398 test_node_hwnd_provider_( (node), (hwnd), __FILE__, __LINE__)
16399static void test_node_hwnd_provider_(HUIANODE node, HWND hwnd, const char *file, int line)
16400{
16401 WCHAR buf[1024] = { 0 };
16402 HRESULT hr;
16403 VARIANT v;
16404 DWORD pid;
16405
16406 winetest_push_context("UIA_NativeWindowHandlePropertyId");
16407 hr = UiaGetPropertyValue(node, UIA_NativeWindowHandlePropertyId, &v);
16408 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16409 ok_(file, line)(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16410 ok_(file, line)(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
16411 VariantClear(&v);
16413
16414 winetest_push_context("UIA_NamePropertyId");
16416 hr = UiaGetPropertyValue(node, UIA_NamePropertyId, &v);
16417 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16418 ok_(file, line)(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
16419 ok(!lstrcmpW(V_BSTR(&v), buf), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
16420 VariantClear(&v);
16422
16423 winetest_push_context("UIA_ClassNamePropertyId");
16424 memset(buf, 0, sizeof(buf));
16426 hr = UiaGetPropertyValue(node, UIA_ClassNamePropertyId, &v);
16427 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16428 ok_(file, line)(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
16429 ok(!lstrcmpW(V_BSTR(&v), buf), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
16430 VariantClear(&v);
16432
16434 winetest_push_context("UIA_ProcessIdPropertyId");
16435 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
16436 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16437 ok_(file, line)(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16438 ok_(file, line)(V_I4(&v) == pid, "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), pid);
16439 VariantClear(&v);
16441}
16442
16443enum {
16447};
16448
16454};
16455
16457 { WS_OVERLAPPEDWINDOW, 0, UIA_WindowControlTypeId, PARENT_HWND_NULL },
16458 /* Top-level window (parent is desktop window) is always a window control. */
16459 { WS_CHILD, 0, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
16460 /* Not a top-level window, considered a pane. */
16461 { WS_CHILD, 0, UIA_PaneControlTypeId, PARENT_HWND_HWND },
16462 /* Not a top-level window, but WS_EX_APPWINDOW is always considered a window. */
16463 { WS_CHILD, WS_EX_APPWINDOW, UIA_WindowControlTypeId, PARENT_HWND_HWND },
16464 /*
16465 * WS_POPUP is always a pane regardless of being a top level window,
16466 * unless WS_CAPTION is set.
16467 */
16468 { WS_CAPTION | WS_POPUP, 0, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
16469 { WS_BORDER | WS_POPUP, 0, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
16470 { WS_POPUP, 0, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
16471 /*
16472 * Top level window with WS_EX_TOOLWINDOW and without WS_CAPTION is
16473 * considered a pane.
16474 */
16475 { WS_CHILD, WS_EX_TOOLWINDOW, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
16476 { WS_CHILD | WS_CAPTION, WS_EX_TOOLWINDOW, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
16477};
16478
16479static void create_base_hwnd_test_node(HWND hwnd, BOOL child_hwnd, struct Provider *main, struct Provider *nc,
16480 HUIANODE *ret_node)
16481{
16482 ULONG main_ref, nc_ref;
16483 HRESULT hr;
16484
16487 nc->ignore_hwnd_prop = main->ignore_hwnd_prop = TRUE;
16488 main_ref = main->ref;
16489 nc_ref = nc->ref;