uiautomationcore/tests: Increase wait timeout for cross-process event with navigation.
[wine.git] / dlls / uiautomationcore / tests / uiautomation.c
blobf396adc1200fe10a0d687e4c984d321af6476e08
1 /*
2 * UI Automation tests
4 * Copyright 2019 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define COBJMACROS
23 #include <assert.h>
24 #include "windows.h"
25 #include "initguid.h"
26 #include "uiautomation.h"
27 #include "ocidl.h"
28 #include "wine/iaccessible2.h"
30 #include "wine/test.h"
32 static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, LONG, DWORD, IRawElementProviderSimple **);
33 static HRESULT (WINAPI *pUiaDisconnectProvider)(IRawElementProviderSimple *);
35 struct str_id_pair {
36 int id;
37 const char *str;
40 static const struct str_id_pair uia_prop_id_strs[] = {
41 { UIA_RuntimeIdPropertyId, "UIA_RuntimeIdPropertyId", },
42 { UIA_BoundingRectanglePropertyId, "UIA_BoundingRectanglePropertyId", },
43 { UIA_ProcessIdPropertyId, "UIA_ProcessIdPropertyId", },
44 { UIA_ControlTypePropertyId, "UIA_ControlTypePropertyId", },
45 { UIA_LocalizedControlTypePropertyId, "UIA_LocalizedControlTypePropertyId", },
46 { UIA_NamePropertyId, "UIA_NamePropertyId", },
47 { UIA_AcceleratorKeyPropertyId, "UIA_AcceleratorKeyPropertyId", },
48 { UIA_AccessKeyPropertyId, "UIA_AccessKeyPropertyId", },
49 { UIA_HasKeyboardFocusPropertyId, "UIA_HasKeyboardFocusPropertyId", },
50 { UIA_IsKeyboardFocusablePropertyId, "UIA_IsKeyboardFocusablePropertyId", },
51 { UIA_IsEnabledPropertyId, "UIA_IsEnabledPropertyId", },
52 { UIA_AutomationIdPropertyId, "UIA_AutomationIdPropertyId", },
53 { UIA_ClassNamePropertyId, "UIA_ClassNamePropertyId", },
54 { UIA_HelpTextPropertyId, "UIA_HelpTextPropertyId", },
55 { UIA_ClickablePointPropertyId, "UIA_ClickablePointPropertyId", },
56 { UIA_CulturePropertyId, "UIA_CulturePropertyId", },
57 { UIA_IsControlElementPropertyId, "UIA_IsControlElementPropertyId", },
58 { UIA_IsContentElementPropertyId, "UIA_IsContentElementPropertyId", },
59 { UIA_LabeledByPropertyId, "UIA_LabeledByPropertyId", },
60 { UIA_IsPasswordPropertyId, "UIA_IsPasswordPropertyId", },
61 { UIA_NativeWindowHandlePropertyId, "UIA_NativeWindowHandlePropertyId", },
62 { UIA_ItemTypePropertyId, "UIA_ItemTypePropertyId", },
63 { UIA_IsOffscreenPropertyId, "UIA_IsOffscreenPropertyId", },
64 { UIA_OrientationPropertyId, "UIA_OrientationPropertyId", },
65 { UIA_FrameworkIdPropertyId, "UIA_FrameworkIdPropertyId", },
66 { UIA_IsRequiredForFormPropertyId, "UIA_IsRequiredForFormPropertyId", },
67 { UIA_ItemStatusPropertyId, "UIA_ItemStatusPropertyId", },
68 { UIA_IsDockPatternAvailablePropertyId, "UIA_IsDockPatternAvailablePropertyId", },
69 { UIA_IsExpandCollapsePatternAvailablePropertyId, "UIA_IsExpandCollapsePatternAvailablePropertyId", },
70 { UIA_IsGridItemPatternAvailablePropertyId, "UIA_IsGridItemPatternAvailablePropertyId", },
71 { UIA_IsGridPatternAvailablePropertyId, "UIA_IsGridPatternAvailablePropertyId", },
72 { UIA_IsInvokePatternAvailablePropertyId, "UIA_IsInvokePatternAvailablePropertyId", },
73 { UIA_IsMultipleViewPatternAvailablePropertyId, "UIA_IsMultipleViewPatternAvailablePropertyId", },
74 { UIA_IsRangeValuePatternAvailablePropertyId, "UIA_IsRangeValuePatternAvailablePropertyId", },
75 { UIA_IsScrollPatternAvailablePropertyId, "UIA_IsScrollPatternAvailablePropertyId", },
76 { UIA_IsScrollItemPatternAvailablePropertyId, "UIA_IsScrollItemPatternAvailablePropertyId", },
77 { UIA_IsSelectionItemPatternAvailablePropertyId, "UIA_IsSelectionItemPatternAvailablePropertyId", },
78 { UIA_IsSelectionPatternAvailablePropertyId, "UIA_IsSelectionPatternAvailablePropertyId", },
79 { UIA_IsTablePatternAvailablePropertyId, "UIA_IsTablePatternAvailablePropertyId", },
80 { UIA_IsTableItemPatternAvailablePropertyId, "UIA_IsTableItemPatternAvailablePropertyId", },
81 { UIA_IsTextPatternAvailablePropertyId, "UIA_IsTextPatternAvailablePropertyId", },
82 { UIA_IsTogglePatternAvailablePropertyId, "UIA_IsTogglePatternAvailablePropertyId", },
83 { UIA_IsTransformPatternAvailablePropertyId, "UIA_IsTransformPatternAvailablePropertyId", },
84 { UIA_IsValuePatternAvailablePropertyId, "UIA_IsValuePatternAvailablePropertyId", },
85 { UIA_IsWindowPatternAvailablePropertyId, "UIA_IsWindowPatternAvailablePropertyId", },
86 { UIA_ValueValuePropertyId, "UIA_ValueValuePropertyId", },
87 { UIA_ValueIsReadOnlyPropertyId, "UIA_ValueIsReadOnlyPropertyId", },
88 { UIA_RangeValueValuePropertyId, "UIA_RangeValueValuePropertyId", },
89 { UIA_RangeValueIsReadOnlyPropertyId, "UIA_RangeValueIsReadOnlyPropertyId", },
90 { UIA_RangeValueMinimumPropertyId, "UIA_RangeValueMinimumPropertyId", },
91 { UIA_RangeValueMaximumPropertyId, "UIA_RangeValueMaximumPropertyId", },
92 { UIA_RangeValueLargeChangePropertyId, "UIA_RangeValueLargeChangePropertyId", },
93 { UIA_RangeValueSmallChangePropertyId, "UIA_RangeValueSmallChangePropertyId", },
94 { UIA_ScrollHorizontalScrollPercentPropertyId, "UIA_ScrollHorizontalScrollPercentPropertyId", },
95 { UIA_ScrollHorizontalViewSizePropertyId, "UIA_ScrollHorizontalViewSizePropertyId", },
96 { UIA_ScrollVerticalScrollPercentPropertyId, "UIA_ScrollVerticalScrollPercentPropertyId", },
97 { UIA_ScrollVerticalViewSizePropertyId, "UIA_ScrollVerticalViewSizePropertyId", },
98 { UIA_ScrollHorizontallyScrollablePropertyId, "UIA_ScrollHorizontallyScrollablePropertyId", },
99 { UIA_ScrollVerticallyScrollablePropertyId, "UIA_ScrollVerticallyScrollablePropertyId", },
100 { UIA_SelectionSelectionPropertyId, "UIA_SelectionSelectionPropertyId", },
101 { UIA_SelectionCanSelectMultiplePropertyId, "UIA_SelectionCanSelectMultiplePropertyId", },
102 { UIA_SelectionIsSelectionRequiredPropertyId, "UIA_SelectionIsSelectionRequiredPropertyId", },
103 { UIA_GridRowCountPropertyId, "UIA_GridRowCountPropertyId", },
104 { UIA_GridColumnCountPropertyId, "UIA_GridColumnCountPropertyId", },
105 { UIA_GridItemRowPropertyId, "UIA_GridItemRowPropertyId", },
106 { UIA_GridItemColumnPropertyId, "UIA_GridItemColumnPropertyId", },
107 { UIA_GridItemRowSpanPropertyId, "UIA_GridItemRowSpanPropertyId", },
108 { UIA_GridItemColumnSpanPropertyId, "UIA_GridItemColumnSpanPropertyId", },
109 { UIA_GridItemContainingGridPropertyId, "UIA_GridItemContainingGridPropertyId", },
110 { UIA_DockDockPositionPropertyId, "UIA_DockDockPositionPropertyId", },
111 { UIA_ExpandCollapseExpandCollapseStatePropertyId, "UIA_ExpandCollapseExpandCollapseStatePropertyId", },
112 { UIA_MultipleViewCurrentViewPropertyId, "UIA_MultipleViewCurrentViewPropertyId", },
113 { UIA_MultipleViewSupportedViewsPropertyId, "UIA_MultipleViewSupportedViewsPropertyId", },
114 { UIA_WindowCanMaximizePropertyId, "UIA_WindowCanMaximizePropertyId", },
115 { UIA_WindowCanMinimizePropertyId, "UIA_WindowCanMinimizePropertyId", },
116 { UIA_WindowWindowVisualStatePropertyId, "UIA_WindowWindowVisualStatePropertyId", },
117 { UIA_WindowWindowInteractionStatePropertyId, "UIA_WindowWindowInteractionStatePropertyId", },
118 { UIA_WindowIsModalPropertyId, "UIA_WindowIsModalPropertyId", },
119 { UIA_WindowIsTopmostPropertyId, "UIA_WindowIsTopmostPropertyId", },
120 { UIA_SelectionItemIsSelectedPropertyId, "UIA_SelectionItemIsSelectedPropertyId", },
121 { UIA_SelectionItemSelectionContainerPropertyId, "UIA_SelectionItemSelectionContainerPropertyId", },
122 { UIA_TableRowHeadersPropertyId, "UIA_TableRowHeadersPropertyId", },
123 { UIA_TableColumnHeadersPropertyId, "UIA_TableColumnHeadersPropertyId", },
124 { UIA_TableRowOrColumnMajorPropertyId, "UIA_TableRowOrColumnMajorPropertyId", },
125 { UIA_TableItemRowHeaderItemsPropertyId, "UIA_TableItemRowHeaderItemsPropertyId", },
126 { UIA_TableItemColumnHeaderItemsPropertyId, "UIA_TableItemColumnHeaderItemsPropertyId", },
127 { UIA_ToggleToggleStatePropertyId, "UIA_ToggleToggleStatePropertyId", },
128 { UIA_TransformCanMovePropertyId, "UIA_TransformCanMovePropertyId", },
129 { UIA_TransformCanResizePropertyId, "UIA_TransformCanResizePropertyId", },
130 { UIA_TransformCanRotatePropertyId, "UIA_TransformCanRotatePropertyId", },
131 { UIA_IsLegacyIAccessiblePatternAvailablePropertyId, "UIA_IsLegacyIAccessiblePatternAvailablePropertyId", },
132 { UIA_LegacyIAccessibleChildIdPropertyId, "UIA_LegacyIAccessibleChildIdPropertyId", },
133 { UIA_LegacyIAccessibleNamePropertyId, "UIA_LegacyIAccessibleNamePropertyId", },
134 { UIA_LegacyIAccessibleValuePropertyId, "UIA_LegacyIAccessibleValuePropertyId", },
135 { UIA_LegacyIAccessibleDescriptionPropertyId, "UIA_LegacyIAccessibleDescriptionPropertyId", },
136 { UIA_LegacyIAccessibleRolePropertyId, "UIA_LegacyIAccessibleRolePropertyId", },
137 { UIA_LegacyIAccessibleStatePropertyId, "UIA_LegacyIAccessibleStatePropertyId", },
138 { UIA_LegacyIAccessibleHelpPropertyId, "UIA_LegacyIAccessibleHelpPropertyId", },
139 { UIA_LegacyIAccessibleKeyboardShortcutPropertyId, "UIA_LegacyIAccessibleKeyboardShortcutPropertyId", },
140 { UIA_LegacyIAccessibleSelectionPropertyId, "UIA_LegacyIAccessibleSelectionPropertyId", },
141 { UIA_LegacyIAccessibleDefaultActionPropertyId, "UIA_LegacyIAccessibleDefaultActionPropertyId", },
142 { UIA_AriaRolePropertyId, "UIA_AriaRolePropertyId", },
143 { UIA_AriaPropertiesPropertyId, "UIA_AriaPropertiesPropertyId", },
144 { UIA_IsDataValidForFormPropertyId, "UIA_IsDataValidForFormPropertyId", },
145 { UIA_ControllerForPropertyId, "UIA_ControllerForPropertyId", },
146 { UIA_DescribedByPropertyId, "UIA_DescribedByPropertyId", },
147 { UIA_FlowsToPropertyId, "UIA_FlowsToPropertyId", },
148 { UIA_ProviderDescriptionPropertyId, "UIA_ProviderDescriptionPropertyId", },
149 { UIA_IsItemContainerPatternAvailablePropertyId, "UIA_IsItemContainerPatternAvailablePropertyId", },
150 { UIA_IsVirtualizedItemPatternAvailablePropertyId, "UIA_IsVirtualizedItemPatternAvailablePropertyId", },
151 { UIA_IsSynchronizedInputPatternAvailablePropertyId, "UIA_IsSynchronizedInputPatternAvailablePropertyId", },
152 { UIA_OptimizeForVisualContentPropertyId, "UIA_OptimizeForVisualContentPropertyId", },
153 { UIA_IsObjectModelPatternAvailablePropertyId, "UIA_IsObjectModelPatternAvailablePropertyId", },
154 { UIA_AnnotationAnnotationTypeIdPropertyId, "UIA_AnnotationAnnotationTypeIdPropertyId", },
155 { UIA_AnnotationAnnotationTypeNamePropertyId, "UIA_AnnotationAnnotationTypeNamePropertyId", },
156 { UIA_AnnotationAuthorPropertyId, "UIA_AnnotationAuthorPropertyId", },
157 { UIA_AnnotationDateTimePropertyId, "UIA_AnnotationDateTimePropertyId", },
158 { UIA_AnnotationTargetPropertyId, "UIA_AnnotationTargetPropertyId", },
159 { UIA_IsAnnotationPatternAvailablePropertyId, "UIA_IsAnnotationPatternAvailablePropertyId", },
160 { UIA_IsTextPattern2AvailablePropertyId, "UIA_IsTextPattern2AvailablePropertyId", },
161 { UIA_StylesStyleIdPropertyId, "UIA_StylesStyleIdPropertyId", },
162 { UIA_StylesStyleNamePropertyId, "UIA_StylesStyleNamePropertyId", },
163 { UIA_StylesFillColorPropertyId, "UIA_StylesFillColorPropertyId", },
164 { UIA_StylesFillPatternStylePropertyId, "UIA_StylesFillPatternStylePropertyId", },
165 { UIA_StylesShapePropertyId, "UIA_StylesShapePropertyId", },
166 { UIA_StylesFillPatternColorPropertyId, "UIA_StylesFillPatternColorPropertyId", },
167 { UIA_StylesExtendedPropertiesPropertyId, "UIA_StylesExtendedPropertiesPropertyId", },
168 { UIA_IsStylesPatternAvailablePropertyId, "UIA_IsStylesPatternAvailablePropertyId", },
169 { UIA_IsSpreadsheetPatternAvailablePropertyId, "UIA_IsSpreadsheetPatternAvailablePropertyId", },
170 { UIA_SpreadsheetItemFormulaPropertyId, "UIA_SpreadsheetItemFormulaPropertyId", },
171 { UIA_SpreadsheetItemAnnotationObjectsPropertyId, "UIA_SpreadsheetItemAnnotationObjectsPropertyId", },
172 { UIA_SpreadsheetItemAnnotationTypesPropertyId, "UIA_SpreadsheetItemAnnotationTypesPropertyId", },
173 { UIA_IsSpreadsheetItemPatternAvailablePropertyId, "UIA_IsSpreadsheetItemPatternAvailablePropertyId", },
174 { UIA_Transform2CanZoomPropertyId, "UIA_Transform2CanZoomPropertyId", },
175 { UIA_IsTransformPattern2AvailablePropertyId, "UIA_IsTransformPattern2AvailablePropertyId", },
176 { UIA_LiveSettingPropertyId, "UIA_LiveSettingPropertyId", },
177 { UIA_IsTextChildPatternAvailablePropertyId, "UIA_IsTextChildPatternAvailablePropertyId", },
178 { UIA_IsDragPatternAvailablePropertyId, "UIA_IsDragPatternAvailablePropertyId", },
179 { UIA_DragIsGrabbedPropertyId, "UIA_DragIsGrabbedPropertyId", },
180 { UIA_DragDropEffectPropertyId, "UIA_DragDropEffectPropertyId", },
181 { UIA_DragDropEffectsPropertyId, "UIA_DragDropEffectsPropertyId", },
182 { UIA_IsDropTargetPatternAvailablePropertyId, "UIA_IsDropTargetPatternAvailablePropertyId", },
183 { UIA_DropTargetDropTargetEffectPropertyId, "UIA_DropTargetDropTargetEffectPropertyId", },
184 { UIA_DropTargetDropTargetEffectsPropertyId, "UIA_DropTargetDropTargetEffectsPropertyId", },
185 { UIA_DragGrabbedItemsPropertyId, "UIA_DragGrabbedItemsPropertyId", },
186 { UIA_Transform2ZoomLevelPropertyId, "UIA_Transform2ZoomLevelPropertyId", },
187 { UIA_Transform2ZoomMinimumPropertyId, "UIA_Transform2ZoomMinimumPropertyId", },
188 { UIA_Transform2ZoomMaximumPropertyId, "UIA_Transform2ZoomMaximumPropertyId", },
189 { UIA_FlowsFromPropertyId, "UIA_FlowsFromPropertyId", },
190 { UIA_IsTextEditPatternAvailablePropertyId, "UIA_IsTextEditPatternAvailablePropertyId", },
191 { UIA_IsPeripheralPropertyId, "UIA_IsPeripheralPropertyId", },
192 { UIA_IsCustomNavigationPatternAvailablePropertyId, "UIA_IsCustomNavigationPatternAvailablePropertyId", },
193 { UIA_PositionInSetPropertyId, "UIA_PositionInSetPropertyId", },
194 { UIA_SizeOfSetPropertyId, "UIA_SizeOfSetPropertyId", },
195 { UIA_LevelPropertyId, "UIA_LevelPropertyId", },
196 { UIA_AnnotationTypesPropertyId, "UIA_AnnotationTypesPropertyId", },
197 { UIA_AnnotationObjectsPropertyId, "UIA_AnnotationObjectsPropertyId", },
198 { UIA_LandmarkTypePropertyId, "UIA_LandmarkTypePropertyId", },
199 { UIA_LocalizedLandmarkTypePropertyId, "UIA_LocalizedLandmarkTypePropertyId", },
200 { UIA_FullDescriptionPropertyId, "UIA_FullDescriptionPropertyId", },
201 { UIA_FillColorPropertyId, "UIA_FillColorPropertyId", },
202 { UIA_OutlineColorPropertyId, "UIA_OutlineColorPropertyId", },
203 { UIA_FillTypePropertyId, "UIA_FillTypePropertyId", },
204 { UIA_VisualEffectsPropertyId, "UIA_VisualEffectsPropertyId", },
205 { UIA_OutlineThicknessPropertyId, "UIA_OutlineThicknessPropertyId", },
206 { UIA_CenterPointPropertyId, "UIA_CenterPointPropertyId", },
207 { UIA_RotationPropertyId, "UIA_RotationPropertyId", },
208 { UIA_SizePropertyId, "UIA_SizePropertyId", },
209 { UIA_IsSelectionPattern2AvailablePropertyId, "UIA_IsSelectionPattern2AvailablePropertyId", },
210 { UIA_Selection2FirstSelectedItemPropertyId, "UIA_Selection2FirstSelectedItemPropertyId", },
211 { UIA_Selection2LastSelectedItemPropertyId, "UIA_Selection2LastSelectedItemPropertyId", },
212 { UIA_Selection2CurrentSelectedItemPropertyId, "UIA_Selection2CurrentSelectedItemPropertyId", },
213 { UIA_Selection2ItemCountPropertyId, "UIA_Selection2ItemCountPropertyId", },
214 { UIA_HeadingLevelPropertyId, "UIA_HeadingLevelPropertyId", },
215 { UIA_IsDialogPropertyId, "UIA_IsDialogPropertyId", },
218 static const struct str_id_pair uia_pattern_id_strs[] = {
219 { UIA_InvokePatternId, "UIA_InvokePatternId", },
220 { UIA_SelectionPatternId, "UIA_SelectionPatternId", },
221 { UIA_ValuePatternId, "UIA_ValuePatternId", },
222 { UIA_RangeValuePatternId, "UIA_RangeValuePatternId", },
223 { UIA_ScrollPatternId, "UIA_ScrollPatternId", },
224 { UIA_ExpandCollapsePatternId, "UIA_ExpandCollapsePatternId", },
225 { UIA_GridPatternId, "UIA_GridPatternId", },
226 { UIA_GridItemPatternId, "UIA_GridItemPatternId", },
227 { UIA_MultipleViewPatternId, "UIA_MultipleViewPatternId", },
228 { UIA_WindowPatternId, "UIA_WindowPatternId", },
229 { UIA_SelectionItemPatternId, "UIA_SelectionItemPatternId", },
230 { UIA_DockPatternId, "UIA_DockPatternId", },
231 { UIA_TablePatternId, "UIA_TablePatternId", },
232 { UIA_TableItemPatternId, "UIA_TableItemPatternId", },
233 { UIA_TextPatternId, "UIA_TextPatternId", },
234 { UIA_TogglePatternId, "UIA_TogglePatternId", },
235 { UIA_TransformPatternId, "UIA_TransformPatternId", },
236 { UIA_ScrollItemPatternId, "UIA_ScrollItemPatternId", },
237 { UIA_LegacyIAccessiblePatternId, "UIA_LegacyIAccessiblePatternId", },
238 { UIA_ItemContainerPatternId, "UIA_ItemContainerPatternId", },
239 { UIA_VirtualizedItemPatternId, "UIA_VirtualizedItemPatternId", },
240 { UIA_SynchronizedInputPatternId, "UIA_SynchronizedInputPatternId", },
241 { UIA_ObjectModelPatternId, "UIA_ObjectModelPatternId", },
242 { UIA_AnnotationPatternId, "UIA_AnnotationPatternId", },
243 { UIA_TextPattern2Id, "UIA_TextPattern2Id", },
244 { UIA_StylesPatternId, "UIA_StylesPatternId", },
245 { UIA_SpreadsheetPatternId, "UIA_SpreadsheetPatternId", },
246 { UIA_SpreadsheetItemPatternId, "UIA_SpreadsheetItemPatternId", },
247 { UIA_TransformPattern2Id, "UIA_TransformPattern2Id", },
248 { UIA_TextChildPatternId, "UIA_TextChildPatternId", },
249 { UIA_DragPatternId, "UIA_DragPatternId", },
250 { UIA_DropTargetPatternId, "UIA_DropTargetPatternId", },
251 { UIA_TextEditPatternId, "UIA_TextEditPatternId", },
252 { UIA_CustomNavigationPatternId, "UIA_CustomNavigationPatternId", },
255 static const struct str_id_pair uia_nav_dir_strs[] = {
256 { NavigateDirection_Parent, "NavigateDirection_Parent" },
257 { NavigateDirection_NextSibling, "NavigateDirection_NextSibling" },
258 { NavigateDirection_PreviousSibling, "NavigateDirection_PreviousSibling" },
259 { NavigateDirection_FirstChild, "NavigateDirection_FirstChild" },
260 { NavigateDirection_LastChild, "NavigateDirection_LastChild" },
263 static const struct str_id_pair uia_event_id_strs[] = {
264 { UIA_ToolTipOpenedEventId, "UIA_ToolTipOpenedEventId" },
265 { UIA_ToolTipClosedEventId, "UIA_ToolTipClosedEventId", },
266 { UIA_StructureChangedEventId, "UIA_StructureChangedEventId", },
267 { UIA_MenuOpenedEventId, "UIA_MenuOpenedEventId", },
268 { UIA_AutomationPropertyChangedEventId, "UIA_AutomationPropertyChangedEventId", },
269 { UIA_AutomationFocusChangedEventId, "UIA_AutomationFocusChangedEventId", },
270 { UIA_AsyncContentLoadedEventId, "UIA_AsyncContentLoadedEventId", },
271 { UIA_MenuClosedEventId, "UIA_MenuClosedEventId", },
272 { UIA_LayoutInvalidatedEventId, "UIA_LayoutInvalidatedEventId", },
273 { UIA_Invoke_InvokedEventId, "UIA_Invoke_InvokedEventId", },
274 { UIA_SelectionItem_ElementAddedToSelectionEventId, "UIA_SelectionItem_ElementAddedToSelectionEventId", },
275 { UIA_SelectionItem_ElementRemovedFromSelectionEventId, "UIA_SelectionItem_ElementRemovedFromSelectionEventId", },
276 { UIA_SelectionItem_ElementSelectedEventId, "UIA_SelectionItem_ElementSelectedEventId", },
277 { UIA_Selection_InvalidatedEventId, "UIA_Selection_InvalidatedEventId", },
278 { UIA_Text_TextSelectionChangedEventId, "UIA_Text_TextSelectionChangedEventId", },
279 { UIA_Text_TextChangedEventId, "UIA_Text_TextChangedEventId", },
280 { UIA_Window_WindowOpenedEventId, "UIA_Window_WindowOpenedEventId", },
281 { UIA_Window_WindowClosedEventId, "UIA_Window_WindowClosedEventId", },
282 { UIA_MenuModeStartEventId, "UIA_MenuModeStartEventId", },
283 { UIA_MenuModeEndEventId, "UIA_MenuModeEndEventId", },
284 { UIA_InputReachedTargetEventId, "UIA_InputReachedTargetEventId", },
285 { UIA_InputReachedOtherElementEventId, "UIA_InputReachedOtherElementEventId", },
286 { UIA_InputDiscardedEventId, "UIA_InputDiscardedEventId", },
287 { UIA_SystemAlertEventId, "UIA_SystemAlertEventId", },
288 { UIA_LiveRegionChangedEventId, "UIA_LiveRegionChangedEventId", },
289 { UIA_HostedFragmentRootsInvalidatedEventId, "UIA_HostedFragmentRootsInvalidatedEventId", },
290 { UIA_Drag_DragStartEventId, "UIA_Drag_DragStartEventId", },
291 { UIA_Drag_DragCancelEventId, "UIA_Drag_DragCancelEventId", },
292 { UIA_Drag_DragCompleteEventId, "UIA_Drag_DragCompleteEventId", },
293 { UIA_DropTarget_DragEnterEventId, "UIA_DropTarget_DragEnterEventId", },
294 { UIA_DropTarget_DragLeaveEventId, "UIA_DropTarget_DragLeaveEventId", },
295 { UIA_DropTarget_DroppedEventId, "UIA_DropTarget_DroppedEventId", },
296 { UIA_TextEdit_TextChangedEventId, "UIA_TextEdit_TextChangedEventId", },
297 { UIA_TextEdit_ConversionTargetChangedEventId, "UIA_TextEdit_ConversionTargetChangedEventId", },
298 { UIA_ChangesEventId, "UIA_ChangesEventId", },
299 { UIA_NotificationEventId, "UIA_NotificationEventId", },
302 static int __cdecl str_id_pair_compare(const void *a, const void *b)
304 const int *id = a;
305 const struct str_id_pair *pair = b;
307 return ((*id) > pair->id) - ((*id) < pair->id);
310 #define get_str_for_id(id, id_pair) \
311 get_str_from_id_pair( (id), (id_pair), (ARRAY_SIZE(id_pair)) )
312 static const char *get_str_from_id_pair(int id, const struct str_id_pair *id_pair, int id_pair_size)
314 const struct str_id_pair *pair;
316 if (!(pair = bsearch(&id, id_pair, id_pair_size, sizeof(*pair), str_id_pair_compare)))
317 return "";
318 else
319 return pair->str;
323 #define PROV_METHOD_TRACE(prov, method) \
324 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method "\n", GetCurrentProcessId(), GetCurrentThreadId(), (prov)->prov_name);
326 #define PROV_METHOD_TRACE2(prov, method, arg, str_table) \
327 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method ": %d (%s)\n", GetCurrentProcessId(), GetCurrentThreadId(), (prov)->prov_name, \
328 arg, get_str_for_id(arg, str_table)); \
330 #define ACC_METHOD_TRACE(acc, method) \
331 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method "\n", GetCurrentProcessId(), GetCurrentThreadId(), (acc)->interface_name);
333 #define ACC_METHOD_TRACE2(acc, cid, method) \
334 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method ": %s\n", GetCurrentProcessId(), GetCurrentThreadId(), \
335 (acc)->interface_name, debugstr_variant((cid)));
337 #define DEFINE_EXPECT(func) \
338 static int expect_ ## func = 0, called_ ## func = 0
340 #define SET_EXPECT(func) \
341 do { called_ ## func = 0; expect_ ## func = 1; } while(0)
343 #define SET_EXPECT_MULTI(func, num) \
344 do { called_ ## func = 0; expect_ ## func = num; } while(0)
346 #define CHECK_EXPECT2(func) \
347 do { \
348 ok(expect_ ##func, "unexpected call " #func "\n"); \
349 called_ ## func++; \
350 }while(0)
352 #define CHECK_EXPECT(func) \
353 do { \
354 CHECK_EXPECT2(func); \
355 expect_ ## func--; \
356 }while(0)
358 #define CALLED_COUNT(func) \
359 called_ ## func
361 #define CHECK_CALLED(func) \
362 do { \
363 ok(called_ ## func, "expected " #func "\n"); \
364 expect_ ## func = called_ ## func = 0; \
365 }while(0)
367 #define CHECK_CALLED_MULTI(func, num) \
368 do { \
369 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
370 expect_ ## func = called_ ## func = 0; \
371 }while(0)
373 #define CHECK_CALLED_AT_LEAST(func, num) \
374 do { \
375 ok(called_ ## func >= num, "expected " #func " at least %d time(s) (got %d)\n", num, called_ ## func); \
376 expect_ ## func = called_ ## func = 0; \
377 }while(0)
379 #define CHECK_CALLED_AT_MOST(func, num) \
380 do { \
381 ok(called_ ## func <= num, "expected " #func " at most %d time(s) (got %d)\n", num, called_ ## func); \
382 expect_ ## func = called_ ## func = 0; \
383 }while(0)
385 #define NAVDIR_INTERNAL_HWND 10
386 #define UIA_RUNTIME_ID_PREFIX 42
388 DEFINE_EXPECT(winproc_GETOBJECT_CLIENT);
389 DEFINE_EXPECT(prov_callback_base_hwnd);
390 DEFINE_EXPECT(prov_callback_nonclient);
391 DEFINE_EXPECT(prov_callback_proxy);
392 DEFINE_EXPECT(prov_callback_parent_proxy);
393 DEFINE_EXPECT(uia_event_callback);
394 DEFINE_EXPECT(uia_com_event_callback);
395 DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot);
396 DEFINE_EXPECT(child_winproc_GETOBJECT_UiaRoot);
398 static BOOL check_variant_i4(VARIANT *v, int val)
400 if (V_VT(v) == VT_I4 && V_I4(v) == val)
401 return TRUE;
403 return FALSE;
406 static BOOL check_variant_bool(VARIANT *v, BOOL val)
408 if (V_VT(v) == VT_BOOL && V_BOOL(v) == (val ? VARIANT_TRUE : VARIANT_FALSE))
409 return TRUE;
411 return FALSE;
414 static void variant_init_bool(VARIANT *v, BOOL val)
416 V_VT(v) = VT_BOOL;
417 V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE;
420 static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
422 IUnknown *unk1, *unk2;
423 BOOL cmp;
425 IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
426 IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
427 cmp = unk1 == unk2;
429 IUnknown_Release(unk1);
430 IUnknown_Release(unk2);
431 return cmp;
434 #define test_implements_interface( unk, iid, exp_implemented ) \
435 test_implements_interface_( ((IUnknown *)(unk)), (iid), (exp_implemented), __FILE__, __LINE__)
436 static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_implemented, const char *file, int line)
438 IUnknown *unk2 = NULL;
439 HRESULT hr;
441 hr = IUnknown_QueryInterface(unk, iid, (void **)&unk2);
442 ok_(file, line)(hr == (exp_implemented ? S_OK : E_NOINTERFACE), "Unexpected hr %#lx\n", hr);
443 ok_(file, line)(!!unk2 == exp_implemented, "Unexpected iface %p\n", unk2);
444 if (unk2)
445 IUnknown_Release(unk2);
448 #define DEFINE_ACC_METHOD_EXPECT(method) \
449 int expect_ ## method , called_ ## method
451 #define DEFINE_ACC_METHOD_EXPECTS \
452 DEFINE_ACC_METHOD_EXPECT(QI_IAccIdentity); \
453 DEFINE_ACC_METHOD_EXPECT(get_accParent); \
454 DEFINE_ACC_METHOD_EXPECT(get_accChildCount); \
455 DEFINE_ACC_METHOD_EXPECT(get_accChild); \
456 DEFINE_ACC_METHOD_EXPECT(get_accName); \
457 DEFINE_ACC_METHOD_EXPECT(get_accValue); \
458 DEFINE_ACC_METHOD_EXPECT(get_accDescription); \
459 DEFINE_ACC_METHOD_EXPECT(get_accRole); \
460 DEFINE_ACC_METHOD_EXPECT(get_accState); \
461 DEFINE_ACC_METHOD_EXPECT(get_accHelp); \
462 DEFINE_ACC_METHOD_EXPECT(get_accHelpTopic); \
463 DEFINE_ACC_METHOD_EXPECT(get_accKeyboardShortcut); \
464 DEFINE_ACC_METHOD_EXPECT(get_accFocus); \
465 DEFINE_ACC_METHOD_EXPECT(get_accSelection); \
466 DEFINE_ACC_METHOD_EXPECT(get_accDefaultAction); \
467 DEFINE_ACC_METHOD_EXPECT(accSelect); \
468 DEFINE_ACC_METHOD_EXPECT(accLocation); \
469 DEFINE_ACC_METHOD_EXPECT(accNavigate); \
470 DEFINE_ACC_METHOD_EXPECT(accHitTest); \
471 DEFINE_ACC_METHOD_EXPECT(accDoDefaultAction); \
472 DEFINE_ACC_METHOD_EXPECT(put_accName); \
473 DEFINE_ACC_METHOD_EXPECT(put_accValue); \
474 DEFINE_ACC_METHOD_EXPECT(get_nRelations); \
475 DEFINE_ACC_METHOD_EXPECT(get_relation); \
476 DEFINE_ACC_METHOD_EXPECT(get_relations); \
477 DEFINE_ACC_METHOD_EXPECT(role); \
478 DEFINE_ACC_METHOD_EXPECT(scrollTo); \
479 DEFINE_ACC_METHOD_EXPECT(scrollToPoint); \
480 DEFINE_ACC_METHOD_EXPECT(get_groupPosition); \
481 DEFINE_ACC_METHOD_EXPECT(get_states); \
482 DEFINE_ACC_METHOD_EXPECT(get_extendedRole); \
483 DEFINE_ACC_METHOD_EXPECT(get_localizedExtendedRole); \
484 DEFINE_ACC_METHOD_EXPECT(get_nExtendedStates); \
485 DEFINE_ACC_METHOD_EXPECT(get_extendedStates); \
486 DEFINE_ACC_METHOD_EXPECT(get_localizedExtendedStates); \
487 DEFINE_ACC_METHOD_EXPECT(get_uniqueID); \
488 DEFINE_ACC_METHOD_EXPECT(get_windowHandle); \
489 DEFINE_ACC_METHOD_EXPECT(get_indexInParent); \
490 DEFINE_ACC_METHOD_EXPECT(get_locale); \
491 DEFINE_ACC_METHOD_EXPECT(get_attributes) \
493 static struct Accessible
495 IAccessible IAccessible_iface;
496 IAccessible2 IAccessible2_iface;
497 IOleWindow IOleWindow_iface;
498 IServiceProvider IServiceProvider_iface;
499 LONG ref;
501 const char *interface_name;
503 IAccessible *parent;
504 HWND acc_hwnd;
505 HWND ow_hwnd;
506 INT role;
507 INT state;
508 LONG child_count;
509 LPCWSTR name;
510 LONG left, top, width, height;
511 BOOL enable_ia2;
512 LONG unique_id;
513 DEFINE_ACC_METHOD_EXPECTS;
514 } Accessible, Accessible2, Accessible_child, Accessible_child2;
516 #define SET_ACC_METHOD_EXPECT(acc, method) \
517 do { (acc)->called_ ## method = 0; (acc)->expect_ ## method = 1; } while(0)
519 #define SET_ACC_METHOD_EXPECT_MULTI(acc, method, num) \
520 do { (acc)->called_ ## method = 0; (acc)->expect_ ## method = num; } while(0)
522 #define CHECK_ACC_METHOD_EXPECT2(acc, method) \
523 do { \
524 ok((acc)->expect_ ##method, "unexpected call %s_" #method "\n", (acc)->interface_name); \
525 (acc)->called_ ## method++; \
526 }while(0)
528 #define CHECK_ACC_METHOD_EXPECT(acc, method) \
529 do { \
530 CHECK_ACC_METHOD_EXPECT2(acc, method); \
531 (acc)->expect_ ## method--; \
532 }while(0)
534 #define CHECK_ACC_METHOD_CALLED(acc, method) \
535 do { \
536 ok((acc)->called_ ## method, "expected %s_" #method "\n", (acc)->interface_name); \
537 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
538 }while(0)
540 #define CHECK_ACC_METHOD_CALLED_MULTI(acc, method, num) \
541 do { \
542 ok((acc)->called_ ## method == num, "expected %s_" #method " %d times (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
543 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
544 }while(0)
546 static inline struct Accessible* impl_from_Accessible(IAccessible *iface)
548 return CONTAINING_RECORD(iface, struct Accessible, IAccessible_iface);
551 static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID riid, void **obj)
553 struct Accessible *This = impl_from_Accessible(iface);
555 *obj = NULL;
556 if (IsEqualIID(riid, &IID_IAccIdentity))
558 CHECK_ACC_METHOD_EXPECT(This, QI_IAccIdentity);
559 ACC_METHOD_TRACE(This, QI_IAccIdentity);
560 return E_NOINTERFACE;
563 if (IsEqualIID(riid, &IID_IUnknown) || IsEqualIID(riid, &IID_IDispatch) ||
564 IsEqualIID(riid, &IID_IAccessible))
565 *obj = iface;
566 else if (IsEqualIID(riid, &IID_IOleWindow))
567 *obj = &This->IOleWindow_iface;
568 else if (IsEqualIID(riid, &IID_IServiceProvider))
569 *obj = &This->IServiceProvider_iface;
570 else if (IsEqualIID(riid, &IID_IAccessible2) && This->enable_ia2)
571 *obj = &This->IAccessible2_iface;
572 else
573 return E_NOINTERFACE;
575 IAccessible_AddRef(iface);
576 return S_OK;
579 static ULONG WINAPI Accessible_AddRef(IAccessible *iface)
581 struct Accessible *This = impl_from_Accessible(iface);
582 return InterlockedIncrement(&This->ref);
585 static ULONG WINAPI Accessible_Release(IAccessible *iface)
587 struct Accessible *This = impl_from_Accessible(iface);
588 return InterlockedDecrement(&This->ref);
591 static HRESULT WINAPI Accessible_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
593 ok(0, "unexpected call\n");
594 return E_NOTIMPL;
597 static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface, UINT iTInfo,
598 LCID lcid, ITypeInfo **out_tinfo)
600 ok(0, "unexpected call\n");
601 return E_NOTIMPL;
604 static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID riid,
605 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
607 ok(0, "unexpected call\n");
608 return E_NOTIMPL;
611 static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID disp_id_member,
612 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
613 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
615 ok(0, "unexpected call\n");
616 return E_NOTIMPL;
619 static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **out_parent)
621 struct Accessible *This = impl_from_Accessible(iface);
623 CHECK_ACC_METHOD_EXPECT(This, get_accParent);
624 ACC_METHOD_TRACE(This, get_accParent);
625 if (This->parent)
626 return IAccessible_QueryInterface(This->parent, &IID_IDispatch, (void **)out_parent);
628 *out_parent = NULL;
629 return S_FALSE;
632 static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out_count)
634 struct Accessible *This = impl_from_Accessible(iface);
636 CHECK_ACC_METHOD_EXPECT(This, get_accChildCount);
637 ACC_METHOD_TRACE(This, get_accChildCount);
638 if (This->child_count)
640 *out_count = This->child_count;
641 return S_OK;
644 return E_NOTIMPL;
647 static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_id,
648 IDispatch **out_child)
650 struct Accessible *This = impl_from_Accessible(iface);
652 CHECK_ACC_METHOD_EXPECT(This, get_accChild);
653 ACC_METHOD_TRACE2(This, &child_id, get_accChild);
655 *out_child = NULL;
656 if (V_VT(&child_id) != VT_I4)
657 return E_INVALIDARG;
659 if (This == &Accessible)
661 switch (V_I4(&child_id))
663 case CHILDID_SELF:
664 return IAccessible_QueryInterface(&This->IAccessible_iface, &IID_IDispatch, (void **)out_child);
666 /* Simple element children. */
667 case 1:
668 case 3:
669 return S_FALSE;
671 case 2:
672 return IAccessible_QueryInterface(&Accessible_child.IAccessible_iface, &IID_IDispatch, (void **)out_child);
674 case 4:
675 return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
677 default:
678 break;
682 return E_NOTIMPL;
685 static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_id,
686 BSTR *out_name)
688 struct Accessible *This = impl_from_Accessible(iface);
690 CHECK_ACC_METHOD_EXPECT(This, get_accName);
691 ACC_METHOD_TRACE2(This, &child_id, get_accName);
693 *out_name = NULL;
694 if (This->name)
696 *out_name = SysAllocString(This->name);
697 return S_OK;
700 return E_NOTIMPL;
703 static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface, VARIANT child_id,
704 BSTR *out_value)
706 struct Accessible *This = impl_from_Accessible(iface);
707 CHECK_ACC_METHOD_EXPECT(This, get_accValue);
708 ACC_METHOD_TRACE2(This, &child_id, get_accValue);
709 return E_NOTIMPL;
712 static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface, VARIANT child_id,
713 BSTR *out_description)
715 struct Accessible *This = impl_from_Accessible(iface);
716 CHECK_ACC_METHOD_EXPECT(This, get_accDescription);
717 ACC_METHOD_TRACE2(This, &child_id, get_accDescription);
718 return E_NOTIMPL;
721 static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_id,
722 VARIANT *out_role)
724 struct Accessible *This = impl_from_Accessible(iface);
726 CHECK_ACC_METHOD_EXPECT(This, get_accRole);
727 ACC_METHOD_TRACE2(This, &child_id, get_accRole);
729 if (This->role)
731 V_VT(out_role) = VT_I4;
732 V_I4(out_role) = This->role;
733 return S_OK;
736 return E_NOTIMPL;
739 static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_id,
740 VARIANT *out_state)
742 struct Accessible *This = impl_from_Accessible(iface);
744 CHECK_ACC_METHOD_EXPECT(This, get_accState);
745 ACC_METHOD_TRACE2(This, &child_id, get_accState);
747 if (V_VT(&child_id) != VT_I4)
748 return E_INVALIDARG;
750 if (This == &Accessible && V_I4(&child_id) != CHILDID_SELF)
752 switch (V_I4(&child_id))
754 case 1:
755 V_VT(out_state) = VT_I4;
756 V_I4(out_state) = STATE_SYSTEM_INVISIBLE;
757 break;
759 case 3:
760 V_VT(out_state) = VT_I4;
761 V_I4(out_state) = STATE_SYSTEM_FOCUSABLE;
762 break;
764 default:
765 return E_INVALIDARG;
768 return S_OK;
771 if (This->state)
773 V_VT(out_state) = VT_I4;
774 V_I4(out_state) = This->state;
775 return S_OK;
778 return E_NOTIMPL;
781 static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface, VARIANT child_id,
782 BSTR *out_help)
784 struct Accessible *This = impl_from_Accessible(iface);
785 CHECK_ACC_METHOD_EXPECT(This, get_accHelp);
786 ACC_METHOD_TRACE2(This, &child_id, get_accHelp);
787 return E_NOTIMPL;
790 static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface,
791 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
793 struct Accessible *This = impl_from_Accessible(iface);
794 CHECK_ACC_METHOD_EXPECT(This, get_accHelpTopic);
795 ACC_METHOD_TRACE2(This, &child_id, get_accHelpTopic);
796 return E_NOTIMPL;
799 static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VARIANT child_id,
800 BSTR *out_kbd_shortcut)
802 struct Accessible *This = impl_from_Accessible(iface);
803 CHECK_ACC_METHOD_EXPECT(This, get_accKeyboardShortcut);
804 ACC_METHOD_TRACE2(This, &child_id, get_accKeyboardShortcut);
805 return E_NOTIMPL;
808 static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pchild_id)
810 struct Accessible *This = impl_from_Accessible(iface);
811 CHECK_ACC_METHOD_EXPECT(This, get_accFocus);
812 ACC_METHOD_TRACE(This, get_accFocus);
813 return E_NOTIMPL;
816 static HRESULT WINAPI Accessible_get_accSelection(IAccessible *iface, VARIANT *out_selection)
818 struct Accessible *This = impl_from_Accessible(iface);
819 CHECK_ACC_METHOD_EXPECT(This, get_accSelection);
820 ACC_METHOD_TRACE(This, get_accSelection);
821 return E_NOTIMPL;
824 static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface, VARIANT child_id,
825 BSTR *out_default_action)
827 struct Accessible *This = impl_from_Accessible(iface);
828 CHECK_ACC_METHOD_EXPECT(This, get_accDefaultAction);
829 ACC_METHOD_TRACE2(This, &child_id, get_accDefaultAction);
830 return E_NOTIMPL;
833 static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, LONG select_flags,
834 VARIANT child_id)
836 struct Accessible *This = impl_from_Accessible(iface);
837 CHECK_ACC_METHOD_EXPECT(This, accSelect);
838 ACC_METHOD_TRACE2(This, &child_id, accSelect);
839 return E_NOTIMPL;
842 static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *out_left,
843 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
845 struct Accessible *This = impl_from_Accessible(iface);
847 CHECK_ACC_METHOD_EXPECT(This, accLocation);
848 ACC_METHOD_TRACE2(This, &child_id, accLocation);
850 if (This->width && This->height)
852 *out_left = This->left;
853 *out_top = This->top;
854 *out_width = This->width;
855 *out_height = This->height;
856 return S_OK;
859 return E_NOTIMPL;
862 static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface, LONG nav_direction,
863 VARIANT child_id_start, VARIANT *out_var)
865 struct Accessible *This = impl_from_Accessible(iface);
867 CHECK_ACC_METHOD_EXPECT(This, accNavigate);
868 ACC_METHOD_TRACE2(This, &child_id_start, accNavigate);
870 VariantInit(out_var);
873 * This is an undocumented way for UI Automation to get an HWND for
874 * IAccessible's contained in a Direct Annotation wrapper object.
876 if ((nav_direction == NAVDIR_INTERNAL_HWND) && check_variant_i4(&child_id_start, CHILDID_SELF) &&
877 This->acc_hwnd)
879 V_VT(out_var) = VT_I4;
880 V_I4(out_var) = HandleToUlong(This->acc_hwnd);
881 return S_OK;
883 return S_FALSE;
886 static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface, LONG left, LONG top,
887 VARIANT *out_child_id)
889 struct Accessible *This = impl_from_Accessible(iface);
890 CHECK_ACC_METHOD_EXPECT(This, accHitTest);
891 ACC_METHOD_TRACE(This, accHitTest);
892 return E_NOTIMPL;
895 static HRESULT WINAPI Accessible_accDoDefaultAction(IAccessible *iface, VARIANT child_id)
897 struct Accessible *This = impl_from_Accessible(iface);
898 CHECK_ACC_METHOD_EXPECT(This, accDoDefaultAction);
899 ACC_METHOD_TRACE2(This, &child_id, accDoDefaultAction);
900 return E_NOTIMPL;
903 static HRESULT WINAPI Accessible_put_accName(IAccessible *iface, VARIANT child_id,
904 BSTR name)
906 struct Accessible *This = impl_from_Accessible(iface);
907 CHECK_ACC_METHOD_EXPECT(This, put_accName);
908 ACC_METHOD_TRACE2(This, &child_id, put_accName);
909 return E_NOTIMPL;
912 static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface, VARIANT child_id,
913 BSTR value)
915 struct Accessible *This = impl_from_Accessible(iface);
916 CHECK_ACC_METHOD_EXPECT(This, put_accValue);
917 ACC_METHOD_TRACE2(This, &child_id, put_accValue);
918 return E_NOTIMPL;
921 static IAccessibleVtbl AccessibleVtbl = {
922 Accessible_QueryInterface,
923 Accessible_AddRef,
924 Accessible_Release,
925 Accessible_GetTypeInfoCount,
926 Accessible_GetTypeInfo,
927 Accessible_GetIDsOfNames,
928 Accessible_Invoke,
929 Accessible_get_accParent,
930 Accessible_get_accChildCount,
931 Accessible_get_accChild,
932 Accessible_get_accName,
933 Accessible_get_accValue,
934 Accessible_get_accDescription,
935 Accessible_get_accRole,
936 Accessible_get_accState,
937 Accessible_get_accHelp,
938 Accessible_get_accHelpTopic,
939 Accessible_get_accKeyboardShortcut,
940 Accessible_get_accFocus,
941 Accessible_get_accSelection,
942 Accessible_get_accDefaultAction,
943 Accessible_accSelect,
944 Accessible_accLocation,
945 Accessible_accNavigate,
946 Accessible_accHitTest,
947 Accessible_accDoDefaultAction,
948 Accessible_put_accName,
949 Accessible_put_accValue
952 static inline struct Accessible* impl_from_Accessible2(IAccessible2 *iface)
954 return CONTAINING_RECORD(iface, struct Accessible, IAccessible2_iface);
957 static HRESULT WINAPI Accessible2_QueryInterface(IAccessible2 *iface, REFIID riid, void **obj)
959 struct Accessible *This = impl_from_Accessible2(iface);
960 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
963 static ULONG WINAPI Accessible2_AddRef(IAccessible2 *iface)
965 struct Accessible *This = impl_from_Accessible2(iface);
966 return IAccessible_AddRef(&This->IAccessible_iface);
969 static ULONG WINAPI Accessible2_Release(IAccessible2 *iface)
971 struct Accessible *This = impl_from_Accessible2(iface);
972 return IAccessible_Release(&This->IAccessible_iface);
975 static HRESULT WINAPI Accessible2_GetTypeInfoCount(IAccessible2 *iface, UINT *pctinfo)
977 struct Accessible *This = impl_from_Accessible2(iface);
978 return IAccessible_GetTypeInfoCount(&This->IAccessible_iface, pctinfo);
981 static HRESULT WINAPI Accessible2_GetTypeInfo(IAccessible2 *iface, UINT iTInfo,
982 LCID lcid, ITypeInfo **out_tinfo)
984 struct Accessible *This = impl_from_Accessible2(iface);
985 return IAccessible_GetTypeInfo(&This->IAccessible_iface, iTInfo, lcid, out_tinfo);
988 static HRESULT WINAPI Accessible2_GetIDsOfNames(IAccessible2 *iface, REFIID riid,
989 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
991 struct Accessible *This = impl_from_Accessible2(iface);
992 return IAccessible_GetIDsOfNames(&This->IAccessible_iface, riid, rg_names, name_count,
993 lcid, rg_disp_id);
996 static HRESULT WINAPI Accessible2_Invoke(IAccessible2 *iface, DISPID disp_id_member,
997 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
998 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
1000 struct Accessible *This = impl_from_Accessible2(iface);
1001 return IAccessible_Invoke(&This->IAccessible_iface, disp_id_member, riid, lcid, flags,
1002 disp_params, var_result, excep_info, arg_err);
1005 static HRESULT WINAPI Accessible2_get_accParent(IAccessible2 *iface, IDispatch **out_parent)
1007 struct Accessible *This = impl_from_Accessible2(iface);
1008 return IAccessible_get_accParent(&This->IAccessible_iface, out_parent);
1011 static HRESULT WINAPI Accessible2_get_accChildCount(IAccessible2 *iface, LONG *out_count)
1013 struct Accessible *This = impl_from_Accessible2(iface);
1014 return IAccessible_get_accChildCount(&This->IAccessible_iface, out_count);
1017 static HRESULT WINAPI Accessible2_get_accChild(IAccessible2 *iface, VARIANT child_id,
1018 IDispatch **out_child)
1020 struct Accessible *This = impl_from_Accessible2(iface);
1021 return IAccessible_get_accChild(&This->IAccessible_iface, child_id, out_child);
1024 static HRESULT WINAPI Accessible2_get_accName(IAccessible2 *iface, VARIANT child_id,
1025 BSTR *out_name)
1027 struct Accessible *This = impl_from_Accessible2(iface);
1028 return IAccessible_get_accName(&This->IAccessible_iface, child_id, out_name);
1031 static HRESULT WINAPI Accessible2_get_accValue(IAccessible2 *iface, VARIANT child_id,
1032 BSTR *out_value)
1034 struct Accessible *This = impl_from_Accessible2(iface);
1035 return IAccessible_get_accValue(&This->IAccessible_iface, child_id, out_value);
1038 static HRESULT WINAPI Accessible2_get_accDescription(IAccessible2 *iface, VARIANT child_id,
1039 BSTR *out_description)
1041 struct Accessible *This = impl_from_Accessible2(iface);
1042 return IAccessible_get_accDescription(&This->IAccessible_iface, child_id, out_description);
1045 static HRESULT WINAPI Accessible2_get_accRole(IAccessible2 *iface, VARIANT child_id,
1046 VARIANT *out_role)
1048 struct Accessible *This = impl_from_Accessible2(iface);
1049 return IAccessible_get_accRole(&This->IAccessible_iface, child_id, out_role);
1052 static HRESULT WINAPI Accessible2_get_accState(IAccessible2 *iface, VARIANT child_id,
1053 VARIANT *out_state)
1055 struct Accessible *This = impl_from_Accessible2(iface);
1056 return IAccessible_get_accState(&This->IAccessible_iface, child_id, out_state);
1059 static HRESULT WINAPI Accessible2_get_accHelp(IAccessible2 *iface, VARIANT child_id,
1060 BSTR *out_help)
1062 struct Accessible *This = impl_from_Accessible2(iface);
1063 return IAccessible_get_accHelp(&This->IAccessible_iface, child_id, out_help);
1066 static HRESULT WINAPI Accessible2_get_accHelpTopic(IAccessible2 *iface,
1067 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
1069 struct Accessible *This = impl_from_Accessible2(iface);
1070 return IAccessible_get_accHelpTopic(&This->IAccessible_iface, out_help_file, child_id,
1071 out_topic_id);
1074 static HRESULT WINAPI Accessible2_get_accKeyboardShortcut(IAccessible2 *iface, VARIANT child_id,
1075 BSTR *out_kbd_shortcut)
1077 struct Accessible *This = impl_from_Accessible2(iface);
1078 return IAccessible_get_accKeyboardShortcut(&This->IAccessible_iface, child_id,
1079 out_kbd_shortcut);
1082 static HRESULT WINAPI Accessible2_get_accFocus(IAccessible2 *iface, VARIANT *pchild_id)
1084 struct Accessible *This = impl_from_Accessible2(iface);
1085 return IAccessible_get_accFocus(&This->IAccessible_iface, pchild_id);
1088 static HRESULT WINAPI Accessible2_get_accSelection(IAccessible2 *iface, VARIANT *out_selection)
1090 struct Accessible *This = impl_from_Accessible2(iface);
1091 return IAccessible_get_accSelection(&This->IAccessible_iface, out_selection);
1094 static HRESULT WINAPI Accessible2_get_accDefaultAction(IAccessible2 *iface, VARIANT child_id,
1095 BSTR *out_default_action)
1097 struct Accessible *This = impl_from_Accessible2(iface);
1098 return IAccessible_get_accDefaultAction(&This->IAccessible_iface, child_id,
1099 out_default_action);
1102 static HRESULT WINAPI Accessible2_accSelect(IAccessible2 *iface, LONG select_flags,
1103 VARIANT child_id)
1105 struct Accessible *This = impl_from_Accessible2(iface);
1106 return IAccessible_accSelect(&This->IAccessible_iface, select_flags, child_id);
1109 static HRESULT WINAPI Accessible2_accLocation(IAccessible2 *iface, LONG *out_left,
1110 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
1112 struct Accessible *This = impl_from_Accessible2(iface);
1113 return IAccessible_accLocation(&This->IAccessible_iface, out_left, out_top, out_width,
1114 out_height, child_id);
1117 static HRESULT WINAPI Accessible2_accNavigate(IAccessible2 *iface, LONG nav_direction,
1118 VARIANT child_id_start, VARIANT *out_var)
1120 struct Accessible *This = impl_from_Accessible2(iface);
1121 return IAccessible_accNavigate(&This->IAccessible_iface, nav_direction, child_id_start,
1122 out_var);
1125 static HRESULT WINAPI Accessible2_accHitTest(IAccessible2 *iface, LONG left, LONG top,
1126 VARIANT *out_child_id)
1128 struct Accessible *This = impl_from_Accessible2(iface);
1129 return IAccessible_accHitTest(&This->IAccessible_iface, left, top, out_child_id);
1132 static HRESULT WINAPI Accessible2_accDoDefaultAction(IAccessible2 *iface, VARIANT child_id)
1134 struct Accessible *This = impl_from_Accessible2(iface);
1135 return IAccessible_accDoDefaultAction(&This->IAccessible_iface, child_id);
1138 static HRESULT WINAPI Accessible2_put_accName(IAccessible2 *iface, VARIANT child_id,
1139 BSTR name)
1141 struct Accessible *This = impl_from_Accessible2(iface);
1142 return IAccessible_put_accName(&This->IAccessible_iface, child_id, name);
1145 static HRESULT WINAPI Accessible2_put_accValue(IAccessible2 *iface, VARIANT child_id,
1146 BSTR value)
1148 struct Accessible *This = impl_from_Accessible2(iface);
1149 return IAccessible_put_accValue(&This->IAccessible_iface, child_id, value);
1152 static HRESULT WINAPI Accessible2_get_nRelations(IAccessible2 *iface, LONG *out_nRelations)
1154 struct Accessible *This = impl_from_Accessible2(iface);
1155 CHECK_ACC_METHOD_EXPECT(This, get_nRelations);
1156 ACC_METHOD_TRACE(This, get_nRelations);
1157 return E_NOTIMPL;
1160 static HRESULT WINAPI Accessible2_get_relation(IAccessible2 *iface, LONG relation_idx,
1161 IAccessibleRelation **out_relation)
1163 struct Accessible *This = impl_from_Accessible2(iface);
1164 CHECK_ACC_METHOD_EXPECT(This, get_relation);
1165 ACC_METHOD_TRACE(This, get_relation);
1166 return E_NOTIMPL;
1169 static HRESULT WINAPI Accessible2_get_relations(IAccessible2 *iface, LONG count,
1170 IAccessibleRelation **out_relations, LONG *out_relation_count)
1172 struct Accessible *This = impl_from_Accessible2(iface);
1173 CHECK_ACC_METHOD_EXPECT(This, get_relations);
1174 ACC_METHOD_TRACE(This, get_relations);
1175 return E_NOTIMPL;
1178 static HRESULT WINAPI Accessible2_role(IAccessible2 *iface, LONG *out_role)
1180 struct Accessible *This = impl_from_Accessible2(iface);
1181 CHECK_ACC_METHOD_EXPECT(This, role);
1182 ACC_METHOD_TRACE(This, role);
1183 return E_NOTIMPL;
1186 static HRESULT WINAPI Accessible2_scrollTo(IAccessible2 *iface, enum IA2ScrollType scroll_type)
1188 struct Accessible *This = impl_from_Accessible2(iface);
1189 CHECK_ACC_METHOD_EXPECT(This, scrollTo);
1190 ACC_METHOD_TRACE(This, scrollTo);
1191 return E_NOTIMPL;
1194 static HRESULT WINAPI Accessible2_scrollToPoint(IAccessible2 *iface,
1195 enum IA2CoordinateType coordinate_type, LONG x, LONG y)
1197 struct Accessible *This = impl_from_Accessible2(iface);
1198 CHECK_ACC_METHOD_EXPECT(This, scrollToPoint);
1199 ACC_METHOD_TRACE(This, scrollToPoint);
1200 return E_NOTIMPL;
1203 static HRESULT WINAPI Accessible2_get_groupPosition(IAccessible2 *iface, LONG *out_group_level,
1204 LONG *out_similar_items_in_group, LONG *out_position_in_group)
1206 struct Accessible *This = impl_from_Accessible2(iface);
1207 CHECK_ACC_METHOD_EXPECT(This, get_groupPosition);
1208 ACC_METHOD_TRACE(This, get_groupPosition);
1209 return E_NOTIMPL;
1212 static HRESULT WINAPI Accessible2_get_states(IAccessible2 *iface, AccessibleStates *out_states)
1214 struct Accessible *This = impl_from_Accessible2(iface);
1215 CHECK_ACC_METHOD_EXPECT(This, get_states);
1216 ACC_METHOD_TRACE(This, get_states);
1217 return E_NOTIMPL;
1220 static HRESULT WINAPI Accessible2_get_extendedRole(IAccessible2 *iface, BSTR *out_extended_role)
1222 struct Accessible *This = impl_from_Accessible2(iface);
1223 CHECK_ACC_METHOD_EXPECT(This, get_extendedRole);
1224 ACC_METHOD_TRACE(This, get_extendedRole);
1225 return E_NOTIMPL;
1228 static HRESULT WINAPI Accessible2_get_localizedExtendedRole(IAccessible2 *iface,
1229 BSTR *out_localized_extended_role)
1231 struct Accessible *This = impl_from_Accessible2(iface);
1232 CHECK_ACC_METHOD_EXPECT(This, get_localizedExtendedRole);
1233 ACC_METHOD_TRACE(This, get_localizedExtendedRole);
1234 return E_NOTIMPL;
1237 static HRESULT WINAPI Accessible2_get_nExtendedStates(IAccessible2 *iface, LONG *out_nExtendedStates)
1239 struct Accessible *This = impl_from_Accessible2(iface);
1240 CHECK_ACC_METHOD_EXPECT(This, get_nExtendedStates);
1241 ACC_METHOD_TRACE(This, get_nExtendedStates);
1242 return E_NOTIMPL;
1245 static HRESULT WINAPI Accessible2_get_extendedStates(IAccessible2 *iface, LONG count,
1246 BSTR **out_extended_states, LONG *out_extended_states_count)
1248 struct Accessible *This = impl_from_Accessible2(iface);
1249 CHECK_ACC_METHOD_EXPECT(This, get_extendedStates);
1250 ACC_METHOD_TRACE(This, get_extendedStates);
1251 return E_NOTIMPL;
1254 static HRESULT WINAPI Accessible2_get_localizedExtendedStates(IAccessible2 *iface, LONG count,
1255 BSTR **out_localized_extended_states, LONG *out_localized_extended_states_count)
1257 struct Accessible *This = impl_from_Accessible2(iface);
1258 CHECK_ACC_METHOD_EXPECT(This, get_localizedExtendedStates);
1259 ACC_METHOD_TRACE(This, get_localizedExtendedStates);
1260 return E_NOTIMPL;
1263 static HRESULT WINAPI Accessible2_get_uniqueID(IAccessible2 *iface, LONG *out_unique_id)
1265 struct Accessible *This = impl_from_Accessible2(iface);
1267 CHECK_ACC_METHOD_EXPECT(This, get_uniqueID);
1268 ACC_METHOD_TRACE(This, get_uniqueID);
1270 *out_unique_id = 0;
1271 if (This->unique_id)
1273 *out_unique_id = This->unique_id;
1274 return S_OK;
1277 return E_NOTIMPL;
1280 static HRESULT WINAPI Accessible2_get_windowHandle(IAccessible2 *iface, HWND *out_hwnd)
1282 struct Accessible *This = impl_from_Accessible2(iface);
1283 CHECK_ACC_METHOD_EXPECT(This, get_windowHandle);
1284 ACC_METHOD_TRACE(This, get_windowHandle);
1285 return E_NOTIMPL;
1288 static HRESULT WINAPI Accessible2_get_indexInParent(IAccessible2 *iface, LONG *out_idx_in_parent)
1290 struct Accessible *This = impl_from_Accessible2(iface);
1291 CHECK_ACC_METHOD_EXPECT(This, get_indexInParent);
1292 ACC_METHOD_TRACE(This, get_indexInParent);
1293 return E_NOTIMPL;
1296 static HRESULT WINAPI Accessible2_get_locale(IAccessible2 *iface, IA2Locale *out_locale)
1298 struct Accessible *This = impl_from_Accessible2(iface);
1299 CHECK_ACC_METHOD_EXPECT(This, get_locale);
1300 ACC_METHOD_TRACE(This, get_locale);
1301 return E_NOTIMPL;
1304 static HRESULT WINAPI Accessible2_get_attributes(IAccessible2 *iface, BSTR *out_attributes)
1306 struct Accessible *This = impl_from_Accessible2(iface);
1307 CHECK_ACC_METHOD_EXPECT(This, get_attributes);
1308 ACC_METHOD_TRACE(This, get_attributes);
1309 return E_NOTIMPL;
1312 static const IAccessible2Vtbl Accessible2Vtbl = {
1313 Accessible2_QueryInterface,
1314 Accessible2_AddRef,
1315 Accessible2_Release,
1316 Accessible2_GetTypeInfoCount,
1317 Accessible2_GetTypeInfo,
1318 Accessible2_GetIDsOfNames,
1319 Accessible2_Invoke,
1320 Accessible2_get_accParent,
1321 Accessible2_get_accChildCount,
1322 Accessible2_get_accChild,
1323 Accessible2_get_accName,
1324 Accessible2_get_accValue,
1325 Accessible2_get_accDescription,
1326 Accessible2_get_accRole,
1327 Accessible2_get_accState,
1328 Accessible2_get_accHelp,
1329 Accessible2_get_accHelpTopic,
1330 Accessible2_get_accKeyboardShortcut,
1331 Accessible2_get_accFocus,
1332 Accessible2_get_accSelection,
1333 Accessible2_get_accDefaultAction,
1334 Accessible2_accSelect,
1335 Accessible2_accLocation,
1336 Accessible2_accNavigate,
1337 Accessible2_accHitTest,
1338 Accessible2_accDoDefaultAction,
1339 Accessible2_put_accName,
1340 Accessible2_put_accValue,
1341 Accessible2_get_nRelations,
1342 Accessible2_get_relation,
1343 Accessible2_get_relations,
1344 Accessible2_role,
1345 Accessible2_scrollTo,
1346 Accessible2_scrollToPoint,
1347 Accessible2_get_groupPosition,
1348 Accessible2_get_states,
1349 Accessible2_get_extendedRole,
1350 Accessible2_get_localizedExtendedRole,
1351 Accessible2_get_nExtendedStates,
1352 Accessible2_get_extendedStates,
1353 Accessible2_get_localizedExtendedStates,
1354 Accessible2_get_uniqueID,
1355 Accessible2_get_windowHandle,
1356 Accessible2_get_indexInParent,
1357 Accessible2_get_locale,
1358 Accessible2_get_attributes,
1361 static inline struct Accessible* impl_from_OleWindow(IOleWindow *iface)
1363 return CONTAINING_RECORD(iface, struct Accessible, IOleWindow_iface);
1366 static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **obj)
1368 struct Accessible *This = impl_from_OleWindow(iface);
1369 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1372 static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
1374 struct Accessible *This = impl_from_OleWindow(iface);
1375 return IAccessible_AddRef(&This->IAccessible_iface);
1378 static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
1380 struct Accessible *This = impl_from_OleWindow(iface);
1381 return IAccessible_Release(&This->IAccessible_iface);
1384 static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd)
1386 struct Accessible *This = impl_from_OleWindow(iface);
1388 *hwnd = This->ow_hwnd;
1389 return *hwnd ? S_OK : E_FAIL;
1392 static HRESULT WINAPI OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL f_enter_mode)
1394 return E_NOTIMPL;
1397 static const IOleWindowVtbl OleWindowVtbl = {
1398 OleWindow_QueryInterface,
1399 OleWindow_AddRef,
1400 OleWindow_Release,
1401 OleWindow_GetWindow,
1402 OleWindow_ContextSensitiveHelp
1405 static inline struct Accessible* impl_from_ServiceProvider(IServiceProvider *iface)
1407 return CONTAINING_RECORD(iface, struct Accessible, IServiceProvider_iface);
1410 static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **obj)
1412 struct Accessible *This = impl_from_ServiceProvider(iface);
1413 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1416 static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
1418 struct Accessible *This = impl_from_ServiceProvider(iface);
1419 return IAccessible_AddRef(&This->IAccessible_iface);
1422 static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
1424 struct Accessible *This = impl_from_ServiceProvider(iface);
1425 return IAccessible_Release(&This->IAccessible_iface);
1428 static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID service_guid,
1429 REFIID riid, void **obj)
1431 struct Accessible *This = impl_from_ServiceProvider(iface);
1433 if (IsEqualIID(riid, &IID_IAccessible2) && IsEqualIID(service_guid, &IID_IAccessible2) &&
1434 This->enable_ia2)
1435 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1437 return E_NOTIMPL;
1440 static const IServiceProviderVtbl ServiceProviderVtbl = {
1441 ServiceProvider_QueryInterface,
1442 ServiceProvider_AddRef,
1443 ServiceProvider_Release,
1444 ServiceProvider_QueryService,
1447 static struct Accessible Accessible =
1449 { &AccessibleVtbl },
1450 { &Accessible2Vtbl },
1451 { &OleWindowVtbl },
1452 { &ServiceProviderVtbl },
1454 "Accessible",
1455 NULL,
1456 0, 0,
1457 0, 0, 0, NULL,
1458 0, 0, 0, 0,
1459 FALSE, 0,
1462 static struct Accessible Accessible2 =
1464 { &AccessibleVtbl },
1465 { &Accessible2Vtbl },
1466 { &OleWindowVtbl },
1467 { &ServiceProviderVtbl },
1469 "Accessible2",
1470 NULL,
1471 0, 0,
1472 0, 0, 0, NULL,
1473 0, 0, 0, 0,
1474 FALSE, 0,
1477 static struct Accessible Accessible_child =
1479 { &AccessibleVtbl },
1480 { &Accessible2Vtbl },
1481 { &OleWindowVtbl },
1482 { &ServiceProviderVtbl },
1484 "Accessible_child",
1485 &Accessible.IAccessible_iface,
1486 0, 0,
1487 0, 0, 0, NULL,
1488 0, 0, 0, 0,
1489 FALSE, 0,
1492 static struct Accessible Accessible_child2 =
1494 { &AccessibleVtbl },
1495 { &Accessible2Vtbl },
1496 { &OleWindowVtbl },
1497 { &ServiceProviderVtbl },
1499 "Accessible_child2",
1500 &Accessible.IAccessible_iface,
1501 0, 0,
1502 0, 0, 0, NULL,
1503 0, 0, 0, 0,
1504 FALSE, 0,
1507 struct Provider_prop_override
1509 int prop_id;
1510 VARIANT val;
1513 struct Provider_value_pattern_data
1515 BOOL is_supported;
1516 BOOL is_read_only;
1519 struct Provider_legacy_accessible_pattern_data
1521 BOOL is_supported;
1522 int child_id;
1523 DWORD role;
1526 static struct Provider
1528 IRawElementProviderSimple IRawElementProviderSimple_iface;
1529 IRawElementProviderFragment IRawElementProviderFragment_iface;
1530 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface;
1531 IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface;
1532 IRawElementProviderAdviseEvents IRawElementProviderAdviseEvents_iface;
1533 IValueProvider IValueProvider_iface;
1534 ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface;
1535 LONG ref;
1537 const char *prov_name;
1538 IRawElementProviderFragment *parent;
1539 IRawElementProviderFragmentRoot *frag_root;
1540 IRawElementProviderFragment *prev_sibling;
1541 IRawElementProviderFragment *next_sibling;
1542 IRawElementProviderFragment *first_child;
1543 IRawElementProviderFragment *last_child;
1544 enum ProviderOptions prov_opts;
1545 HWND hwnd;
1546 BOOL ret_invalid_prop_type;
1547 DWORD expected_tid;
1548 int runtime_id[2];
1549 DWORD last_call_tid;
1550 BOOL ignore_hwnd_prop;
1551 HWND override_hwnd;
1552 struct Provider_prop_override *prop_override;
1553 int prop_override_count;
1554 struct UiaRect bounds_rect;
1555 struct Provider_value_pattern_data value_pattern_data;
1556 struct Provider_legacy_accessible_pattern_data legacy_acc_pattern_data;
1557 IRawElementProviderFragment *focus_prov;
1558 IRawElementProviderFragmentRoot **embedded_frag_roots;
1559 int embedded_frag_roots_count;
1560 int advise_events_added_event_id;
1561 int advise_events_removed_event_id;
1562 } Provider, Provider2, Provider_child, Provider_child2;
1563 static struct Provider Provider_hwnd, Provider_nc, Provider_proxy, Provider_proxy2, Provider_override;
1564 static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links);
1565 static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count);
1566 static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val);
1567 static void initialize_provider_tree(BOOL initialize_nav_links);
1568 static void provider_add_child(struct Provider *prov, struct Provider *child);
1570 static const WCHAR *uia_bstr_prop_str = L"uia-string";
1571 static const ULONG uia_i4_prop_val = 0xdeadbeef;
1572 static const ULONG uia_i4_arr_prop_val[] = { 0xfeedbeef, 0xdeadcafe, 0xfefedede };
1573 static const double uia_r8_prop_val = 128.256f;
1574 static const double uia_r8_arr_prop_val[] = { 2.4, 8.16, 32.64 };
1575 static const IRawElementProviderSimple *uia_unk_arr_prop_val[] = { &Provider_child.IRawElementProviderSimple_iface,
1576 &Provider_child2.IRawElementProviderSimple_iface };
1577 static SAFEARRAY *create_i4_safearray(void)
1579 SAFEARRAY *sa;
1580 LONG idx;
1582 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(uia_i4_arr_prop_val))))
1583 return NULL;
1585 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
1586 SafeArrayPutElement(sa, &idx, (void *)&uia_i4_arr_prop_val[idx]);
1588 return sa;
1591 static SAFEARRAY *create_r8_safearray(void)
1593 SAFEARRAY *sa;
1594 LONG idx;
1596 if (!(sa = SafeArrayCreateVector(VT_R8, 0, ARRAY_SIZE(uia_r8_arr_prop_val))))
1597 return NULL;
1599 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
1600 SafeArrayPutElement(sa, &idx, (void *)&uia_r8_arr_prop_val[idx]);
1602 return sa;
1605 static SAFEARRAY *create_unk_safearray(void)
1607 SAFEARRAY *sa;
1608 LONG idx;
1610 if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, ARRAY_SIZE(uia_unk_arr_prop_val))))
1611 return NULL;
1613 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
1614 SafeArrayPutElement(sa, &idx, (void *)uia_unk_arr_prop_val[idx]);
1616 return sa;
1619 enum {
1620 PROV_GET_PROVIDER_OPTIONS,
1621 PROV_GET_PATTERN_PROV,
1622 PROV_GET_PROPERTY_VALUE,
1623 PROV_GET_HOST_RAW_ELEMENT_PROVIDER,
1624 FRAG_NAVIGATE,
1625 FRAG_GET_RUNTIME_ID,
1626 FRAG_GET_FRAGMENT_ROOT,
1627 FRAG_GET_BOUNDING_RECT,
1628 FRAG_GET_EMBEDDED_FRAGMENT_ROOTS,
1629 FRAG_ROOT_GET_FOCUS,
1630 HWND_OVERRIDE_GET_OVERRIDE_PROVIDER,
1631 ADVISE_EVENTS_EVENT_ADDED,
1632 ADVISE_EVENTS_EVENT_REMOVED,
1635 static const char *prov_method_str[] = {
1636 "get_ProviderOptions",
1637 "GetPatternProvider",
1638 "GetPropertyValue",
1639 "get_HostRawElementProvider",
1640 "Navigate",
1641 "GetRuntimeId",
1642 "get_FragmentRoot",
1643 "get_BoundingRectangle",
1644 "GetEmbeddedFragmentRoots",
1645 "GetFocus",
1646 "GetOverrideProviderForHwnd",
1647 "AdviseEventAdded",
1648 "AdviseEventRemoved",
1651 static const char *get_prov_method_str(int method)
1653 if (method >= ARRAY_SIZE(prov_method_str))
1654 return NULL;
1655 else
1656 return prov_method_str[method];
1659 enum {
1660 METHOD_OPTIONAL = 0x01,
1661 METHOD_TODO = 0x02,
1664 struct prov_method_sequence {
1665 struct Provider *prov;
1666 int method;
1667 int flags;
1670 static int sequence_cnt, sequence_size;
1671 static struct prov_method_sequence *sequence;
1674 * This sequence of method calls is always used when creating an HUIANODE from
1675 * an IRawElementProviderSimple.
1677 #define NODE_CREATE_SEQ(prov) \
1678 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1679 /* Win10v1507 and below call this. */ \
1680 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1681 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1682 { prov , PROV_GET_PROPERTY_VALUE }, \
1683 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1684 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1686 #define NODE_CREATE_SEQ_OPTIONAL(prov) \
1687 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1688 /* Win10v1507 and below call this. */ \
1689 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1690 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1691 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, \
1692 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1693 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1696 * This sequence of method calls is always used when creating an HUIANODE from
1697 * an IRawElementProviderSimple that returns an HWND from get_HostRawElementProvider.
1699 #define NODE_CREATE_SEQ2(prov) \
1700 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1701 /* Win10v1507 and below call this. */ \
1702 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1703 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1704 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1705 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1707 #define NODE_CREATE_SEQ2_OPTIONAL(prov) \
1708 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1709 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1710 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1711 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1714 * Node creation sequence with the first get_ProviderOptions call being optional.
1715 * Used for event tests since each Windows version has different amounts of
1716 * calls to get_ProviderOptions before node creation.
1718 #define NODE_CREATE_SEQ3(prov) \
1719 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1720 /* Win10v1507 and below call this. */ \
1721 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1722 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1723 { prov , PROV_GET_PROPERTY_VALUE }, \
1724 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1725 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1727 static void flush_method_sequence(void)
1729 HeapFree(GetProcessHeap(), 0, sequence);
1730 sequence = NULL;
1731 sequence_cnt = sequence_size = 0;
1734 static BOOL method_sequences_enabled = TRUE;
1735 static void add_method_call(struct Provider *prov, int method)
1737 struct prov_method_sequence prov_method = {0};
1739 if (!method_sequences_enabled)
1740 return;
1742 if (!sequence)
1744 sequence_size = 10;
1745 sequence = HeapAlloc(GetProcessHeap(), 0, sequence_size * sizeof(*sequence));
1747 if (sequence_cnt == sequence_size)
1749 sequence_size *= 2;
1750 sequence = HeapReAlloc(GetProcessHeap(), 0, sequence, sequence_size * sizeof(*sequence));
1753 prov_method.prov = prov;
1754 prov_method.method = method;
1755 prov_method.flags = 0;
1756 sequence[sequence_cnt++] = prov_method;
1759 #define ok_method_sequence( exp, context ) \
1760 ok_method_sequence_( (exp), (context), __FILE__, __LINE__)
1761 static void ok_method_sequence_(const struct prov_method_sequence *expected_list, const char *context,
1762 const char *file, int line)
1764 const struct prov_method_sequence *expected = expected_list;
1765 const struct prov_method_sequence *actual;
1766 unsigned int count = 0;
1768 assert(method_sequences_enabled);
1769 add_method_call(NULL, 0);
1770 actual = sequence;
1772 if (context)
1773 winetest_push_context("%s", context);
1775 while (expected->prov && actual->prov)
1777 if (expected->prov == actual->prov && expected->method == actual->method)
1779 if (expected->flags & METHOD_TODO)
1780 todo_wine ok_(file, line)(1, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1781 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1782 expected++;
1783 actual++;
1785 else if (expected->flags & METHOD_TODO)
1787 todo_wine ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1788 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1789 expected++;
1791 else if (expected->flags & METHOD_OPTIONAL)
1792 expected++;
1793 else
1795 ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1796 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1797 expected++;
1798 actual++;
1800 count++;
1803 /* Handle trailing optional/todo_wine methods. */
1804 while (expected->prov && ((expected->flags & METHOD_OPTIONAL) ||
1805 ((expected->flags & METHOD_TODO) && !strcmp(winetest_platform, "wine"))))
1807 if (expected->flags & METHOD_TODO)
1808 todo_wine ok_(file, line)(0, "%d: expected %s_%s\n", count, expected->prov->prov_name,
1809 get_prov_method_str(expected->method));
1810 count++;
1811 expected++;
1814 if (expected->prov || actual->prov)
1816 if (expected->prov)
1817 ok_( file, line)(0, "incomplete sequence: expected %s_%s, got nothing\n", expected->prov->prov_name,
1818 get_prov_method_str(expected->method));
1819 else
1820 ok_( file, line)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual->prov->prov_name,
1821 get_prov_method_str(actual->method));
1824 if (context)
1825 winetest_pop_context();
1827 flush_method_sequence();
1831 * Parsing the string returned by UIA_ProviderDescriptionPropertyId is
1832 * the only way to know what an HUIANODE represents internally. It
1833 * returns a formatted string which always starts with:
1834 * "[pid:<process-id>,providerId:0x<hwnd-ptr> "
1835 * On Windows versions 10v1507 and below, "providerId:" is "hwnd:"
1837 * This is followed by strings for each provider it represents. These are
1838 * formatted as:
1839 * "<prov-type>:<prov-desc> (<origin>)"
1840 * and are terminated with ";", the final provider has no ";" terminator,
1841 * instead it has "]".
1843 * If the given provider is the one used for navigation towards a parent, it has
1844 * "(parent link)" as a suffix on "<prov-type>".
1846 * <prov-type> is one of "Annotation", "Main", "Override", "Hwnd", or
1847 * "Nonclient".
1849 * <prov-desc> is the string returned from calling GetPropertyValue on the
1850 * IRawElementProviderSimple being represented with a property ID of
1851 * UIA_ProviderDescriptionPropertyId.
1853 * <origin> is the name of the module that the
1854 * IRawElementProviderSimple comes from. For unmanaged code, it's:
1855 * "unmanaged:<executable>"
1856 * and for managed code, it's:
1857 * "managed:<assembly-qualified-name>"
1859 * An example:
1860 * [pid:1500,providerId:0x2F054C Main:Provider (unmanaged:uiautomation_test.exe); Hwnd(parent link):HWND Proxy (unmanaged:uiautomationcore.dll)]
1862 static BOOL get_provider_desc(BSTR prov_desc, const WCHAR *prov_type, WCHAR *out_name)
1864 const WCHAR *str, *str2;
1866 str = wcsstr(prov_desc, prov_type);
1867 if (!str)
1868 return FALSE;
1870 if (!out_name)
1871 return TRUE;
1873 str += wcslen(prov_type);
1874 str2 = wcschr(str, L'(');
1875 lstrcpynW(out_name, str, ((str2 - str)));
1877 return TRUE;
1880 #define check_node_provider_desc_todo( prov_desc, prov_type, prov_name, parent_link ) \
1881 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), TRUE, __FILE__, __LINE__)
1882 #define check_node_provider_desc( prov_desc, prov_type, prov_name, parent_link ) \
1883 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), FALSE, __FILE__, __LINE__)
1884 static void check_node_provider_desc_(BSTR prov_desc, const WCHAR *prov_type, const WCHAR *prov_name,
1885 BOOL parent_link, BOOL todo, const char *file, int line)
1887 WCHAR buf[2048];
1889 if (parent_link)
1890 wsprintfW(buf, L"%s(parent link):", prov_type);
1891 else
1892 wsprintfW(buf, L"%s:", prov_type);
1894 if (!get_provider_desc(prov_desc, buf, buf))
1896 if (parent_link)
1897 wsprintfW(buf, L"%s:", prov_type);
1898 else
1899 wsprintfW(buf, L"%s(parent link):", prov_type);
1901 if (!get_provider_desc(prov_desc, buf, buf))
1902 todo_wine_if(todo) ok_(file, line)(0, "failed to get provider string for %s\n", debugstr_w(prov_type));
1903 else
1905 if (parent_link)
1906 todo_wine_if(todo) ok_(file, line)(0, "expected parent link provider %s\n", debugstr_w(prov_type));
1907 else
1908 todo_wine_if(todo) ok_(file, line)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type));
1911 return;
1914 if (prov_name)
1915 ok_(file, line)(!wcscmp(prov_name, buf), "unexpected provider name %s\n", debugstr_w(buf));
1918 #define check_node_provider_desc_prefix( prov_desc, pid, prov_id ) \
1919 check_node_provider_desc_prefix_( (prov_desc), (pid), (prov_id), __FILE__, __LINE__)
1920 static void check_node_provider_desc_prefix_(BSTR prov_desc, DWORD pid, HWND prov_id, const char *file, int line)
1922 const WCHAR *str, *str2;
1923 WCHAR buf[128];
1924 DWORD prov_pid;
1925 HWND prov_hwnd;
1926 WCHAR *end;
1928 str = wcsstr(prov_desc, L"pid:");
1929 str += wcslen(L"pid:");
1930 str2 = wcschr(str, L',');
1931 lstrcpynW(buf, str, (str2 - str) + 1);
1932 prov_pid = wcstoul(buf, &end, 10);
1933 ok_(file, line)(prov_pid == pid, "Unexpected pid %lu\n", prov_pid);
1935 str = wcsstr(prov_desc, L"providerId:");
1936 if (str)
1937 str += wcslen(L"providerId:");
1938 else
1940 str = wcsstr(prov_desc, L"hwnd:");
1941 str += wcslen(L"hwnd:");
1943 str2 = wcschr(str, L' ');
1944 lstrcpynW(buf, str, (str2 - str) + 1);
1945 prov_hwnd = ULongToHandle(wcstoul(buf, &end, 16));
1946 ok_(file, line)(prov_hwnd == prov_id, "Unexpected hwnd %p\n", prov_hwnd);
1950 * For node providers that come from an HWND belonging to another process
1951 * or another thread, the provider is considered 'nested', a node in a node.
1953 static BOOL get_nested_provider_desc(BSTR prov_desc, const WCHAR *prov_type, BOOL parent_link, WCHAR *out_desc)
1955 const WCHAR *str, *str2;
1956 WCHAR buf[1024];
1958 if (!parent_link)
1959 wsprintfW(buf, L"%s:Nested ", prov_type);
1960 else
1961 wsprintfW(buf, L"%s(parent link):Nested ", prov_type);
1962 str = wcsstr(prov_desc, buf);
1963 /* Check with and without parent-link. */
1964 if (!str)
1965 return FALSE;
1967 if (!out_desc)
1968 return TRUE;
1970 str += wcslen(buf);
1971 str2 = wcschr(str, L']');
1972 /* We want to include the ']' character, so + 2. */
1973 lstrcpynW(out_desc, str, ((str2 - str) + 2));
1975 return TRUE;
1978 #define check_runtime_id( exp_runtime_id, exp_size, runtime_id ) \
1979 check_runtime_id_( (exp_runtime_id), (exp_size), (runtime_id), __FILE__, __LINE__)
1980 static void check_runtime_id_(int *exp_runtime_id, int exp_size, SAFEARRAY *runtime_id, const char *file, int line)
1982 LONG i, idx, lbound, ubound, elems;
1983 HRESULT hr;
1984 UINT dims;
1985 int val;
1987 dims = SafeArrayGetDim(runtime_id);
1988 ok_(file, line)(dims == 1, "Unexpected array dims %d\n", dims);
1990 hr = SafeArrayGetLBound(runtime_id, 1, &lbound);
1991 ok_(file, line)(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
1993 hr = SafeArrayGetUBound(runtime_id, 1, &ubound);
1994 ok_(file, line)(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
1996 elems = (ubound - lbound) + 1;
1997 ok_(file, line)(exp_size == elems, "Unexpected runtime_id array size %#lx\n", elems);
1999 for (i = 0; i < elems; i++)
2001 idx = lbound + i;
2002 hr = SafeArrayGetElement(runtime_id, &idx, &val);
2003 ok_(file, line)(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
2004 ok_(file, line)(val == exp_runtime_id[i], "Unexpected runtime_id[%ld] %#x\n", i, val);
2008 static inline struct Provider *impl_from_ProviderSimple(IRawElementProviderSimple *iface)
2010 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderSimple_iface);
2013 HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
2015 struct Provider *This = impl_from_ProviderSimple(iface);
2017 *ppv = NULL;
2018 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
2019 *ppv = iface;
2020 else if (IsEqualIID(riid, &IID_IRawElementProviderFragment))
2021 *ppv = &This->IRawElementProviderFragment_iface;
2022 else if (IsEqualIID(riid, &IID_IRawElementProviderFragmentRoot))
2023 *ppv = &This->IRawElementProviderFragmentRoot_iface;
2024 else if (IsEqualIID(riid, &IID_IRawElementProviderHwndOverride))
2025 *ppv = &This->IRawElementProviderHwndOverride_iface;
2026 else if (IsEqualIID(riid, &IID_IRawElementProviderAdviseEvents))
2027 *ppv = &This->IRawElementProviderAdviseEvents_iface;
2028 else if (IsEqualIID(riid, &IID_IValueProvider))
2029 *ppv = &This->IValueProvider_iface;
2030 else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider))
2031 *ppv = &This->ILegacyIAccessibleProvider_iface;
2032 else
2033 return E_NOINTERFACE;
2035 IRawElementProviderSimple_AddRef(iface);
2036 return S_OK;
2039 ULONG WINAPI ProviderSimple_AddRef(IRawElementProviderSimple *iface)
2041 struct Provider *This = impl_from_ProviderSimple(iface);
2042 return InterlockedIncrement(&This->ref);
2045 ULONG WINAPI ProviderSimple_Release(IRawElementProviderSimple *iface)
2047 struct Provider *This = impl_from_ProviderSimple(iface);
2048 return InterlockedDecrement(&This->ref);
2051 HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *iface,
2052 enum ProviderOptions *ret_val)
2054 struct Provider *This = impl_from_ProviderSimple(iface);
2056 add_method_call(This, PROV_GET_PROVIDER_OPTIONS);
2057 if (This->expected_tid)
2058 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2059 This->last_call_tid = GetCurrentThreadId();
2060 PROV_METHOD_TRACE(This, get_ProviderOptions);
2062 *ret_val = 0;
2063 if (This->prov_opts)
2065 *ret_val = This->prov_opts;
2066 return S_OK;
2069 return E_NOTIMPL;
2072 HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface,
2073 PATTERNID pattern_id, IUnknown **ret_val)
2075 struct Provider *This = impl_from_ProviderSimple(iface);
2077 add_method_call(This, PROV_GET_PATTERN_PROV);
2078 if (This->expected_tid)
2079 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2080 This->last_call_tid = GetCurrentThreadId();
2081 PROV_METHOD_TRACE2(This, GetPatternProvider, pattern_id, uia_pattern_id_strs);
2083 *ret_val = NULL;
2084 switch (pattern_id)
2086 case UIA_ValuePatternId:
2087 if (This->value_pattern_data.is_supported)
2088 *ret_val = (IUnknown *)iface;
2089 break;
2091 case UIA_LegacyIAccessiblePatternId:
2092 if (This->legacy_acc_pattern_data.is_supported)
2093 *ret_val = (IUnknown *)iface;
2094 break;
2096 default:
2097 break;
2100 if (*ret_val)
2101 IUnknown_AddRef(*ret_val);
2103 return S_OK;
2106 HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface,
2107 PROPERTYID prop_id, VARIANT *ret_val)
2109 struct Provider *This = impl_from_ProviderSimple(iface);
2111 add_method_call(This, PROV_GET_PROPERTY_VALUE);
2112 if (This->expected_tid)
2113 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2114 This->last_call_tid = GetCurrentThreadId();
2115 PROV_METHOD_TRACE2(This, GetPropertyValue, prop_id, uia_prop_id_strs);
2117 if (This->prop_override && This->prop_override_count)
2119 int i;
2121 for (i = 0; i < This->prop_override_count; i++)
2123 if (This->prop_override[i].prop_id == prop_id)
2125 *ret_val = This->prop_override[i].val;
2126 if (V_VT(ret_val) == VT_UNKNOWN)
2127 IUnknown_AddRef(V_UNKNOWN(ret_val));
2129 return S_OK;
2134 VariantInit(ret_val);
2135 switch (prop_id)
2137 case UIA_NativeWindowHandlePropertyId:
2138 if (This->ret_invalid_prop_type)
2140 V_VT(ret_val) = VT_R8;
2141 V_R8(ret_val) = uia_r8_prop_val;
2143 else if (!This->ignore_hwnd_prop)
2145 V_VT(ret_val) = VT_I4;
2146 V_I4(ret_val) = HandleToULong(This->hwnd);
2148 break;
2150 case UIA_ProcessIdPropertyId:
2151 case UIA_ControlTypePropertyId:
2152 case UIA_CulturePropertyId:
2153 case UIA_OrientationPropertyId:
2154 case UIA_LiveSettingPropertyId:
2155 case UIA_PositionInSetPropertyId:
2156 case UIA_SizeOfSetPropertyId:
2157 case UIA_LevelPropertyId:
2158 case UIA_LandmarkTypePropertyId:
2159 case UIA_FillColorPropertyId:
2160 case UIA_FillTypePropertyId:
2161 case UIA_VisualEffectsPropertyId:
2162 case UIA_HeadingLevelPropertyId:
2163 if (This->ret_invalid_prop_type)
2165 V_VT(ret_val) = VT_R8;
2166 V_R8(ret_val) = uia_r8_prop_val;
2168 else
2170 V_VT(ret_val) = VT_I4;
2171 V_I4(ret_val) = uia_i4_prop_val;
2173 break;
2175 case UIA_RotationPropertyId:
2176 if (This->ret_invalid_prop_type)
2178 V_VT(ret_val) = VT_I4;
2179 V_I4(ret_val) = uia_i4_prop_val;
2181 else
2183 V_VT(ret_val) = VT_R8;
2184 V_R8(ret_val) = uia_r8_prop_val;
2186 break;
2188 case UIA_LocalizedControlTypePropertyId:
2189 case UIA_NamePropertyId:
2190 case UIA_AcceleratorKeyPropertyId:
2191 case UIA_AccessKeyPropertyId:
2192 case UIA_AutomationIdPropertyId:
2193 case UIA_ClassNamePropertyId:
2194 case UIA_HelpTextPropertyId:
2195 case UIA_ItemTypePropertyId:
2196 case UIA_FrameworkIdPropertyId:
2197 case UIA_ItemStatusPropertyId:
2198 case UIA_AriaRolePropertyId:
2199 case UIA_AriaPropertiesPropertyId:
2200 case UIA_LocalizedLandmarkTypePropertyId:
2201 case UIA_FullDescriptionPropertyId:
2202 if (This->ret_invalid_prop_type)
2204 V_VT(ret_val) = VT_I4;
2205 V_I4(ret_val) = uia_i4_prop_val;
2207 else
2209 V_VT(ret_val) = VT_BSTR;
2210 V_BSTR(ret_val) = SysAllocString(uia_bstr_prop_str);
2212 break;
2214 case UIA_HasKeyboardFocusPropertyId:
2215 case UIA_IsKeyboardFocusablePropertyId:
2216 case UIA_IsEnabledPropertyId:
2217 case UIA_IsControlElementPropertyId:
2218 case UIA_IsContentElementPropertyId:
2219 case UIA_IsPasswordPropertyId:
2220 case UIA_IsOffscreenPropertyId:
2221 case UIA_IsRequiredForFormPropertyId:
2222 case UIA_IsDataValidForFormPropertyId:
2223 case UIA_OptimizeForVisualContentPropertyId:
2224 case UIA_IsPeripheralPropertyId:
2225 case UIA_IsDialogPropertyId:
2226 if (This->ret_invalid_prop_type)
2228 V_VT(ret_val) = VT_R8;
2229 V_R8(ret_val) = uia_r8_prop_val;
2231 else
2233 V_VT(ret_val) = VT_BOOL;
2234 V_BOOL(ret_val) = VARIANT_TRUE;
2236 break;
2238 case UIA_AnnotationTypesPropertyId:
2239 case UIA_OutlineColorPropertyId:
2240 if (This->ret_invalid_prop_type)
2242 V_VT(ret_val) = VT_ARRAY | VT_R8;
2243 V_ARRAY(ret_val) = create_r8_safearray();
2245 else
2247 V_VT(ret_val) = VT_ARRAY | VT_I4;
2248 V_ARRAY(ret_val) = create_i4_safearray();
2250 break;
2252 case UIA_OutlineThicknessPropertyId:
2253 case UIA_SizePropertyId:
2254 if (This->ret_invalid_prop_type)
2256 V_VT(ret_val) = VT_ARRAY | VT_I4;
2257 V_ARRAY(ret_val) = create_i4_safearray();
2259 else
2261 V_VT(ret_val) = VT_ARRAY | VT_R8;
2262 V_ARRAY(ret_val) = create_r8_safearray();
2264 break;
2266 case UIA_LabeledByPropertyId:
2267 if (This->ret_invalid_prop_type)
2269 V_VT(ret_val) = VT_I4;
2270 V_I4(ret_val) = uia_i4_prop_val;
2272 else
2274 V_VT(ret_val) = VT_UNKNOWN;
2275 V_UNKNOWN(ret_val) = (IUnknown *)&Provider_child.IRawElementProviderSimple_iface;
2276 IUnknown_AddRef(V_UNKNOWN(ret_val));
2278 break;
2280 case UIA_AnnotationObjectsPropertyId:
2281 case UIA_DescribedByPropertyId:
2282 case UIA_FlowsFromPropertyId:
2283 case UIA_FlowsToPropertyId:
2284 case UIA_ControllerForPropertyId:
2285 if (This->ret_invalid_prop_type)
2287 V_VT(ret_val) = VT_ARRAY | VT_I4;
2288 V_ARRAY(ret_val) = create_i4_safearray();
2290 else
2292 V_VT(ret_val) = VT_UNKNOWN | VT_ARRAY;
2293 V_ARRAY(ret_val) = create_unk_safearray();
2295 break;
2297 case UIA_ProviderDescriptionPropertyId:
2299 WCHAR buf[1024] = {};
2301 mbstowcs(buf, This->prov_name, strlen(This->prov_name));
2302 V_VT(ret_val) = VT_BSTR;
2303 V_BSTR(ret_val) = SysAllocString(buf);
2304 break;
2307 default:
2308 break;
2311 return S_OK;
2314 HRESULT WINAPI ProviderSimple_get_HostRawElementProvider(IRawElementProviderSimple *iface,
2315 IRawElementProviderSimple **ret_val)
2317 struct Provider *This = impl_from_ProviderSimple(iface);
2319 add_method_call(This, PROV_GET_HOST_RAW_ELEMENT_PROVIDER);
2320 if (This->expected_tid)
2321 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2322 This->last_call_tid = GetCurrentThreadId();
2323 PROV_METHOD_TRACE(This, get_HostRawElementProvider);
2325 *ret_val = NULL;
2326 if (This->hwnd)
2327 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
2329 return S_OK;
2332 IRawElementProviderSimpleVtbl ProviderSimpleVtbl = {
2333 ProviderSimple_QueryInterface,
2334 ProviderSimple_AddRef,
2335 ProviderSimple_Release,
2336 ProviderSimple_get_ProviderOptions,
2337 ProviderSimple_GetPatternProvider,
2338 ProviderSimple_GetPropertyValue,
2339 ProviderSimple_get_HostRawElementProvider,
2342 static inline struct Provider *impl_from_ProviderFragment(IRawElementProviderFragment *iface)
2344 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderFragment_iface);
2347 static HRESULT WINAPI ProviderFragment_QueryInterface(IRawElementProviderFragment *iface, REFIID riid,
2348 void **ppv)
2350 struct Provider *Provider = impl_from_ProviderFragment(iface);
2351 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2354 static ULONG WINAPI ProviderFragment_AddRef(IRawElementProviderFragment *iface)
2356 struct Provider *Provider = impl_from_ProviderFragment(iface);
2357 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2360 static ULONG WINAPI ProviderFragment_Release(IRawElementProviderFragment *iface)
2362 struct Provider *Provider = impl_from_ProviderFragment(iface);
2363 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2366 static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *iface,
2367 enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
2369 struct Provider *This = impl_from_ProviderFragment(iface);
2371 add_method_call(This, FRAG_NAVIGATE);
2372 if (This->expected_tid)
2373 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2374 This->last_call_tid = GetCurrentThreadId();
2375 PROV_METHOD_TRACE2(This, Navigate, direction, uia_nav_dir_strs);
2377 *ret_val = NULL;
2378 switch (direction)
2380 case NavigateDirection_Parent:
2381 *ret_val = This->parent;
2382 break;
2384 case NavigateDirection_NextSibling:
2385 *ret_val = This->next_sibling;
2386 break;
2388 case NavigateDirection_PreviousSibling:
2389 *ret_val = This->prev_sibling;
2390 break;
2392 case NavigateDirection_FirstChild:
2393 *ret_val = This->first_child;
2394 break;
2396 case NavigateDirection_LastChild:
2397 *ret_val = This->last_child;
2398 break;
2400 default:
2401 trace("Invalid navigate direction %d\n", direction);
2402 break;
2405 if (*ret_val)
2406 IRawElementProviderFragment_AddRef(*ret_val);
2408 return S_OK;
2411 static HRESULT WINAPI ProviderFragment_GetRuntimeId(IRawElementProviderFragment *iface,
2412 SAFEARRAY **ret_val)
2414 struct Provider *This = impl_from_ProviderFragment(iface);
2416 add_method_call(This, FRAG_GET_RUNTIME_ID);
2417 if (This->expected_tid)
2418 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2419 This->last_call_tid = GetCurrentThreadId();
2420 PROV_METHOD_TRACE(This, GetRuntimeId);
2422 *ret_val = NULL;
2423 if (This->runtime_id[0] || This->runtime_id[1])
2425 SAFEARRAY *sa;
2426 LONG idx;
2428 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(This->runtime_id))))
2429 return E_FAIL;
2431 for (idx = 0; idx < ARRAY_SIZE(This->runtime_id); idx++)
2432 SafeArrayPutElement(sa, &idx, (void *)&This->runtime_id[idx]);
2434 *ret_val = sa;
2437 return S_OK;
2440 static HRESULT WINAPI ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment *iface,
2441 struct UiaRect *ret_val)
2443 struct Provider *This = impl_from_ProviderFragment(iface);
2445 add_method_call(This, FRAG_GET_BOUNDING_RECT);
2446 if (This->expected_tid)
2447 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2448 This->last_call_tid = GetCurrentThreadId();
2449 PROV_METHOD_TRACE(This, get_BoundingRectangle);
2451 *ret_val = This->bounds_rect;
2452 return S_OK;
2455 static HRESULT WINAPI ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface,
2456 SAFEARRAY **ret_val)
2458 struct Provider *This = impl_from_ProviderFragment(iface);
2460 add_method_call(This, FRAG_GET_EMBEDDED_FRAGMENT_ROOTS);
2461 if (This->expected_tid)
2462 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2463 This->last_call_tid = GetCurrentThreadId();
2464 PROV_METHOD_TRACE(This, GetEmbeddedFragmentRoots);
2466 *ret_val = NULL;
2467 if (This->embedded_frag_roots && This->embedded_frag_roots_count)
2469 SAFEARRAY *sa;
2470 LONG idx;
2472 if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, This->embedded_frag_roots_count)))
2473 return E_FAIL;
2475 for (idx = 0; idx < This->embedded_frag_roots_count; idx++)
2476 SafeArrayPutElement(sa, &idx, (IUnknown *)This->embedded_frag_roots[idx]);
2478 *ret_val = sa;
2481 return S_OK;
2484 static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *iface)
2486 ok(0, "unexpected call\n");
2487 return E_NOTIMPL;
2490 static HRESULT WINAPI ProviderFragment_get_FragmentRoot(IRawElementProviderFragment *iface,
2491 IRawElementProviderFragmentRoot **ret_val)
2493 struct Provider *This = impl_from_ProviderFragment(iface);
2495 add_method_call(This, FRAG_GET_FRAGMENT_ROOT);
2496 if (This->expected_tid)
2497 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2498 This->last_call_tid = GetCurrentThreadId();
2499 PROV_METHOD_TRACE(This, get_FragmentRoot);
2501 *ret_val = NULL;
2502 if (This->frag_root)
2504 *ret_val = This->frag_root;
2505 IRawElementProviderFragmentRoot_AddRef(This->frag_root);
2508 return S_OK;
2511 static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl = {
2512 ProviderFragment_QueryInterface,
2513 ProviderFragment_AddRef,
2514 ProviderFragment_Release,
2515 ProviderFragment_Navigate,
2516 ProviderFragment_GetRuntimeId,
2517 ProviderFragment_get_BoundingRectangle,
2518 ProviderFragment_GetEmbeddedFragmentRoots,
2519 ProviderFragment_SetFocus,
2520 ProviderFragment_get_FragmentRoot,
2523 static inline struct Provider *impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot *iface)
2525 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderFragmentRoot_iface);
2528 static HRESULT WINAPI ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot *iface, REFIID riid,
2529 void **ppv)
2531 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2532 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2535 static ULONG WINAPI ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot *iface)
2537 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2538 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2541 static ULONG WINAPI ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot *iface)
2543 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2544 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2547 static HRESULT WINAPI ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot *iface,
2548 double x, double y, IRawElementProviderFragment **ret_val)
2550 ok(0, "unexpected call\n");
2551 return E_NOTIMPL;
2554 static HRESULT WINAPI ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot *iface,
2555 IRawElementProviderFragment **ret_val)
2557 struct Provider *Provider = impl_from_ProviderFragmentRoot(iface);
2559 add_method_call(Provider, FRAG_ROOT_GET_FOCUS);
2560 if (Provider->expected_tid)
2561 ok(Provider->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2562 Provider->last_call_tid = GetCurrentThreadId();
2563 PROV_METHOD_TRACE(Provider, GetFocus);
2565 *ret_val = NULL;
2566 if (Provider->focus_prov)
2568 *ret_val = Provider->focus_prov;
2569 IRawElementProviderFragment_AddRef(*ret_val);
2572 return S_OK;
2575 static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl = {
2576 ProviderFragmentRoot_QueryInterface,
2577 ProviderFragmentRoot_AddRef,
2578 ProviderFragmentRoot_Release,
2579 ProviderFragmentRoot_ElementProviderFromPoint,
2580 ProviderFragmentRoot_GetFocus,
2583 static inline struct Provider *impl_from_ProviderHwndOverride(IRawElementProviderHwndOverride *iface)
2585 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderHwndOverride_iface);
2588 static HRESULT WINAPI ProviderHwndOverride_QueryInterface(IRawElementProviderHwndOverride *iface, REFIID riid,
2589 void **ppv)
2591 struct Provider *Provider = impl_from_ProviderHwndOverride(iface);
2592 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2595 static ULONG WINAPI ProviderHwndOverride_AddRef(IRawElementProviderHwndOverride *iface)
2597 struct Provider *Provider = impl_from_ProviderHwndOverride(iface);
2598 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2601 static ULONG WINAPI ProviderHwndOverride_Release(IRawElementProviderHwndOverride *iface)
2603 struct Provider *Provider = impl_from_ProviderHwndOverride(iface);
2604 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2607 static HRESULT WINAPI ProviderHwndOverride_GetOverrideProviderForHwnd(IRawElementProviderHwndOverride *iface,
2608 HWND hwnd, IRawElementProviderSimple **ret_val)
2610 struct Provider *This = impl_from_ProviderHwndOverride(iface);
2612 add_method_call(This, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER);
2613 PROV_METHOD_TRACE(This, GetOverrideProviderForHwnd);
2615 *ret_val = NULL;
2616 if (This->override_hwnd == hwnd)
2618 return IRawElementProviderSimple_QueryInterface(&Provider_override.IRawElementProviderSimple_iface,
2619 &IID_IRawElementProviderSimple, (void **)ret_val);
2622 return S_OK;
2625 static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl = {
2626 ProviderHwndOverride_QueryInterface,
2627 ProviderHwndOverride_AddRef,
2628 ProviderHwndOverride_Release,
2629 ProviderHwndOverride_GetOverrideProviderForHwnd,
2632 static inline struct Provider *impl_from_ProviderAdviseEvents(IRawElementProviderAdviseEvents *iface)
2634 return CONTAINING_RECORD(iface, struct Provider, IRawElementProviderAdviseEvents_iface);
2637 static HRESULT WINAPI ProviderAdviseEvents_QueryInterface(IRawElementProviderAdviseEvents *iface, REFIID riid,
2638 void **ppv)
2640 struct Provider *Provider = impl_from_ProviderAdviseEvents(iface);
2641 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2644 static ULONG WINAPI ProviderAdviseEvents_AddRef(IRawElementProviderAdviseEvents *iface)
2646 struct Provider *Provider = impl_from_ProviderAdviseEvents(iface);
2647 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2650 static ULONG WINAPI ProviderAdviseEvents_Release(IRawElementProviderAdviseEvents *iface)
2652 struct Provider *Provider = impl_from_ProviderAdviseEvents(iface);
2653 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2656 static HRESULT WINAPI ProviderAdviseEvents_AdviseEventAdded(IRawElementProviderAdviseEvents *iface,
2657 EVENTID event_id, SAFEARRAY *prop_ids)
2659 struct Provider *This = impl_from_ProviderAdviseEvents(iface);
2661 add_method_call(This, ADVISE_EVENTS_EVENT_ADDED);
2662 if (This->expected_tid)
2663 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2664 This->last_call_tid = GetCurrentThreadId();
2665 This->advise_events_added_event_id = event_id;
2666 PROV_METHOD_TRACE2(This, AdviseEventAdded, event_id, uia_event_id_strs);
2668 return S_OK;
2671 static HRESULT WINAPI ProviderAdviseEvents_AdviseEventRemoved(IRawElementProviderAdviseEvents *iface,
2672 EVENTID event_id, SAFEARRAY *prop_ids)
2674 struct Provider *This = impl_from_ProviderAdviseEvents(iface);
2676 add_method_call(This, ADVISE_EVENTS_EVENT_REMOVED);
2677 if (This->expected_tid)
2678 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2679 This->last_call_tid = GetCurrentThreadId();
2680 This->advise_events_removed_event_id = event_id;
2681 PROV_METHOD_TRACE2(This, AdviseEventRemoved, event_id, uia_event_id_strs);
2683 return S_OK;
2686 static const IRawElementProviderAdviseEventsVtbl ProviderAdviseEventsVtbl = {
2687 ProviderAdviseEvents_QueryInterface,
2688 ProviderAdviseEvents_AddRef,
2689 ProviderAdviseEvents_Release,
2690 ProviderAdviseEvents_AdviseEventAdded,
2691 ProviderAdviseEvents_AdviseEventRemoved,
2694 static inline struct Provider *impl_from_ProviderValuePattern(IValueProvider *iface)
2696 return CONTAINING_RECORD(iface, struct Provider, IValueProvider_iface);
2699 static HRESULT WINAPI ProviderValuePattern_QueryInterface(IValueProvider *iface, REFIID riid,
2700 void **ppv)
2702 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2703 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2706 static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface)
2708 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2709 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2712 static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface)
2714 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2715 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2718 static HRESULT WINAPI ProviderValuePattern_SetValue(IValueProvider *iface, LPCWSTR val)
2720 ok(0, "unexpected call\n");
2721 return E_NOTIMPL;
2724 static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
2726 ok(0, "unexpected call\n");
2727 return E_NOTIMPL;
2730 static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val)
2732 struct Provider *Provider = impl_from_ProviderValuePattern(iface);
2734 *ret_val = Provider->value_pattern_data.is_read_only;
2736 return S_OK;
2739 static const IValueProviderVtbl ProviderValuePatternVtbl = {
2740 ProviderValuePattern_QueryInterface,
2741 ProviderValuePattern_AddRef,
2742 ProviderValuePattern_Release,
2743 ProviderValuePattern_SetValue,
2744 ProviderValuePattern_get_Value,
2745 ProviderValuePattern_get_IsReadOnly,
2748 static inline struct Provider *impl_from_ProviderLegacyIAccessiblePattern(ILegacyIAccessibleProvider *iface)
2750 return CONTAINING_RECORD(iface, struct Provider, ILegacyIAccessibleProvider_iface);
2753 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_QueryInterface(ILegacyIAccessibleProvider *iface, REFIID riid,
2754 void **ppv)
2756 struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface);
2757 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2760 static ULONG WINAPI ProviderLegacyIAccessiblePattern_AddRef(ILegacyIAccessibleProvider *iface)
2762 struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface);
2763 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2766 static ULONG WINAPI ProviderLegacyIAccessiblePattern_Release(ILegacyIAccessibleProvider *iface)
2768 struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface);
2769 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2772 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_Select(ILegacyIAccessibleProvider *iface, LONG select_flags)
2774 ok(0, "unexpected call\n");
2775 return E_NOTIMPL;
2778 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider *iface)
2780 ok(0, "unexpected call\n");
2781 return E_NOTIMPL;
2784 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val)
2786 ok(0, "unexpected call\n");
2787 return E_NOTIMPL;
2790 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider *iface,
2791 IAccessible **out_acc)
2793 ok(0, "unexpected call\n");
2794 return E_NOTIMPL;
2797 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_ChildId(ILegacyIAccessibleProvider *iface, int *out_cid)
2799 struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface);
2801 *out_cid = Provider->legacy_acc_pattern_data.child_id;
2802 return S_OK;
2805 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name)
2807 ok(0, "unexpected call\n");
2808 return E_NOTIMPL;
2811 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value)
2813 ok(0, "unexpected call\n");
2814 return E_NOTIMPL;
2817 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider *iface,
2818 BSTR *out_description)
2820 ok(0, "unexpected call\n");
2821 return E_NOTIMPL;
2824 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role)
2826 struct Provider *Provider = impl_from_ProviderLegacyIAccessiblePattern(iface);
2828 *out_role = Provider->legacy_acc_pattern_data.role;
2829 return S_OK;
2832 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
2834 ok(0, "unexpected call\n");
2835 return E_NOTIMPL;
2838 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help)
2840 ok(0, "unexpected call\n");
2841 return E_NOTIMPL;
2844 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_KeyboardShortcut(ILegacyIAccessibleProvider *iface,
2845 BSTR *out_kbd_shortcut)
2847 ok(0, "unexpected call\n");
2848 return E_NOTIMPL;
2851 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider *iface,
2852 SAFEARRAY **out_selected)
2854 ok(0, "unexpected call\n");
2855 return E_NOTIMPL;
2858 static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_DefaultAction(ILegacyIAccessibleProvider *iface,
2859 BSTR *out_default_action)
2861 ok(0, "unexpected call\n");
2862 return E_NOTIMPL;
2865 static const ILegacyIAccessibleProviderVtbl ProviderLegacyIAccessiblePatternVtbl = {
2866 ProviderLegacyIAccessiblePattern_QueryInterface,
2867 ProviderLegacyIAccessiblePattern_AddRef,
2868 ProviderLegacyIAccessiblePattern_Release,
2869 ProviderLegacyIAccessiblePattern_Select,
2870 ProviderLegacyIAccessiblePattern_DoDefaultAction,
2871 ProviderLegacyIAccessiblePattern_SetValue,
2872 ProviderLegacyIAccessiblePattern_GetIAccessible,
2873 ProviderLegacyIAccessiblePattern_get_ChildId,
2874 ProviderLegacyIAccessiblePattern_get_Name,
2875 ProviderLegacyIAccessiblePattern_get_Value,
2876 ProviderLegacyIAccessiblePattern_get_Description,
2877 ProviderLegacyIAccessiblePattern_get_Role,
2878 ProviderLegacyIAccessiblePattern_get_State,
2879 ProviderLegacyIAccessiblePattern_get_Help,
2880 ProviderLegacyIAccessiblePattern_get_KeyboardShortcut,
2881 ProviderLegacyIAccessiblePattern_GetSelection,
2882 ProviderLegacyIAccessiblePattern_get_DefaultAction,
2885 static struct Provider Provider =
2887 { &ProviderSimpleVtbl },
2888 { &ProviderFragmentVtbl },
2889 { &ProviderFragmentRootVtbl },
2890 { &ProviderHwndOverrideVtbl },
2891 { &ProviderAdviseEventsVtbl },
2892 { &ProviderValuePatternVtbl },
2893 { &ProviderLegacyIAccessiblePatternVtbl },
2895 "Provider",
2896 NULL, NULL,
2897 NULL, NULL,
2898 &Provider_child.IRawElementProviderFragment_iface, &Provider_child2.IRawElementProviderFragment_iface,
2899 0, 0, 0,
2902 static struct Provider Provider2 =
2904 { &ProviderSimpleVtbl },
2905 { &ProviderFragmentVtbl },
2906 { &ProviderFragmentRootVtbl },
2907 { &ProviderHwndOverrideVtbl },
2908 { &ProviderAdviseEventsVtbl },
2909 { &ProviderValuePatternVtbl },
2910 { &ProviderLegacyIAccessiblePatternVtbl },
2912 "Provider2",
2913 NULL, NULL,
2914 NULL, NULL,
2915 NULL, NULL,
2916 0, 0, 0,
2919 static struct Provider Provider_child =
2921 { &ProviderSimpleVtbl },
2922 { &ProviderFragmentVtbl },
2923 { &ProviderFragmentRootVtbl },
2924 { &ProviderHwndOverrideVtbl },
2925 { &ProviderAdviseEventsVtbl },
2926 { &ProviderValuePatternVtbl },
2927 { &ProviderLegacyIAccessiblePatternVtbl },
2929 "Provider_child",
2930 &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
2931 NULL, &Provider_child2.IRawElementProviderFragment_iface,
2932 NULL, NULL,
2933 ProviderOptions_ServerSideProvider, 0, 0,
2936 static struct Provider Provider_child2 =
2938 { &ProviderSimpleVtbl },
2939 { &ProviderFragmentVtbl },
2940 { &ProviderFragmentRootVtbl },
2941 { &ProviderHwndOverrideVtbl },
2942 { &ProviderAdviseEventsVtbl },
2943 { &ProviderValuePatternVtbl },
2944 { &ProviderLegacyIAccessiblePatternVtbl },
2946 "Provider_child2",
2947 &Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
2948 &Provider_child.IRawElementProviderFragment_iface, NULL,
2949 NULL, NULL,
2950 ProviderOptions_ServerSideProvider, 0, 0,
2953 static struct Provider Provider_hwnd =
2955 { &ProviderSimpleVtbl },
2956 { &ProviderFragmentVtbl },
2957 { &ProviderFragmentRootVtbl },
2958 { &ProviderHwndOverrideVtbl },
2959 { &ProviderAdviseEventsVtbl },
2960 { &ProviderValuePatternVtbl },
2961 { &ProviderLegacyIAccessiblePatternVtbl },
2963 "Provider_hwnd",
2964 NULL, NULL,
2965 NULL, NULL,
2966 NULL, NULL,
2967 ProviderOptions_ClientSideProvider, 0, 0,
2970 static struct Provider Provider_nc =
2972 { &ProviderSimpleVtbl },
2973 { &ProviderFragmentVtbl },
2974 { &ProviderFragmentRootVtbl },
2975 { &ProviderHwndOverrideVtbl },
2976 { &ProviderAdviseEventsVtbl },
2977 { &ProviderValuePatternVtbl },
2978 { &ProviderLegacyIAccessiblePatternVtbl },
2980 "Provider_nc",
2981 NULL, NULL,
2982 NULL, NULL,
2983 NULL, NULL,
2984 ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider,
2985 0, 0,
2988 static struct Provider Provider_proxy =
2990 { &ProviderSimpleVtbl },
2991 { &ProviderFragmentVtbl },
2992 { &ProviderFragmentRootVtbl },
2993 { &ProviderHwndOverrideVtbl },
2994 { &ProviderAdviseEventsVtbl },
2995 { &ProviderValuePatternVtbl },
2996 { &ProviderLegacyIAccessiblePatternVtbl },
2998 "Provider_proxy",
2999 NULL, NULL,
3000 NULL, NULL,
3001 NULL, NULL,
3002 ProviderOptions_ClientSideProvider,
3003 0, 0,
3006 static struct Provider Provider_proxy2 =
3008 { &ProviderSimpleVtbl },
3009 { &ProviderFragmentVtbl },
3010 { &ProviderFragmentRootVtbl },
3011 { &ProviderHwndOverrideVtbl },
3012 { &ProviderAdviseEventsVtbl },
3013 { &ProviderValuePatternVtbl },
3014 { &ProviderLegacyIAccessiblePatternVtbl },
3016 "Provider_proxy2",
3017 NULL, NULL,
3018 NULL, NULL,
3019 NULL, NULL,
3020 ProviderOptions_ClientSideProvider,
3021 0, 0,
3024 static struct Provider Provider_override =
3026 { &ProviderSimpleVtbl },
3027 { &ProviderFragmentVtbl },
3028 { &ProviderFragmentRootVtbl },
3029 { &ProviderHwndOverrideVtbl },
3030 { &ProviderAdviseEventsVtbl },
3031 { &ProviderValuePatternVtbl },
3032 { &ProviderLegacyIAccessiblePatternVtbl },
3034 "Provider_override",
3035 NULL, NULL,
3036 NULL, NULL,
3037 NULL, NULL,
3038 ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider,
3039 0, 0,
3042 #define DEFINE_PROVIDER(name) \
3043 static struct Provider Provider_ ## name = \
3045 { &ProviderSimpleVtbl }, \
3046 { &ProviderFragmentVtbl }, \
3047 { &ProviderFragmentRootVtbl }, \
3048 { &ProviderHwndOverrideVtbl }, \
3049 { &ProviderAdviseEventsVtbl }, \
3050 { &ProviderValuePatternVtbl }, \
3051 { &ProviderLegacyIAccessiblePatternVtbl }, \
3052 1, \
3053 "Provider_" # name "", \
3054 NULL, NULL, \
3055 NULL, NULL, \
3056 NULL, NULL, \
3057 ProviderOptions_ServerSideProvider, 0, 0 \
3060 DEFINE_PROVIDER(hwnd_child);
3061 DEFINE_PROVIDER(hwnd_child2);
3062 DEFINE_PROVIDER(nc_child);
3063 DEFINE_PROVIDER(nc_child2);
3064 DEFINE_PROVIDER(child_child);
3065 DEFINE_PROVIDER(child_child2);
3066 DEFINE_PROVIDER(child2_child);
3067 DEFINE_PROVIDER(child2_child_child);
3068 DEFINE_PROVIDER(hwnd2);
3069 DEFINE_PROVIDER(nc2);
3070 DEFINE_PROVIDER(hwnd3);
3071 DEFINE_PROVIDER(nc3);
3073 static IAccessible *acc_client;
3074 static IRawElementProviderSimple *prov_root;
3075 static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3077 switch (message)
3079 case WM_GETOBJECT:
3080 if (lParam == (DWORD)OBJID_CLIENT)
3082 CHECK_EXPECT(winproc_GETOBJECT_CLIENT);
3083 if (acc_client)
3084 return LresultFromObject(&IID_IAccessible, wParam, (IUnknown *)acc_client);
3086 break;
3088 else if (lParam == UiaRootObjectId)
3090 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot);
3091 if (prov_root)
3092 return UiaReturnRawElementProvider(hwnd, wParam, lParam, prov_root);
3094 break;
3097 break;
3099 default:
3100 break;
3103 return DefWindowProcA(hwnd, message, wParam, lParam);
3106 static IRawElementProviderSimple *child_win_prov_root;
3107 static LRESULT WINAPI child_test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
3109 switch (message)
3111 case WM_GETOBJECT:
3112 if (lParam == UiaRootObjectId)
3114 CHECK_EXPECT(child_winproc_GETOBJECT_UiaRoot);
3115 if (child_win_prov_root)
3116 return UiaReturnRawElementProvider(hwnd, wParam, lParam, child_win_prov_root);
3118 break;
3121 break;
3123 default:
3124 break;
3127 return DefWindowProcA(hwnd, message, wParam, lParam);
3130 static void test_UiaHostProviderFromHwnd(void)
3132 IRawElementProviderSimple *p, *p2;
3133 enum ProviderOptions prov_opt;
3134 WNDCLASSA cls;
3135 HRESULT hr;
3136 HWND hwnd;
3137 VARIANT v;
3138 int i;
3140 cls.style = 0;
3141 cls.lpfnWndProc = test_wnd_proc;
3142 cls.cbClsExtra = 0;
3143 cls.cbWndExtra = 0;
3144 cls.hInstance = GetModuleHandleA(NULL);
3145 cls.hIcon = 0;
3146 cls.hCursor = NULL;
3147 cls.hbrBackground = NULL;
3148 cls.lpszMenuName = NULL;
3149 cls.lpszClassName = "HostProviderFromHwnd class";
3151 RegisterClassA(&cls);
3153 hwnd = CreateWindowExA(0, "HostProviderFromHwnd class", "Test window 1",
3154 WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_VISIBLE,
3155 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
3156 ok(hwnd != NULL, "Failed to create a test window.\n");
3158 p = (void *)0xdeadbeef;
3159 hr = UiaHostProviderFromHwnd(NULL, &p);
3160 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3161 ok(p == NULL, "Unexpected instance.\n");
3163 hr = UiaHostProviderFromHwnd(hwnd, NULL);
3164 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3166 p = NULL;
3167 hr = UiaHostProviderFromHwnd(hwnd, &p);
3168 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
3170 p2 = NULL;
3171 hr = UiaHostProviderFromHwnd(hwnd, &p2);
3172 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
3173 ok(p != p2, "Unexpected instance.\n");
3174 IRawElementProviderSimple_Release(p2);
3176 hr = IRawElementProviderSimple_get_HostRawElementProvider(p, &p2);
3177 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3178 ok(p2 == NULL, "Unexpected instance.\n");
3180 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
3181 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3182 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
3183 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
3185 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
3186 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3187 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3188 VariantClear(&v);
3190 /* No patterns are implemented on the HWND Host provider. */
3191 for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++)
3193 IUnknown *unk;
3195 unk = (void *)0xdeadbeef;
3196 hr = IRawElementProviderSimple_GetPatternProvider(p, i, &unk);
3197 ok(hr == S_OK, "Unexpected hr %#lx, %d.\n", hr, i);
3198 ok(!unk, "Pattern %d returned %p\n", i, unk);
3201 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
3202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3203 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
3204 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3205 "Unexpected provider options %#x\n", prov_opt);
3207 /* Test behavior post Window destruction. */
3208 DestroyWindow(hwnd);
3210 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
3211 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3212 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
3213 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
3215 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
3216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3217 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3218 VariantClear(&v);
3220 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
3221 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3222 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
3223 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3224 "Unexpected provider options %#x\n", prov_opt);
3226 IRawElementProviderSimple_Release(p);
3228 UnregisterClassA("HostProviderFromHwnd class", NULL);
3231 static DWORD WINAPI uia_reserved_val_iface_marshal_thread(LPVOID param)
3233 IStream **stream = param;
3234 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
3235 HRESULT hr;
3237 CoInitializeEx(NULL, COINIT_MULTITHREADED);
3239 hr = CoGetInterfaceAndReleaseStream(stream[0], &IID_IUnknown, (void **)&unk_ns);
3240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3242 hr = CoGetInterfaceAndReleaseStream(stream[1], &IID_IUnknown, (void **)&unk_ma);
3243 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3245 hr = UiaGetReservedNotSupportedValue(&unk_ns2);
3246 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3248 hr = UiaGetReservedMixedAttributeValue(&unk_ma2);
3249 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3251 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
3252 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
3254 CoUninitialize();
3256 return 0;
3259 static void test_uia_reserved_value_ifaces(void)
3261 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
3262 IStream *stream[2];
3263 IMarshal *marshal;
3264 HANDLE thread;
3265 ULONG refcnt;
3266 HRESULT hr;
3268 /* ReservedNotSupportedValue. */
3269 hr = UiaGetReservedNotSupportedValue(NULL);
3270 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3272 hr = UiaGetReservedNotSupportedValue(&unk_ns);
3273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3274 ok(unk_ns != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.\n");
3276 refcnt = IUnknown_AddRef(unk_ns);
3277 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3279 refcnt = IUnknown_AddRef(unk_ns);
3280 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3282 refcnt = IUnknown_Release(unk_ns);
3283 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3285 hr = UiaGetReservedNotSupportedValue(&unk_ns2);
3286 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3287 ok(unk_ns2 != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.");
3288 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
3290 marshal = NULL;
3291 hr = IUnknown_QueryInterface(unk_ns, &IID_IMarshal, (void **)&marshal);
3292 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3293 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
3295 refcnt = IMarshal_AddRef(marshal);
3296 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
3298 refcnt = IMarshal_Release(marshal);
3299 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3301 refcnt = IMarshal_Release(marshal);
3302 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
3304 /* ReservedMixedAttributeValue. */
3305 hr = UiaGetReservedMixedAttributeValue(NULL);
3306 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3308 hr = UiaGetReservedMixedAttributeValue(&unk_ma);
3309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3310 ok(unk_ma != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
3312 refcnt = IUnknown_AddRef(unk_ma);
3313 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3315 refcnt = IUnknown_AddRef(unk_ma);
3316 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3318 refcnt = IUnknown_Release(unk_ma);
3319 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3321 hr = UiaGetReservedMixedAttributeValue(&unk_ma2);
3322 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3323 ok(unk_ma2 != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
3324 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
3326 marshal = NULL;
3327 hr = IUnknown_QueryInterface(unk_ma, &IID_IMarshal, (void **)&marshal);
3328 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3329 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
3331 refcnt = IMarshal_AddRef(marshal);
3332 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
3334 refcnt = IMarshal_Release(marshal);
3335 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3337 refcnt = IMarshal_Release(marshal);
3338 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
3340 /* Test cross-thread marshaling behavior. */
3341 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
3343 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, unk_ns, &stream[0]);
3344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3345 hr = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown, unk_ma, &stream[1]);
3346 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3348 thread = CreateThread(NULL, 0, uia_reserved_val_iface_marshal_thread, (void *)stream, 0, NULL);
3349 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
3351 MSG msg;
3352 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
3354 TranslateMessage(&msg);
3355 DispatchMessageW(&msg);
3358 CloseHandle(thread);
3360 CoUninitialize();
3363 DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
3364 static IAccessible *msaa_acc_da_unwrap(IAccessible *acc)
3366 IServiceProvider *sp;
3367 HRESULT hr;
3369 hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void**)&sp);
3370 if (SUCCEEDED(hr))
3372 IAccessible *acc2 = NULL;
3374 hr = IServiceProvider_QueryService(sp, &SID_AccFromDAWrapper, &IID_IAccessible, (void**)&acc2);
3375 IServiceProvider_Release(sp);
3376 if (SUCCEEDED(hr) && acc2)
3377 return acc2;
3380 return NULL;
3383 #define check_msaa_prov_acc( elprov, acc, cid) \
3384 check_msaa_prov_acc_( ((IUnknown *)elprov), (acc), (cid), __LINE__)
3385 static void check_msaa_prov_acc_(IUnknown *elprov, IAccessible *acc, INT cid, int line)
3387 ILegacyIAccessibleProvider *accprov;
3388 IAccessible *acc2, *acc3;
3389 INT child_id;
3390 HRESULT hr;
3392 hr = IUnknown_QueryInterface(elprov, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
3393 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3394 ok_(__FILE__, line)(!!accprov, "accprov == NULL\n");
3396 acc2 = acc3 = NULL;
3397 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc2);
3398 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3401 * Potentially get our IAccessible out of a direct annotation wrapper
3402 * IAccessible.
3404 if (acc && acc2 && (acc != acc2) && (acc3 = msaa_acc_da_unwrap(acc2)))
3406 IAccessible_Release(acc2);
3407 acc2 = acc3;
3409 ok_(__FILE__, line)(acc2 == acc, "acc2 != acc\n");
3410 if (acc2)
3411 IAccessible_Release(acc2);
3413 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
3414 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3415 ok_(__FILE__, line)(child_id == cid, "child_id != cid\n");
3417 ILegacyIAccessibleProvider_Release(accprov);
3420 #define check_msaa_prov_host_elem_prov( elem, exp_host_prov) \
3421 check_msaa_prov_host_elem_prov_( ((IUnknown *)elem), (exp_host_prov), __LINE__)
3422 static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov, int line)
3424 IRawElementProviderSimple *elprov, *elprov2;
3425 HRESULT hr;
3427 hr = IUnknown_QueryInterface(elem, &IID_IRawElementProviderSimple, (void **)&elprov);
3428 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3429 ok_(__FILE__, line)(!!elprov, "elprov == NULL\n");
3431 elprov2 = (void *)0xdeadbeef;
3432 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3433 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3434 ok_(__FILE__, line)((elprov2 != (void *)0xdeadbeef) && !!elprov2 == exp_host_prov, "Unexpected provider %p from get_HostRawElementProvider\n", elprov2);
3436 if (elprov2)
3437 IRawElementProviderSimple_Release(elprov2);
3438 IRawElementProviderSimple_Release(elprov);
3441 static void set_accessible_props(struct Accessible *acc, INT role, INT state,
3442 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height);
3443 static void test_uia_prov_from_acc_fragment_root(HWND hwnd)
3445 IRawElementProviderFragmentRoot *elroot, *elroot2;
3446 IRawElementProviderFragment *elfrag, *elfrag2;
3447 IRawElementProviderSimple *elprov;
3448 HRESULT hr;
3450 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
3451 Accessible.ow_hwnd = hwnd;
3453 elprov = NULL;
3454 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3455 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3456 ok(!!elprov, "elprov == NULL\n");
3458 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3459 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3460 ok(!!elfrag, "elfrag == NULL\n");
3463 * get_FragmentRoot does the equivalent of calling
3464 * AccessibleObjectFromWindow with OBJID_CLIENT on the HWND associated
3465 * with our IAccessible. Unlike UiaProviderFromIAccessible, it will create
3466 * a provider from a default oleacc proxy.
3468 elroot = NULL;
3469 acc_client = NULL;
3470 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3471 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3472 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3473 ok(!!elroot, "elroot == NULL\n");
3474 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3477 * ILegacyIAccessibleProvider::GetIAccessible returns a NULL
3478 * IAccessible if the provider represents an oleacc proxy.
3480 check_msaa_prov_acc(elroot, NULL, CHILDID_SELF);
3483 * Returns a provider from get_HostRawElementProvider without having
3484 * to query the HWND.
3486 check_msaa_prov_host_elem_prov(elroot, TRUE);
3488 hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
3489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3490 ok(!!elfrag2, "elfrag2 == NULL\n");
3493 * Even on a provider retrieved from get_FragmentRoot, the HWND is
3494 * queried and a new fragment root is returned rather than just
3495 * returning our current fragment root interface.
3497 elroot2 = NULL;
3498 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3499 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
3500 IRawElementProviderFragment_Release(elfrag2);
3501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3502 ok(!!elroot2, "elroot2 == NULL\n");
3503 check_msaa_prov_acc(elroot2, NULL, CHILDID_SELF);
3504 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3506 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
3507 IRawElementProviderFragmentRoot_Release(elroot2);
3508 IRawElementProviderFragmentRoot_Release(elroot);
3511 * Accessible is now the IAccessible for our HWND, so we'll get it instead
3512 * of an oleacc proxy.
3514 acc_client = &Accessible.IAccessible_iface;
3515 elroot = NULL;
3516 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3517 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3519 ok(!!elroot, "elroot == NULL\n");
3520 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3521 check_msaa_prov_acc(elroot, &Accessible.IAccessible_iface, CHILDID_SELF);
3524 * Returns a provider from get_HostRawElementProvider without having
3525 * to query the HWND, same as before.
3527 check_msaa_prov_host_elem_prov(elroot, TRUE);
3529 hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
3530 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3531 ok(!!elfrag2, "elfrag2 == NULL\n");
3533 /* Same deal as before, unique FragmentRoot even on a known root. */
3534 elroot2 = NULL;
3535 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3536 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
3537 IRawElementProviderFragment_Release(elfrag2);
3538 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3539 ok(!!elroot2, "elroot2 == NULL\n");
3540 check_msaa_prov_acc(elroot2, &Accessible.IAccessible_iface, CHILDID_SELF);
3541 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3543 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
3544 IRawElementProviderFragmentRoot_Release(elroot2);
3546 IRawElementProviderFragmentRoot_Release(elroot);
3547 IRawElementProviderFragment_Release(elfrag);
3548 IRawElementProviderSimple_Release(elprov);
3551 * Test simple child element.
3553 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
3554 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3556 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3557 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3558 ok(!!elfrag, "elfrag == NULL\n");
3561 * Simple child element queries HWND as well, does not just return its
3562 * parent.
3564 elroot = NULL;
3565 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3566 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3568 ok(!!elroot, "elroot == NULL\n");
3569 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3570 check_msaa_prov_acc(elroot, &Accessible.IAccessible_iface, CHILDID_SELF);
3571 check_msaa_prov_host_elem_prov(elroot, TRUE);
3573 IRawElementProviderFragmentRoot_Release(elroot);
3574 IRawElementProviderFragment_Release(elfrag);
3575 IRawElementProviderSimple_Release(elprov);
3578 * Test child of root HWND IAccessible.
3580 set_accessible_props(&Accessible_child, ROLE_SYSTEM_TEXT, 0, 0, L"acc_child_name", 0, 0, 0, 0);
3582 elprov = NULL;
3583 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent); /* Gets HWND from parent IAccessible. */
3584 SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
3585 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3586 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3587 ok(!!elprov, "elprov == NULL\n");
3588 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
3589 CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
3591 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3592 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3593 ok(!!elfrag, "elfrag == NULL\n");
3596 * Again, same behavior as simple children. It doesn't just retrieve the
3597 * parent IAccessible, it queries the HWND.
3599 elroot = NULL;
3600 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3601 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3602 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3603 ok(!!elroot, "elroot == NULL\n");
3604 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3605 check_msaa_prov_acc(elroot, &Accessible.IAccessible_iface, CHILDID_SELF);
3607 IRawElementProviderFragmentRoot_Release(elroot);
3608 IRawElementProviderFragment_Release(elfrag);
3609 IRawElementProviderSimple_Release(elprov);
3611 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3612 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
3613 acc_client = NULL;
3616 struct msaa_role_uia_type {
3617 INT acc_role;
3618 INT uia_control_type;
3621 static const struct msaa_role_uia_type msaa_role_uia_types[] = {
3622 { ROLE_SYSTEM_TITLEBAR, UIA_TitleBarControlTypeId },
3623 { ROLE_SYSTEM_MENUBAR, UIA_MenuBarControlTypeId },
3624 { ROLE_SYSTEM_SCROLLBAR, UIA_ScrollBarControlTypeId },
3625 { ROLE_SYSTEM_GRIP, UIA_ThumbControlTypeId },
3626 { ROLE_SYSTEM_WINDOW, UIA_WindowControlTypeId },
3627 { ROLE_SYSTEM_MENUPOPUP, UIA_MenuControlTypeId },
3628 { ROLE_SYSTEM_MENUITEM, UIA_MenuItemControlTypeId },
3629 { ROLE_SYSTEM_TOOLTIP, UIA_ToolTipControlTypeId },
3630 { ROLE_SYSTEM_APPLICATION, UIA_WindowControlTypeId },
3631 { ROLE_SYSTEM_DOCUMENT, UIA_DocumentControlTypeId },
3632 { ROLE_SYSTEM_PANE, UIA_PaneControlTypeId },
3633 { ROLE_SYSTEM_GROUPING, UIA_GroupControlTypeId },
3634 { ROLE_SYSTEM_SEPARATOR, UIA_SeparatorControlTypeId },
3635 { ROLE_SYSTEM_TOOLBAR, UIA_ToolBarControlTypeId },
3636 { ROLE_SYSTEM_STATUSBAR, UIA_StatusBarControlTypeId },
3637 { ROLE_SYSTEM_TABLE, UIA_TableControlTypeId },
3638 { ROLE_SYSTEM_COLUMNHEADER, UIA_HeaderControlTypeId },
3639 { ROLE_SYSTEM_ROWHEADER, UIA_HeaderControlTypeId },
3640 { ROLE_SYSTEM_CELL, UIA_DataItemControlTypeId },
3641 { ROLE_SYSTEM_LINK, UIA_HyperlinkControlTypeId },
3642 { ROLE_SYSTEM_LIST, UIA_ListControlTypeId },
3643 { ROLE_SYSTEM_LISTITEM, UIA_ListItemControlTypeId },
3644 { ROLE_SYSTEM_OUTLINE, UIA_TreeControlTypeId },
3645 { ROLE_SYSTEM_OUTLINEITEM, UIA_TreeItemControlTypeId },
3646 { ROLE_SYSTEM_PAGETAB, UIA_TabItemControlTypeId },
3647 { ROLE_SYSTEM_INDICATOR, UIA_ThumbControlTypeId },
3648 { ROLE_SYSTEM_GRAPHIC, UIA_ImageControlTypeId },
3649 { ROLE_SYSTEM_STATICTEXT, UIA_TextControlTypeId },
3650 { ROLE_SYSTEM_TEXT, UIA_EditControlTypeId },
3651 { ROLE_SYSTEM_PUSHBUTTON, UIA_ButtonControlTypeId },
3652 { ROLE_SYSTEM_CHECKBUTTON, UIA_CheckBoxControlTypeId },
3653 { ROLE_SYSTEM_RADIOBUTTON, UIA_RadioButtonControlTypeId },
3654 { ROLE_SYSTEM_COMBOBOX, UIA_ComboBoxControlTypeId },
3655 { ROLE_SYSTEM_PROGRESSBAR, UIA_ProgressBarControlTypeId },
3656 { ROLE_SYSTEM_SLIDER, UIA_SliderControlTypeId },
3657 { ROLE_SYSTEM_SPINBUTTON, UIA_SpinnerControlTypeId },
3658 { ROLE_SYSTEM_BUTTONDROPDOWN, UIA_SplitButtonControlTypeId },
3659 { ROLE_SYSTEM_BUTTONMENU, UIA_MenuItemControlTypeId },
3660 { ROLE_SYSTEM_BUTTONDROPDOWNGRID, UIA_ButtonControlTypeId },
3661 { ROLE_SYSTEM_PAGETABLIST, UIA_TabControlTypeId },
3662 { ROLE_SYSTEM_SPLITBUTTON, UIA_SplitButtonControlTypeId },
3663 /* These accessible roles have no equivalent in UI Automation. */
3664 { ROLE_SYSTEM_SOUND, 0 },
3665 { ROLE_SYSTEM_CURSOR, 0 },
3666 { ROLE_SYSTEM_CARET, 0 },
3667 { ROLE_SYSTEM_ALERT, 0 },
3668 { ROLE_SYSTEM_CLIENT, 0 },
3669 { ROLE_SYSTEM_CHART, 0 },
3670 { ROLE_SYSTEM_DIALOG, 0 },
3671 { ROLE_SYSTEM_BORDER, 0 },
3672 { ROLE_SYSTEM_COLUMN, 0 },
3673 { ROLE_SYSTEM_ROW, 0 },
3674 { ROLE_SYSTEM_HELPBALLOON, 0 },
3675 { ROLE_SYSTEM_CHARACTER, 0 },
3676 { ROLE_SYSTEM_PROPERTYPAGE, 0 },
3677 { ROLE_SYSTEM_DROPLIST, 0 },
3678 { ROLE_SYSTEM_DIAL, 0 },
3679 { ROLE_SYSTEM_HOTKEYFIELD, 0 },
3680 { ROLE_SYSTEM_DIAGRAM, 0 },
3681 { ROLE_SYSTEM_ANIMATION, 0 },
3682 { ROLE_SYSTEM_EQUATION, 0 },
3683 { ROLE_SYSTEM_WHITESPACE, 0 },
3684 { ROLE_SYSTEM_IPADDRESS, 0 },
3685 { ROLE_SYSTEM_OUTLINEBUTTON, 0 },
3688 struct msaa_state_uia_prop {
3689 INT acc_state;
3690 INT prop_id;
3693 static const struct msaa_state_uia_prop msaa_state_uia_props[] = {
3694 { STATE_SYSTEM_FOCUSED, UIA_HasKeyboardFocusPropertyId },
3695 { STATE_SYSTEM_FOCUSABLE, UIA_IsKeyboardFocusablePropertyId },
3696 { ~STATE_SYSTEM_UNAVAILABLE, UIA_IsEnabledPropertyId },
3697 { STATE_SYSTEM_PROTECTED, UIA_IsPasswordPropertyId },
3700 static void set_accessible_props(struct Accessible *acc, INT role, INT state,
3701 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height)
3704 acc->role = role;
3705 acc->state = state;
3706 acc->child_count = child_count;
3707 acc->name = name;
3708 acc->left = left;
3709 acc->top = top;
3710 acc->width = width;
3711 acc->height = height;
3714 static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id)
3716 acc->enable_ia2 = enable_ia2;
3717 acc->unique_id = unique_id;
3720 static void test_uia_prov_from_acc_ia2(void)
3722 IRawElementProviderSimple *elprov, *elprov2;
3723 HRESULT hr;
3725 /* Only one exposes an IA2 interface, no match. */
3726 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
3727 set_accessible_ia2_props(&Accessible, TRUE, 0);
3728 set_accessible_props(&Accessible2, ROLE_SYSTEM_TEXT, 0, 0, L"acc_name", 0, 0, 0, 0);
3729 set_accessible_ia2_props(&Accessible2, FALSE, 0);
3731 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3732 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3733 if (Accessible.ref != 3)
3735 IRawElementProviderSimple_Release(elprov);
3736 win_skip("UiaProviderFromIAccessible has no IAccessible2 support, skipping tests.\n");
3737 return;
3740 acc_client = &Accessible2.IAccessible_iface;
3741 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3742 /* The four below are only called on Win10v1909. */
3743 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
3744 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
3745 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
3746 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
3747 elprov2 = (void *)0xdeadbeef;
3748 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3750 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3751 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3752 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3755 * Win10v1909 has IAccessible2 support, but it's not used for checking if
3756 * two IAccessible interfaces match. Skip the comparison tests for this
3757 * Windows version.
3759 if (Accessible.called_get_accRole)
3761 IRawElementProviderSimple_Release(elprov);
3762 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
3763 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
3764 CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
3765 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
3766 win_skip("Win10v1909 doesn't support IAccessible2 interface comparison, skipping tests.\n");
3767 return;
3769 Accessible.called_get_accRole = Accessible.expect_get_accRole = 0;
3770 Accessible2.called_get_accRole = Accessible2.expect_get_accRole = 0;
3771 Accessible2.called_QI_IAccIdentity = Accessible2.expect_QI_IAccIdentity = 0;
3772 Accessible2.called_get_accParent = Accessible2.expect_get_accParent = 0;
3774 Accessible.role = Accessible2.role = 0;
3775 elprov2 = (void *)0xdeadbeef;
3776 acc_client = NULL;
3777 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3778 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3779 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3781 IRawElementProviderSimple_Release(elprov);
3782 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3785 * If &Accessible returns a failure code on get_uniqueID, &Accessible2's
3786 * uniqueID is not checked.
3788 set_accessible_ia2_props(&Accessible, TRUE, 0);
3789 set_accessible_ia2_props(&Accessible2, TRUE, 0);
3790 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3791 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3792 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3794 acc_client = &Accessible2.IAccessible_iface;
3795 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3796 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
3797 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
3798 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
3799 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
3800 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
3801 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
3802 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
3803 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
3804 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
3805 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
3806 elprov2 = (void *)0xdeadbeef;
3807 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3808 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3809 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3810 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3811 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3812 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
3813 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
3814 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
3815 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
3816 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
3817 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
3818 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
3819 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
3820 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
3821 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
3822 IRawElementProviderSimple_Release(elprov2);
3824 elprov2 = (void *)0xdeadbeef;
3825 acc_client = NULL;
3826 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3827 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3828 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3829 IRawElementProviderSimple_Release(elprov2);
3831 IRawElementProviderSimple_Release(elprov);
3832 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3834 /* Unique ID matches. */
3835 set_accessible_ia2_props(&Accessible, TRUE, 1);
3836 set_accessible_ia2_props(&Accessible2, TRUE, 1);
3837 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3838 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3839 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3841 acc_client = &Accessible2.IAccessible_iface;
3842 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3843 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
3844 SET_ACC_METHOD_EXPECT(&Accessible2, get_uniqueID);
3845 elprov2 = (void *)0xdeadbeef;
3846 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3847 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3848 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3849 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3850 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3851 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
3852 CHECK_ACC_METHOD_CALLED(&Accessible2, get_uniqueID);
3853 IRawElementProviderSimple_Release(elprov2);
3855 elprov2 = (void *)0xdeadbeef;
3856 acc_client = NULL;
3857 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3858 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3859 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3860 IRawElementProviderSimple_Release(elprov2);
3862 IRawElementProviderSimple_Release(elprov);
3863 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3865 /* Unique ID mismatch. */
3866 set_accessible_ia2_props(&Accessible, TRUE, 1);
3867 set_accessible_ia2_props(&Accessible2, TRUE, 2);
3868 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3869 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3870 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
3872 acc_client = &Accessible2.IAccessible_iface;
3873 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3874 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
3875 SET_ACC_METHOD_EXPECT(&Accessible2, get_uniqueID);
3876 elprov2 = (void *)0xdeadbeef;
3877 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3878 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3879 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3880 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
3881 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3882 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
3883 CHECK_ACC_METHOD_CALLED(&Accessible2, get_uniqueID);
3885 elprov2 = (void *)0xdeadbeef;
3886 acc_client = NULL;
3887 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3888 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3889 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
3891 IRawElementProviderSimple_Release(elprov);
3892 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
3894 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
3895 set_accessible_ia2_props(&Accessible, FALSE, 0);
3896 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
3897 set_accessible_ia2_props(&Accessible2, FALSE, 0);
3900 #define check_fragment_acc( fragment, acc, cid) \
3901 check_fragment_acc_( (fragment), (acc), (cid), __LINE__)
3902 static void check_fragment_acc_(IRawElementProviderFragment *elfrag, IAccessible *acc,
3903 INT cid, int line)
3905 ILegacyIAccessibleProvider *accprov;
3906 IAccessible *accessible;
3907 INT child_id;
3908 HRESULT hr;
3910 hr = IRawElementProviderFragment_QueryInterface(elfrag, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
3911 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
3912 ok_(__FILE__, line) (!!accprov, "accprov == NULL\n");
3914 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &accessible);
3915 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
3916 ok_(__FILE__, line) (accessible == acc, "accessible != acc\n");
3917 IAccessible_Release(accessible);
3919 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
3920 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
3921 ok_(__FILE__, line) (child_id == cid, "child_id != cid\n");
3923 ILegacyIAccessibleProvider_Release(accprov);
3926 static void test_uia_prov_from_acc_navigation(void)
3928 IRawElementProviderFragment *elfrag, *elfrag2, *elfrag3;
3929 IRawElementProviderSimple *elprov, *elprov2;
3930 HRESULT hr;
3933 * Full IAccessible parent, with 4 children:
3934 * childid 1 is a simple element, with STATE_SYSTEM_INVISIBLE.
3935 * childid 2 is Accessible_child.
3936 * childid 3 is a simple element with STATE_SYSTEM_NORMAL.
3937 * childid 4 is Accessible_child2.
3939 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3940 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3941 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3943 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3944 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3945 ok(!!elfrag, "elfrag == NULL\n");
3948 * First time doing NavigateDirection_Parent will result in the same root
3949 * accessible check as get_HostRawElementProvider. If this IAccessible is
3950 * the root for its associated HWND, NavigateDirection_Parent and
3951 * NavigateDirection_Next/PreviousSibling will do nothing, as UI Automation
3952 * provides non-client area providers for the root IAccessible's parent
3953 * and siblings.
3955 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
3956 L"acc_name", 0, 0, 50, 50);
3957 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
3958 L"acc_name", 0, 0, 50, 50);
3959 acc_client = &Accessible2.IAccessible_iface;
3960 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3961 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
3962 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
3963 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
3964 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
3965 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
3966 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
3967 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
3968 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
3969 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
3970 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
3971 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
3972 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
3973 elfrag2 = (void *)0xdeadbeef;
3974 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
3975 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
3976 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3977 ok(!elfrag2, "elfrag2 != NULL\n");
3978 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3979 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
3980 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
3981 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
3982 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
3983 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
3984 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
3985 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
3986 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
3987 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
3988 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
3989 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
3990 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
3991 acc_client = NULL;
3993 /* No check against root IAccessible, since it was done previously. */
3994 elprov2 = (void *)0xdeadbeef;
3995 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3996 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3997 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
3998 IRawElementProviderSimple_Release(elprov2);
4000 /* Do nothing. */
4001 elfrag2 = (void *)0xdeadbeef;
4002 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4003 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4004 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4005 ok(!elfrag2, "elfrag2 != NULL\n");
4007 elfrag2 = (void *)0xdeadbeef;
4008 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4009 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4010 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4011 ok(!elfrag2, "elfrag2 != NULL\n");
4013 elfrag2 = (void *)0xdeadbeef;
4014 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
4015 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4016 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4017 ok(!elfrag2, "elfrag2 != NULL\n");
4020 * Retrieve childid 2 (Accessible_child) as first child. childid 1 is skipped due to
4021 * having a state of STATE_SYSTEM_INVISIBLE.
4023 set_accessible_props(&Accessible_child, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4024 set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4025 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 3);
4026 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 2);
4027 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4028 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
4029 SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
4030 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4031 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4032 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4033 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4034 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4035 ok(!!elfrag2, "elfrag2 == NULL\n");
4036 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 3);
4037 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 2);
4038 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
4039 CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
4040 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4042 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4043 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4044 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4045 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4046 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_NextSibling, &elfrag3);
4047 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
4048 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4049 ok(!!elfrag3, "elfrag2 == NULL\n");
4050 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4051 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4052 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4053 check_fragment_acc(elfrag3, &Accessible.IAccessible_iface, 3);
4055 IRawElementProviderFragment_Release(elfrag3);
4056 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4057 IRawElementProviderFragment_Release(elfrag2);
4058 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4059 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4061 /* Retrieve childid 3 as first child now that Accessible_child is invisible. */
4062 set_accessible_props(&Accessible_child, 0, STATE_SYSTEM_INVISIBLE, 0, NULL, 0, 0, 0, 0);
4063 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 4);
4064 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 3);
4065 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accState, 2);
4066 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
4067 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4068 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4069 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4070 ok(!!elfrag2, "elfrag2 == NULL\n");
4071 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 4);
4072 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 3);
4073 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accState, 2);
4074 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
4075 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
4076 IRawElementProviderFragment_Release(elfrag2);
4077 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4079 /* Retrieve childid 4 (Accessible_child2) as last child. */
4080 set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4081 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 2);
4082 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4083 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accState);
4084 SET_ACC_METHOD_EXPECT(&Accessible_child2, accNavigate);
4085 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accParent);
4086 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4087 ok(Accessible_child2.ref == 2, "Unexpected refcnt %ld\n", Accessible_child2.ref);
4088 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4089 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4090 ok(!!elfrag2, "elfrag2 == NULL\n");
4091 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 2);
4092 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4093 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accState);
4094 CHECK_ACC_METHOD_CALLED(&Accessible_child2, accNavigate);
4095 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accParent);
4097 check_fragment_acc(elfrag2, &Accessible_child2.IAccessible_iface, CHILDID_SELF);
4098 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4099 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4100 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4101 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_PreviousSibling, &elfrag3);
4102 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
4103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4104 ok(!!elfrag3, "elfrag2 == NULL\n");
4105 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4106 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4107 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4108 check_fragment_acc(elfrag3, &Accessible.IAccessible_iface, 3);
4110 IRawElementProviderFragment_Release(elfrag3);
4111 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4112 IRawElementProviderFragment_Release(elfrag2);
4113 ok(Accessible_child2.ref == 1, "Unexpected refcnt %ld\n", Accessible_child2.ref);
4114 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4116 /* Retrieve childid 3 as last child, now that Accessible_child2 is STATE_SYSTEM_INVISIBLE. */
4117 set_accessible_props(&Accessible_child2, 0, STATE_SYSTEM_INVISIBLE, 0, NULL, 0, 0, 0, 0);
4118 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 3);
4119 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 2);
4120 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4121 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accState);
4122 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4123 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4125 ok(!!elfrag2, "elfrag2 == NULL\n");
4126 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 3);
4127 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 2);
4128 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4129 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accState);
4130 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
4131 IRawElementProviderFragment_Release(elfrag2);
4132 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4134 IRawElementProviderFragment_Release(elfrag);
4135 IRawElementProviderSimple_Release(elprov);
4136 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4139 * Full IAccessible child tests.
4141 SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
4142 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4143 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, 0, UIA_PFIA_DEFAULT, &elprov);
4144 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4145 CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
4146 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4147 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4149 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4151 ok(!!elfrag, "elfrag == NULL\n");
4154 * After determining this isn't the root IAccessible, get_accParent will
4155 * be used to get the parent.
4157 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4158 set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4159 acc_client = &Accessible2.IAccessible_iface;
4160 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4161 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accRole);
4162 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4163 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4164 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4165 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4166 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4167 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4169 ok(!!elfrag2, "elfrag2 == NULL\n");
4170 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4171 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accRole);
4172 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4173 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
4174 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
4175 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4176 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
4177 IRawElementProviderFragment_Release(elfrag2);
4178 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4179 acc_client = NULL;
4181 /* Second call only does get_accParent, no root check. */
4182 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4183 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4184 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4186 ok(!!elfrag2, "elfrag2 == NULL\n");
4187 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4188 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
4189 IRawElementProviderFragment_Release(elfrag2);
4190 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4192 /* ChildCount of 0, do nothing for First/Last child.*/
4193 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4194 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4195 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4196 ok(!elfrag2, "elfrag2 != NULL\n");
4197 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4199 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4200 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4201 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4202 ok(!elfrag2, "elfrag2 != NULL\n");
4203 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4206 * In the case of sibling navigation on an IAccessible that wasn't
4207 * received through previous navigation from a parent (i.e, from
4208 * NavigateDirection_First/LastChild), we have to figure out which
4209 * IAccessible child we represent by comparing against all children of our
4210 * IAccessible parent. If we find more than one IAccessible that matches,
4211 * or none at all that do, navigation will fail.
4213 set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 1,
4214 L"acc_child", 0, 0, 50, 50);
4215 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 1,
4216 L"acc_child", 0, 0, 50, 50);
4217 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 5);
4218 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 4);
4219 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4220 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accRole);
4221 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
4222 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4223 SET_ACC_METHOD_EXPECT(&Accessible_child, accLocation);
4224 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accName);
4225 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accRole);
4226 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accState);
4227 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accChildCount);
4228 SET_ACC_METHOD_EXPECT(&Accessible_child2, accLocation);
4229 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accName);
4230 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4231 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4232 ok(!elfrag2, "elfrag2 != NULL\n");
4233 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 5);
4234 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 4);
4235 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4236 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accRole);
4237 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
4238 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4239 CHECK_ACC_METHOD_CALLED(&Accessible_child, accLocation);
4240 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accName);
4241 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accRole);
4242 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accState);
4243 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accChildCount);
4244 CHECK_ACC_METHOD_CALLED(&Accessible_child2, accLocation);
4245 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accName);
4247 /* Now they have a role mismatch, we can determine our position. */
4248 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
4249 L"acc_child", 0, 0, 50, 50);
4250 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 6);
4251 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 5);
4252 /* Check ChildID 1 for STATE_SYSTEM_INVISIBLE. */
4253 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4254 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4255 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accRole);
4256 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accRole);
4257 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
4259 * Even though we didn't get a new fragment, now that we know our
4260 * position, a reference is added to the parent IAccessible.
4262 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4263 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4264 ok(!elfrag2, "elfrag2 != NULL\n");
4265 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 6);
4266 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 5);
4267 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4268 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4269 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accRole);
4270 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accRole);
4272 /* Now that we know our position, no extra nav work. */
4273 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4274 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4275 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4276 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4277 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4278 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4279 ok(!!elfrag2, "elfrag2 == NULL\n");
4280 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4281 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4282 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4283 if (elfrag2)
4285 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, 3);
4286 IRawElementProviderFragment_Release(elfrag2);
4287 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4290 IRawElementProviderFragment_Release(elfrag);
4291 IRawElementProviderSimple_Release(elprov);
4292 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4293 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4296 * Simple element child tests.
4298 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
4299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4300 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4302 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4303 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4304 ok(!!elfrag, "elfrag == NULL\n");
4307 * Simple child elements don't check the root IAccessible, because they
4308 * can't be the root IAccessible.
4310 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4311 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4312 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4313 ok(!!elfrag2, "elfrag2 == NULL\n");
4314 check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF);
4315 IRawElementProviderFragment_Release(elfrag2);
4316 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4319 * Test NavigateDirection_First/LastChild on simple child element. Does
4320 * nothing, as simple children cannot have children.
4322 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4323 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4324 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4325 ok(!elfrag2, "elfrag2 != NULL\n");
4327 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4328 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4329 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4330 ok(!elfrag2, "elfrag2 != NULL\n");
4333 * NavigateDirection_Next/PreviousSibling behaves normally, no IAccessible
4334 * comparisons.
4336 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4337 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4338 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
4339 SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
4340 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4341 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4342 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4343 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4344 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4345 ok(!!elfrag2, "elfrag2 == NULL\n");
4346 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4347 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4348 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
4349 CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
4350 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4351 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4353 IRawElementProviderFragment_Release(elfrag2);
4354 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4355 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4356 IRawElementProviderFragment_Release(elfrag);
4357 IRawElementProviderSimple_Release(elprov);
4358 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4360 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
4361 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
4362 set_accessible_props(&Accessible_child, 0, 0, 0, NULL, 0, 0, 0, 0);
4363 set_accessible_props(&Accessible_child2, 0, 0, 0, NULL, 0, 0, 0, 0);
4366 static void test_uia_prov_from_acc_properties(void)
4368 IRawElementProviderSimple *elprov;
4369 RECT rect[2] = { 0 };
4370 HRESULT hr;
4371 VARIANT v;
4372 int i, x;
4374 /* MSAA role to UIA control type test. */
4375 VariantInit(&v);
4376 for (i = 0; i < ARRAY_SIZE(msaa_role_uia_types); i++)
4378 const struct msaa_role_uia_type *role = &msaa_role_uia_types[i];
4379 ILegacyIAccessibleProvider *accprov;
4380 DWORD role_val;
4381 IUnknown *unk;
4384 * Roles get cached once a valid one is mapped, so create a new
4385 * element for each role.
4387 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4388 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4389 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4391 Accessible.role = role->acc_role;
4392 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4393 VariantClear(&v);
4394 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
4395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4396 if (role->uia_control_type)
4397 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
4398 else
4399 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
4400 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4402 if (!role->uia_control_type)
4403 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4404 VariantClear(&v);
4405 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
4406 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4407 if (role->uia_control_type)
4408 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
4409 else
4410 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
4411 if (!role->uia_control_type)
4412 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4414 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
4415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4416 ok(!!unk, "unk == NULL\n");
4418 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
4419 IUnknown_Release(unk);
4420 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4421 ok(!!accprov, "accprov == NULL\n");
4423 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4424 hr = ILegacyIAccessibleProvider_get_Role(accprov, &role_val);
4425 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4426 ok(role_val == Accessible.role, "role_val != Accessible.role\n");
4427 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4429 ILegacyIAccessibleProvider_Release(accprov);
4430 IRawElementProviderSimple_Release(elprov);
4431 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4434 /* ROLE_SYSTEM_CLOCK has no mapping in Windows < 10 1809. */
4435 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4437 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4439 Accessible.role = ROLE_SYSTEM_CLOCK;
4440 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4441 VariantClear(&v);
4442 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
4443 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4444 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
4445 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
4446 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4448 if (V_VT(&v) == VT_EMPTY)
4449 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4450 VariantClear(&v);
4451 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
4452 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
4453 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
4454 if (V_VT(&v) == VT_EMPTY)
4455 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4457 Accessible.role = 0;
4458 IRawElementProviderSimple_Release(elprov);
4459 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4461 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4462 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4463 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4465 /* UIA PropertyId's that correspond directly to individual MSAA state flags. */
4466 for (i = 0; i < ARRAY_SIZE(msaa_state_uia_props); i++)
4468 const struct msaa_state_uia_prop *state = &msaa_state_uia_props[i];
4470 for (x = 0; x < 2; x++)
4472 Accessible.state = x ? state->acc_state : ~state->acc_state;
4473 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4474 hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v);
4475 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4476 ok(check_variant_bool(&v, x), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
4477 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4480 Accessible.state = 0;
4483 * UIA_IsOffscreenPropertyId relies upon either STATE_SYSTEM_OFFSCREEN
4484 * being set, or accLocation returning a location that is within the
4485 * client area bounding box of the HWND it is contained within.
4487 set_accessible_props(&Accessible, 0, STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0);
4488 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4489 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
4490 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4491 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
4492 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
4493 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4495 /* accLocation fails, will return FALSE. */
4496 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0);
4497 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4498 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4499 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
4500 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4501 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
4502 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
4503 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4504 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4506 /* Window is visible, Accessible is within its bounds. */
4507 ShowWindow(Accessible.ow_hwnd, SW_SHOW);
4508 ok(GetClientRect(Accessible.ow_hwnd, &rect[0]), "GetClientRect returned FALSE\n");
4509 MapWindowPoints(Accessible.ow_hwnd, NULL, (POINT *)&rect[0], 2);
4511 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[0].left, rect[0].top,
4512 (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top));
4513 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4514 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4515 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
4516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4517 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
4518 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
4519 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4520 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4523 * Window is invisible, Accessible is within its bounds. Window visibility
4524 * doesn't effect whether or not an IAccessible is considered offscreen.
4526 ShowWindow(Accessible.ow_hwnd, SW_HIDE);
4527 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[0].left, rect[0].top,
4528 (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top));
4529 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4530 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4531 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
4532 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4533 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
4534 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
4535 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4536 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4538 /* Accessible now outside of its window's bounds. */
4539 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[0].right, rect[0].bottom,
4540 10, 10);
4541 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4542 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4543 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
4544 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4545 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
4546 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
4547 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4548 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4550 /* Accessible within window bounds, but not client area bounds. */
4551 ok(GetWindowRect(Accessible.ow_hwnd, &rect[1]), "GetWindowRect returned FALSE\n");
4552 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", rect[1].left, rect[1].top,
4553 (rect[0].left - rect[1].left) - 1, (rect[0].top - rect[1].top) - 1);
4555 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4556 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4557 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
4558 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4559 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
4560 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
4561 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4562 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4564 IRawElementProviderSimple_Release(elprov);
4565 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4567 /* UIA_NamePropertyId tests. */
4568 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible", 0, 0, 0, 0);
4569 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4570 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4571 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4573 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4574 VariantInit(&v);
4575 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
4576 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4577 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
4578 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
4579 VariantClear(&v);
4580 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4582 /* Name is not cached. */
4583 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible2", 0, 0, 0, 0);
4584 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4585 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
4586 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4587 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
4588 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
4589 VariantClear(&v);
4590 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4592 IRawElementProviderSimple_Release(elprov);
4593 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4596 static void test_UiaProviderFromIAccessible(void)
4598 ILegacyIAccessibleProvider *accprov;
4599 IRawElementProviderSimple *elprov, *elprov2;
4600 IRawElementProviderFragment *elfrag;
4601 enum ProviderOptions prov_opt;
4602 struct UiaRect rect;
4603 IAccessible *acc;
4604 IUnknown *unk;
4605 WNDCLASSA cls;
4606 HRESULT hr;
4607 HWND hwnd;
4608 VARIANT v;
4609 INT cid;
4611 CoInitializeEx(NULL, COINIT_MULTITHREADED);
4612 cls.style = 0;
4613 cls.lpfnWndProc = test_wnd_proc;
4614 cls.cbClsExtra = 0;
4615 cls.cbWndExtra = 0;
4616 cls.hInstance = GetModuleHandleA(NULL);
4617 cls.hIcon = 0;
4618 cls.hCursor = NULL;
4619 cls.hbrBackground = NULL;
4620 cls.lpszMenuName = NULL;
4621 cls.lpszClassName = "UiaProviderFromIAccessible class";
4623 RegisterClassA(&cls);
4625 hwnd = CreateWindowA("UiaProviderFromIAccessible class", "Test window", WS_OVERLAPPEDWINDOW,
4626 0, 0, 100, 100, NULL, NULL, NULL, NULL);
4628 hr = pUiaProviderFromIAccessible(NULL, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4629 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4631 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, NULL);
4632 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
4635 * UiaProviderFromIAccessible will not wrap an MSAA proxy, this is
4636 * detected by checking for the 'IIS_IsOleaccProxy' service from the
4637 * IServiceProvider interface.
4639 hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
4640 ok(hr == S_OK, "got %#lx\n", hr);
4641 ok(!!acc, "acc == NULL\n");
4643 hr = pUiaProviderFromIAccessible(acc, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4644 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
4645 IAccessible_Release(acc);
4647 /* Don't return an HWND from accNavigate or OleWindow. */
4648 SET_ACC_METHOD_EXPECT(&Accessible, accNavigate);
4649 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent);
4650 Accessible.acc_hwnd = NULL;
4651 Accessible.ow_hwnd = NULL;
4652 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4653 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
4654 CHECK_ACC_METHOD_CALLED(&Accessible, accNavigate);
4655 CHECK_ACC_METHOD_CALLED(&Accessible, get_accParent);
4657 /* Return an HWND from accNavigate, not OleWindow. */
4658 SET_ACC_METHOD_EXPECT(&Accessible, accNavigate);
4659 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4660 acc_client = &Accessible.IAccessible_iface;
4661 Accessible.acc_hwnd = hwnd;
4662 Accessible.ow_hwnd = NULL;
4663 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4664 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4665 CHECK_ACC_METHOD_CALLED(&Accessible, accNavigate);
4666 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4667 IRawElementProviderSimple_Release(elprov);
4668 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4669 acc_client = NULL;
4671 /* Skip tests on Win10v1507. */
4672 if (called_winproc_GETOBJECT_CLIENT)
4674 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
4675 return;
4677 expect_winproc_GETOBJECT_CLIENT = FALSE;
4679 /* Return an HWND from parent IAccessible's IOleWindow interface. */
4680 SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
4681 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4682 Accessible.acc_hwnd = NULL;
4683 Accessible.ow_hwnd = hwnd;
4684 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4685 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4686 CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
4687 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
4688 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4689 IRawElementProviderSimple_Release(elprov);
4690 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4692 /* Return an HWND from OleWindow, not accNavigate. */
4693 Accessible.acc_hwnd = NULL;
4694 Accessible.ow_hwnd = hwnd;
4695 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4697 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4699 hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opt);
4700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4701 ok((prov_opt == (ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading)) ||
4702 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
4703 "Unexpected provider options %#x\n", prov_opt);
4705 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
4707 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ProviderDescriptionPropertyId, &v);
4708 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4709 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
4710 VariantClear(&v);
4712 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
4713 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4714 ok(!!unk, "unk == NULL\n");
4715 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
4717 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
4718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4719 ok(!!accprov, "accprov == NULL\n");
4721 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
4722 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4723 ok(cid == CHILDID_SELF, "cid != CHILDID_SELF\n");
4725 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
4726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4727 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
4728 IAccessible_Release(acc);
4729 IUnknown_Release(unk);
4730 ILegacyIAccessibleProvider_Release(accprov);
4732 IRawElementProviderSimple_Release(elprov);
4733 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4735 /* ChildID other than CHILDID_SELF. */
4736 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
4737 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4738 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4740 /* Even simple children implement IRawElementProviderFragmentRoot. */
4741 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
4744 * Simple child element (IAccessible without CHILDID_SELF) cannot be root
4745 * IAccessible. No checks against the root HWND IAccessible will be done.
4747 elprov2 = (void *)0xdeadbeef;
4748 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4750 ok(!elprov2, "elprov != NULL\n");
4752 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
4753 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4754 ok(!!unk, "unk == NULL\n");
4755 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
4757 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
4758 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4759 ok(!!accprov, "accprov == NULL\n");
4761 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
4762 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4763 ok(cid == 1, "cid != CHILDID_SELF\n");
4765 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
4766 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4767 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
4768 IAccessible_Release(acc);
4769 IUnknown_Release(unk);
4770 ILegacyIAccessibleProvider_Release(accprov);
4772 IRawElementProviderSimple_Release(elprov);
4773 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4776 * &Accessible.IAccessible_iface will be compared against the default
4777 * client accessible object. Since we have all properties set to 0,
4778 * we return failure HRESULTs and all properties will get queried but not
4779 * compared.
4781 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4782 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4783 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4785 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4786 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4787 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4788 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4789 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4790 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4791 elprov2 = (void *)0xdeadbeef;
4792 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4793 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4794 ok(!elprov2, "elprov != NULL\n");
4795 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4796 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4797 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4798 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4799 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4800 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4803 * Interface that isn't the HWND root, still implements
4804 * IRawElementProviderFragmentRoot.
4806 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
4808 /* Second call won't send WM_GETOBJECT. */
4809 elprov2 = (void *)0xdeadbeef;
4810 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4811 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4812 ok(!elprov2, "elprov != NULL\n");
4814 IRawElementProviderSimple_Release(elprov);
4815 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4818 * Return &Accessible.IAccessible_iface in response to OBJID_CLIENT,
4819 * interface pointers will be compared, no method calls to check property
4820 * values.
4822 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4823 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4824 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4826 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4827 elprov2 = (void *)0xdeadbeef;
4828 acc_client = &Accessible.IAccessible_iface;
4829 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4830 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4831 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4832 IRawElementProviderSimple_Release(elprov2);
4833 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4835 /* Second call, no checks. */
4836 elprov2 = (void *)0xdeadbeef;
4837 acc_client = NULL;
4838 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4840 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4841 IRawElementProviderSimple_Release(elprov2);
4843 IRawElementProviderSimple_Release(elprov);
4844 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4847 * Return &Accessible2.IAccessible_iface in response to OBJID_CLIENT,
4848 * interface pointers won't match, so properties will be compared.
4850 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4851 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4852 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4854 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
4855 L"acc_name", 0, 0, 50, 50);
4856 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
4857 L"acc_name", 0, 0, 50, 50);
4859 acc_client = &Accessible2.IAccessible_iface;
4860 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4861 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4862 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4863 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4864 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4865 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4866 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4867 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
4868 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
4869 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
4870 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
4872 * The IAccessible returned by WM_GETOBJECT will be checked for an
4873 * IAccIdentity interface to see if Dynamic Annotation properties should
4874 * be queried. If not present on the current IAccessible, it will check
4875 * the parent IAccessible for one.
4877 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4878 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4879 elprov2 = (void *)0xdeadbeef;
4880 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4881 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4882 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4883 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4884 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4885 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4886 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4887 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4888 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4889 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4890 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4891 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
4892 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
4893 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
4894 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
4895 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
4896 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
4897 IRawElementProviderSimple_Release(elprov2);
4899 elprov2 = (void *)0xdeadbeef;
4900 acc_client = NULL;
4901 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4903 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4904 IRawElementProviderSimple_Release(elprov2);
4906 IRawElementProviderSimple_Release(elprov);
4907 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4910 * If a failure HRESULT is returned from the IRawElementProviderSimple
4911 * IAccessible, the corresponding AOFW IAccessible method isn't called.
4912 * An exception is get_accChildCount, which is always called, but only
4913 * checked if the HRESULT return value is not a failure. If Role/State/Name
4914 * are not queried, no IAccIdentity check is done.
4916 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4917 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4918 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4920 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
4921 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
4922 L"acc_name", 0, 0, 50, 50);
4924 acc_client = &Accessible2.IAccessible_iface;
4925 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4926 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4927 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4928 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4929 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
4930 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4931 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4932 elprov2 = (void *)0xdeadbeef;
4933 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4934 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4935 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4936 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4937 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4938 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4939 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4940 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
4941 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4942 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4944 acc_client = NULL;
4945 elprov2 = (void *)0xdeadbeef;
4946 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4947 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4948 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4950 IRawElementProviderSimple_Release(elprov);
4951 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4954 * Properties are checked in a sequence of accRole, accState,
4955 * accChildCount, accLocation, and finally accName. If a mismatch is found
4956 * early in the sequence, the rest aren't checked.
4958 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4959 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4960 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4962 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4963 set_accessible_props(&Accessible2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4965 acc_client = &Accessible2.IAccessible_iface;
4966 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4967 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4968 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4969 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4970 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4971 elprov2 = (void *)0xdeadbeef;
4972 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4974 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4975 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4976 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4977 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4978 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
4979 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
4981 elprov2 = (void *)0xdeadbeef;
4982 acc_client = NULL;
4983 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4985 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4987 IRawElementProviderSimple_Release(elprov);
4988 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4990 /* 4/5 properties match, considered a match. */
4991 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4992 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4993 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4995 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
4996 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
4998 acc_client = &Accessible2.IAccessible_iface;
4999 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5000 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5001 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5002 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5003 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5004 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5005 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5006 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5007 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5008 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
5009 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5010 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5011 elprov2 = (void *)0xdeadbeef;
5012 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5013 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5014 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5015 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5016 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5017 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5018 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5019 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5020 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5021 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5022 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5023 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5024 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5025 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
5026 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
5027 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
5028 IRawElementProviderSimple_Release(elprov2);
5030 elprov2 = (void *)0xdeadbeef;
5031 acc_client = NULL;
5032 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5033 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5034 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5035 IRawElementProviderSimple_Release(elprov2);
5037 IRawElementProviderSimple_Release(elprov);
5038 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5040 /* 3/5 properties match, not considered a match. */
5041 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5043 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5045 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
5046 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
5048 acc_client = &Accessible2.IAccessible_iface;
5049 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5050 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5051 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5052 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5053 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5054 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5055 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5056 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5057 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5058 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5059 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5060 elprov2 = (void *)0xdeadbeef;
5061 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5063 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5064 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5065 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5066 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5067 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5068 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5069 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5070 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5071 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5072 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5073 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
5074 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
5076 elprov2 = (void *)0xdeadbeef;
5077 acc_client = NULL;
5078 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5079 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5080 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5082 IRawElementProviderSimple_Release(elprov);
5083 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5085 /* Only name matches, considered a match. */
5086 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5087 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5088 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5090 set_accessible_props(&Accessible, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
5091 set_accessible_props(&Accessible2, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
5093 acc_client = &Accessible2.IAccessible_iface;
5094 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5095 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5096 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5097 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5098 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5099 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5100 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5101 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
5102 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5103 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5104 elprov2 = (void *)0xdeadbeef;
5105 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5107 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5108 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5109 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5110 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5111 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5112 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5113 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5114 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5115 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5116 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
5117 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
5118 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
5119 IRawElementProviderSimple_Release(elprov2);
5121 elprov2 = (void *)0xdeadbeef;
5122 acc_client = NULL;
5123 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5125 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5126 IRawElementProviderSimple_Release(elprov2);
5128 IRawElementProviderSimple_Release(elprov);
5129 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5132 * Test IRawElementProviderFragment_get_BoundingRectangle.
5134 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, L"acc_name", 25, 25, 50, 50);
5135 /* Test the case where Accessible is not the root for its HWND. */
5136 acc_client = NULL;
5137 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5138 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5139 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5141 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
5142 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5143 ok(!!elfrag, "elfrag == NULL\n");
5145 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5146 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5147 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5148 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5149 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5151 ok(rect.left == (double)Accessible.left, "Unexpected left value %f\n", rect.left);
5152 ok(rect.top == (double)Accessible.top, "Unexpected top value %f\n", rect.top);
5153 ok(rect.width == (double)Accessible.width, "Unexpected width value %f\n", rect.width);
5154 ok(rect.height == (double)Accessible.height, "Unexpected height value %f\n", rect.height);
5155 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5156 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5157 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5158 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5160 /* If Accessible has STATE_SYSTEM_OFFSCREEN, it will return an empty rect. */
5161 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_OFFSCREEN, 0, L"acc_name", 0, 0, 50, 50);
5162 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5163 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5164 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5165 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5166 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5167 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5168 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5169 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5171 IRawElementProviderFragment_Release(elfrag);
5172 IRawElementProviderSimple_Release(elprov);
5173 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5175 /* Test case where accessible is the root accessible. */
5176 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
5177 acc_client = &Accessible.IAccessible_iface;
5178 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5179 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5180 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5182 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
5183 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5184 ok(!!elfrag, "elfrag == NULL\n");
5186 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5187 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5188 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5189 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5190 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5191 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5192 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5193 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5195 /* Second call does nothing. */
5196 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5197 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5198 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5199 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5200 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5201 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5203 IRawElementProviderFragment_Release(elfrag);
5204 IRawElementProviderSimple_Release(elprov);
5205 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5206 acc_client = NULL;
5208 test_uia_prov_from_acc_properties();
5209 test_uia_prov_from_acc_navigation();
5210 test_uia_prov_from_acc_ia2();
5211 test_uia_prov_from_acc_fragment_root(hwnd);
5213 CoUninitialize();
5214 DestroyWindow(hwnd);
5215 UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
5216 Accessible.acc_hwnd = NULL;
5217 Accessible.ow_hwnd = NULL;
5220 struct uia_lookup_id {
5221 const GUID *guid;
5222 int id;
5225 static const struct uia_lookup_id uia_property_lookup_ids[] = {
5226 { &RuntimeId_Property_GUID, UIA_RuntimeIdPropertyId },
5227 { &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId },
5228 { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId },
5229 { &ControlType_Property_GUID, UIA_ControlTypePropertyId },
5230 { &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId },
5231 { &Name_Property_GUID, UIA_NamePropertyId },
5232 { &AcceleratorKey_Property_GUID, UIA_AcceleratorKeyPropertyId },
5233 { &AccessKey_Property_GUID, UIA_AccessKeyPropertyId },
5234 { &HasKeyboardFocus_Property_GUID, UIA_HasKeyboardFocusPropertyId },
5235 { &IsKeyboardFocusable_Property_GUID, UIA_IsKeyboardFocusablePropertyId },
5236 { &IsEnabled_Property_GUID, UIA_IsEnabledPropertyId },
5237 { &AutomationId_Property_GUID, UIA_AutomationIdPropertyId },
5238 { &ClassName_Property_GUID, UIA_ClassNamePropertyId },
5239 { &HelpText_Property_GUID, UIA_HelpTextPropertyId },
5240 { &ClickablePoint_Property_GUID, UIA_ClickablePointPropertyId },
5241 { &Culture_Property_GUID, UIA_CulturePropertyId },
5242 { &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId },
5243 { &IsContentElement_Property_GUID, UIA_IsContentElementPropertyId },
5244 { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId },
5245 { &IsPassword_Property_GUID, UIA_IsPasswordPropertyId },
5246 { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId },
5247 { &ItemType_Property_GUID, UIA_ItemTypePropertyId },
5248 { &IsOffscreen_Property_GUID, UIA_IsOffscreenPropertyId },
5249 { &Orientation_Property_GUID, UIA_OrientationPropertyId },
5250 { &FrameworkId_Property_GUID, UIA_FrameworkIdPropertyId },
5251 { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId },
5252 { &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId },
5253 { &IsDockPatternAvailable_Property_GUID, UIA_IsDockPatternAvailablePropertyId },
5254 { &IsExpandCollapsePatternAvailable_Property_GUID, UIA_IsExpandCollapsePatternAvailablePropertyId },
5255 { &IsGridItemPatternAvailable_Property_GUID, UIA_IsGridItemPatternAvailablePropertyId },
5256 { &IsGridPatternAvailable_Property_GUID, UIA_IsGridPatternAvailablePropertyId },
5257 { &IsInvokePatternAvailable_Property_GUID, UIA_IsInvokePatternAvailablePropertyId },
5258 { &IsMultipleViewPatternAvailable_Property_GUID, UIA_IsMultipleViewPatternAvailablePropertyId },
5259 { &IsRangeValuePatternAvailable_Property_GUID, UIA_IsRangeValuePatternAvailablePropertyId },
5260 { &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId },
5261 { &IsScrollItemPatternAvailable_Property_GUID, UIA_IsScrollItemPatternAvailablePropertyId },
5262 { &IsSelectionItemPatternAvailable_Property_GUID, UIA_IsSelectionItemPatternAvailablePropertyId },
5263 { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId },
5264 { &IsTablePatternAvailable_Property_GUID, UIA_IsTablePatternAvailablePropertyId },
5265 { &IsTableItemPatternAvailable_Property_GUID, UIA_IsTableItemPatternAvailablePropertyId },
5266 { &IsTextPatternAvailable_Property_GUID, UIA_IsTextPatternAvailablePropertyId },
5267 { &IsTogglePatternAvailable_Property_GUID, UIA_IsTogglePatternAvailablePropertyId },
5268 { &IsTransformPatternAvailable_Property_GUID, UIA_IsTransformPatternAvailablePropertyId },
5269 { &IsValuePatternAvailable_Property_GUID, UIA_IsValuePatternAvailablePropertyId },
5270 { &IsWindowPatternAvailable_Property_GUID, UIA_IsWindowPatternAvailablePropertyId },
5271 { &Value_Value_Property_GUID, UIA_ValueValuePropertyId },
5272 { &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId },
5273 { &RangeValue_Value_Property_GUID, UIA_RangeValueValuePropertyId },
5274 { &RangeValue_IsReadOnly_Property_GUID, UIA_RangeValueIsReadOnlyPropertyId },
5275 { &RangeValue_Minimum_Property_GUID, UIA_RangeValueMinimumPropertyId },
5276 { &RangeValue_Maximum_Property_GUID, UIA_RangeValueMaximumPropertyId },
5277 { &RangeValue_LargeChange_Property_GUID, UIA_RangeValueLargeChangePropertyId },
5278 { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId },
5279 { &Scroll_HorizontalScrollPercent_Property_GUID, UIA_ScrollHorizontalScrollPercentPropertyId },
5280 { &Scroll_HorizontalViewSize_Property_GUID, UIA_ScrollHorizontalViewSizePropertyId },
5281 { &Scroll_VerticalScrollPercent_Property_GUID, UIA_ScrollVerticalScrollPercentPropertyId },
5282 { &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId },
5283 { &Scroll_HorizontallyScrollable_Property_GUID, UIA_ScrollHorizontallyScrollablePropertyId },
5284 { &Scroll_VerticallyScrollable_Property_GUID, UIA_ScrollVerticallyScrollablePropertyId },
5285 { &Selection_Selection_Property_GUID, UIA_SelectionSelectionPropertyId },
5286 { &Selection_CanSelectMultiple_Property_GUID, UIA_SelectionCanSelectMultiplePropertyId },
5287 { &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId },
5288 { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId },
5289 { &Grid_ColumnCount_Property_GUID, UIA_GridColumnCountPropertyId },
5290 { &GridItem_Row_Property_GUID, UIA_GridItemRowPropertyId },
5291 { &GridItem_Column_Property_GUID, UIA_GridItemColumnPropertyId },
5292 { &GridItem_RowSpan_Property_GUID, UIA_GridItemRowSpanPropertyId },
5293 { &GridItem_ColumnSpan_Property_GUID, UIA_GridItemColumnSpanPropertyId },
5294 { &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId },
5295 { &Dock_DockPosition_Property_GUID, UIA_DockDockPositionPropertyId },
5296 { &ExpandCollapse_ExpandCollapseState_Property_GUID, UIA_ExpandCollapseExpandCollapseStatePropertyId },
5297 { &MultipleView_CurrentView_Property_GUID, UIA_MultipleViewCurrentViewPropertyId },
5298 { &MultipleView_SupportedViews_Property_GUID, UIA_MultipleViewSupportedViewsPropertyId },
5299 { &Window_CanMaximize_Property_GUID, UIA_WindowCanMaximizePropertyId },
5300 { &Window_CanMinimize_Property_GUID, UIA_WindowCanMinimizePropertyId },
5301 { &Window_WindowVisualState_Property_GUID, UIA_WindowWindowVisualStatePropertyId },
5302 { &Window_WindowInteractionState_Property_GUID, UIA_WindowWindowInteractionStatePropertyId },
5303 { &Window_IsModal_Property_GUID, UIA_WindowIsModalPropertyId },
5304 { &Window_IsTopmost_Property_GUID, UIA_WindowIsTopmostPropertyId },
5305 { &SelectionItem_IsSelected_Property_GUID, UIA_SelectionItemIsSelectedPropertyId },
5306 { &SelectionItem_SelectionContainer_Property_GUID, UIA_SelectionItemSelectionContainerPropertyId },
5307 { &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId },
5308 { &Table_ColumnHeaders_Property_GUID, UIA_TableColumnHeadersPropertyId },
5309 { &Table_RowOrColumnMajor_Property_GUID, UIA_TableRowOrColumnMajorPropertyId },
5310 { &TableItem_RowHeaderItems_Property_GUID, UIA_TableItemRowHeaderItemsPropertyId },
5311 { &TableItem_ColumnHeaderItems_Property_GUID, UIA_TableItemColumnHeaderItemsPropertyId },
5312 { &Toggle_ToggleState_Property_GUID, UIA_ToggleToggleStatePropertyId },
5313 { &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId },
5314 { &Transform_CanResize_Property_GUID, UIA_TransformCanResizePropertyId },
5315 { &Transform_CanRotate_Property_GUID, UIA_TransformCanRotatePropertyId },
5316 { &IsLegacyIAccessiblePatternAvailable_Property_GUID, UIA_IsLegacyIAccessiblePatternAvailablePropertyId },
5317 { &LegacyIAccessible_ChildId_Property_GUID, UIA_LegacyIAccessibleChildIdPropertyId },
5318 { &LegacyIAccessible_Name_Property_GUID, UIA_LegacyIAccessibleNamePropertyId },
5319 { &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId },
5320 { &LegacyIAccessible_Description_Property_GUID, UIA_LegacyIAccessibleDescriptionPropertyId },
5321 { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId },
5322 { &LegacyIAccessible_State_Property_GUID, UIA_LegacyIAccessibleStatePropertyId },
5323 { &LegacyIAccessible_Help_Property_GUID, UIA_LegacyIAccessibleHelpPropertyId },
5324 { &LegacyIAccessible_KeyboardShortcut_Property_GUID, UIA_LegacyIAccessibleKeyboardShortcutPropertyId },
5325 { &LegacyIAccessible_Selection_Property_GUID, UIA_LegacyIAccessibleSelectionPropertyId },
5326 { &LegacyIAccessible_DefaultAction_Property_GUID, UIA_LegacyIAccessibleDefaultActionPropertyId },
5327 { &AriaRole_Property_GUID, UIA_AriaRolePropertyId },
5328 { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId },
5329 { &IsDataValidForForm_Property_GUID, UIA_IsDataValidForFormPropertyId },
5330 { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId },
5331 { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId },
5332 { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId },
5333 { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId },
5334 { &IsItemContainerPatternAvailable_Property_GUID, UIA_IsItemContainerPatternAvailablePropertyId },
5335 { &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId },
5336 { &IsSynchronizedInputPatternAvailable_Property_GUID, UIA_IsSynchronizedInputPatternAvailablePropertyId },
5337 /* Implemented on Win8+ */
5338 { &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId },
5339 { &IsObjectModelPatternAvailable_Property_GUID, UIA_IsObjectModelPatternAvailablePropertyId },
5340 { &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId },
5341 { &Annotation_AnnotationTypeName_Property_GUID, UIA_AnnotationAnnotationTypeNamePropertyId },
5342 { &Annotation_Author_Property_GUID, UIA_AnnotationAuthorPropertyId },
5343 { &Annotation_DateTime_Property_GUID, UIA_AnnotationDateTimePropertyId },
5344 { &Annotation_Target_Property_GUID, UIA_AnnotationTargetPropertyId },
5345 { &IsAnnotationPatternAvailable_Property_GUID, UIA_IsAnnotationPatternAvailablePropertyId },
5346 { &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId },
5347 { &Styles_StyleId_Property_GUID, UIA_StylesStyleIdPropertyId },
5348 { &Styles_StyleName_Property_GUID, UIA_StylesStyleNamePropertyId },
5349 { &Styles_FillColor_Property_GUID, UIA_StylesFillColorPropertyId },
5350 { &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId },
5351 { &Styles_Shape_Property_GUID, UIA_StylesShapePropertyId },
5352 { &Styles_FillPatternColor_Property_GUID, UIA_StylesFillPatternColorPropertyId },
5353 { &Styles_ExtendedProperties_Property_GUID, UIA_StylesExtendedPropertiesPropertyId },
5354 { &IsStylesPatternAvailable_Property_GUID, UIA_IsStylesPatternAvailablePropertyId },
5355 { &IsSpreadsheetPatternAvailable_Property_GUID, UIA_IsSpreadsheetPatternAvailablePropertyId },
5356 { &SpreadsheetItem_Formula_Property_GUID, UIA_SpreadsheetItemFormulaPropertyId },
5357 { &SpreadsheetItem_AnnotationObjects_Property_GUID, UIA_SpreadsheetItemAnnotationObjectsPropertyId },
5358 { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId },
5359 { &IsSpreadsheetItemPatternAvailable_Property_GUID, UIA_IsSpreadsheetItemPatternAvailablePropertyId },
5360 { &Transform2_CanZoom_Property_GUID, UIA_Transform2CanZoomPropertyId },
5361 { &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId },
5362 { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId },
5363 { &IsTextChildPatternAvailable_Property_GUID, UIA_IsTextChildPatternAvailablePropertyId },
5364 { &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId },
5365 { &Drag_IsGrabbed_Property_GUID, UIA_DragIsGrabbedPropertyId },
5366 { &Drag_DropEffect_Property_GUID, UIA_DragDropEffectPropertyId },
5367 { &Drag_DropEffects_Property_GUID, UIA_DragDropEffectsPropertyId },
5368 { &IsDropTargetPatternAvailable_Property_GUID, UIA_IsDropTargetPatternAvailablePropertyId },
5369 { &DropTarget_DropTargetEffect_Property_GUID, UIA_DropTargetDropTargetEffectPropertyId },
5370 { &DropTarget_DropTargetEffects_Property_GUID, UIA_DropTargetDropTargetEffectsPropertyId },
5371 { &Drag_GrabbedItems_Property_GUID, UIA_DragGrabbedItemsPropertyId },
5372 { &Transform2_ZoomLevel_Property_GUID, UIA_Transform2ZoomLevelPropertyId },
5373 { &Transform2_ZoomMinimum_Property_GUID, UIA_Transform2ZoomMinimumPropertyId },
5374 { &Transform2_ZoomMaximum_Property_GUID, UIA_Transform2ZoomMaximumPropertyId },
5375 { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId },
5376 { &IsTextEditPatternAvailable_Property_GUID, UIA_IsTextEditPatternAvailablePropertyId },
5377 { &IsPeripheral_Property_GUID, UIA_IsPeripheralPropertyId },
5378 /* Implemented on Win10v1507+. */
5379 { &IsCustomNavigationPatternAvailable_Property_GUID, UIA_IsCustomNavigationPatternAvailablePropertyId },
5380 { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId },
5381 { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId },
5382 { &Level_Property_GUID, UIA_LevelPropertyId },
5383 { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId },
5384 { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId },
5385 /* Implemented on Win10v1809+. */
5386 { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId },
5387 { &LocalizedLandmarkType_Property_GUID, UIA_LocalizedLandmarkTypePropertyId },
5388 { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId },
5389 { &FillColor_Property_GUID, UIA_FillColorPropertyId },
5390 { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId },
5391 { &FillType_Property_GUID, UIA_FillTypePropertyId },
5392 { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId },
5393 { &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId },
5394 { &CenterPoint_Property_GUID, UIA_CenterPointPropertyId },
5395 { &Rotation_Property_GUID, UIA_RotationPropertyId },
5396 { &Size_Property_GUID, UIA_SizePropertyId },
5397 { &IsSelectionPattern2Available_Property_GUID, UIA_IsSelectionPattern2AvailablePropertyId },
5398 { &Selection2_FirstSelectedItem_Property_GUID, UIA_Selection2FirstSelectedItemPropertyId },
5399 { &Selection2_LastSelectedItem_Property_GUID, UIA_Selection2LastSelectedItemPropertyId },
5400 { &Selection2_CurrentSelectedItem_Property_GUID, UIA_Selection2CurrentSelectedItemPropertyId },
5401 { &Selection2_ItemCount_Property_GUID, UIA_Selection2ItemCountPropertyId },
5402 { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId },
5403 { &IsDialog_Property_GUID, UIA_IsDialogPropertyId },
5406 static const struct uia_lookup_id uia_event_lookup_ids[] = {
5407 { &ToolTipOpened_Event_GUID, UIA_ToolTipOpenedEventId },
5408 { &ToolTipClosed_Event_GUID, UIA_ToolTipClosedEventId },
5409 { &StructureChanged_Event_GUID, UIA_StructureChangedEventId },
5410 { &MenuOpened_Event_GUID, UIA_MenuOpenedEventId },
5411 { &AutomationPropertyChanged_Event_GUID, UIA_AutomationPropertyChangedEventId },
5412 { &AutomationFocusChanged_Event_GUID, UIA_AutomationFocusChangedEventId },
5413 { &AsyncContentLoaded_Event_GUID, UIA_AsyncContentLoadedEventId },
5414 { &MenuClosed_Event_GUID, UIA_MenuClosedEventId },
5415 { &LayoutInvalidated_Event_GUID, UIA_LayoutInvalidatedEventId },
5416 { &Invoke_Invoked_Event_GUID, UIA_Invoke_InvokedEventId },
5417 { &SelectionItem_ElementAddedToSelectionEvent_Event_GUID, UIA_SelectionItem_ElementAddedToSelectionEventId },
5418 { &SelectionItem_ElementRemovedFromSelectionEvent_Event_GUID, UIA_SelectionItem_ElementRemovedFromSelectionEventId },
5419 { &SelectionItem_ElementSelectedEvent_Event_GUID, UIA_SelectionItem_ElementSelectedEventId },
5420 { &Selection_InvalidatedEvent_Event_GUID, UIA_Selection_InvalidatedEventId },
5421 { &Text_TextSelectionChangedEvent_Event_GUID, UIA_Text_TextSelectionChangedEventId },
5422 { &Text_TextChangedEvent_Event_GUID, UIA_Text_TextChangedEventId },
5423 { &Window_WindowOpened_Event_GUID, UIA_Window_WindowOpenedEventId },
5424 { &Window_WindowClosed_Event_GUID, UIA_Window_WindowClosedEventId },
5425 { &MenuModeStart_Event_GUID, UIA_MenuModeStartEventId },
5426 { &MenuModeEnd_Event_GUID, UIA_MenuModeEndEventId },
5427 { &InputReachedTarget_Event_GUID, UIA_InputReachedTargetEventId },
5428 { &InputReachedOtherElement_Event_GUID, UIA_InputReachedOtherElementEventId },
5429 { &InputDiscarded_Event_GUID, UIA_InputDiscardedEventId },
5430 /* Implemented on Win8+ */
5431 { &SystemAlert_Event_GUID, UIA_SystemAlertEventId },
5432 { &LiveRegionChanged_Event_GUID, UIA_LiveRegionChangedEventId },
5433 { &HostedFragmentRootsInvalidated_Event_GUID, UIA_HostedFragmentRootsInvalidatedEventId },
5434 { &Drag_DragStart_Event_GUID, UIA_Drag_DragStartEventId },
5435 { &Drag_DragCancel_Event_GUID, UIA_Drag_DragCancelEventId },
5436 { &Drag_DragComplete_Event_GUID, UIA_Drag_DragCompleteEventId },
5437 { &DropTarget_DragEnter_Event_GUID, UIA_DropTarget_DragEnterEventId },
5438 { &DropTarget_DragLeave_Event_GUID, UIA_DropTarget_DragLeaveEventId },
5439 { &DropTarget_Dropped_Event_GUID, UIA_DropTarget_DroppedEventId },
5440 { &TextEdit_TextChanged_Event_GUID, UIA_TextEdit_TextChangedEventId },
5441 { &TextEdit_ConversionTargetChanged_Event_GUID, UIA_TextEdit_ConversionTargetChangedEventId },
5442 /* Implemented on Win10v1809+. */
5443 { &Changes_Event_GUID, UIA_ChangesEventId },
5444 { &Notification_Event_GUID, UIA_NotificationEventId },
5447 static const struct uia_lookup_id uia_pattern_lookup_ids[] = {
5448 { &Invoke_Pattern_GUID, UIA_InvokePatternId },
5449 { &Selection_Pattern_GUID, UIA_SelectionPatternId },
5450 { &Value_Pattern_GUID, UIA_ValuePatternId },
5451 { &RangeValue_Pattern_GUID, UIA_RangeValuePatternId },
5452 { &Scroll_Pattern_GUID, UIA_ScrollPatternId },
5453 { &ExpandCollapse_Pattern_GUID, UIA_ExpandCollapsePatternId },
5454 { &Grid_Pattern_GUID, UIA_GridPatternId },
5455 { &GridItem_Pattern_GUID, UIA_GridItemPatternId },
5456 { &MultipleView_Pattern_GUID, UIA_MultipleViewPatternId },
5457 { &Window_Pattern_GUID, UIA_WindowPatternId },
5458 { &SelectionItem_Pattern_GUID, UIA_SelectionItemPatternId },
5459 { &Dock_Pattern_GUID, UIA_DockPatternId },
5460 { &Table_Pattern_GUID, UIA_TablePatternId },
5461 { &TableItem_Pattern_GUID, UIA_TableItemPatternId },
5462 { &Text_Pattern_GUID, UIA_TextPatternId },
5463 { &Toggle_Pattern_GUID, UIA_TogglePatternId },
5464 { &Transform_Pattern_GUID, UIA_TransformPatternId },
5465 { &ScrollItem_Pattern_GUID, UIA_ScrollItemPatternId },
5466 { &LegacyIAccessible_Pattern_GUID, UIA_LegacyIAccessiblePatternId },
5467 { &ItemContainer_Pattern_GUID, UIA_ItemContainerPatternId },
5468 { &VirtualizedItem_Pattern_GUID, UIA_VirtualizedItemPatternId },
5469 { &SynchronizedInput_Pattern_GUID, UIA_SynchronizedInputPatternId },
5470 /* Implemented on Win8+ */
5471 { &ObjectModel_Pattern_GUID, UIA_ObjectModelPatternId },
5472 { &Annotation_Pattern_GUID, UIA_AnnotationPatternId },
5473 { &Text_Pattern2_GUID, UIA_TextPattern2Id },
5474 { &Styles_Pattern_GUID, UIA_StylesPatternId },
5475 { &Spreadsheet_Pattern_GUID, UIA_SpreadsheetPatternId },
5476 { &SpreadsheetItem_Pattern_GUID, UIA_SpreadsheetItemPatternId },
5477 { &Tranform_Pattern2_GUID, UIA_TransformPattern2Id },
5478 { &TextChild_Pattern_GUID, UIA_TextChildPatternId },
5479 { &Drag_Pattern_GUID, UIA_DragPatternId },
5480 { &DropTarget_Pattern_GUID, UIA_DropTargetPatternId },
5481 { &TextEdit_Pattern_GUID, UIA_TextEditPatternId },
5482 /* Implemented on Win10+. */
5483 { &CustomNavigation_Pattern_GUID, UIA_CustomNavigationPatternId },
5486 static const struct uia_lookup_id uia_control_type_lookup_ids[] = {
5487 { &Button_Control_GUID, UIA_ButtonControlTypeId },
5488 { &Calendar_Control_GUID, UIA_CalendarControlTypeId },
5489 { &CheckBox_Control_GUID, UIA_CheckBoxControlTypeId },
5490 { &ComboBox_Control_GUID, UIA_ComboBoxControlTypeId },
5491 { &Edit_Control_GUID, UIA_EditControlTypeId },
5492 { &Hyperlink_Control_GUID, UIA_HyperlinkControlTypeId },
5493 { &Image_Control_GUID, UIA_ImageControlTypeId },
5494 { &ListItem_Control_GUID, UIA_ListItemControlTypeId },
5495 { &List_Control_GUID, UIA_ListControlTypeId },
5496 { &Menu_Control_GUID, UIA_MenuControlTypeId },
5497 { &MenuBar_Control_GUID, UIA_MenuBarControlTypeId },
5498 { &MenuItem_Control_GUID, UIA_MenuItemControlTypeId },
5499 { &ProgressBar_Control_GUID, UIA_ProgressBarControlTypeId },
5500 { &RadioButton_Control_GUID, UIA_RadioButtonControlTypeId },
5501 { &ScrollBar_Control_GUID, UIA_ScrollBarControlTypeId },
5502 { &Slider_Control_GUID, UIA_SliderControlTypeId },
5503 { &Spinner_Control_GUID, UIA_SpinnerControlTypeId },
5504 { &StatusBar_Control_GUID, UIA_StatusBarControlTypeId },
5505 { &Tab_Control_GUID, UIA_TabControlTypeId },
5506 { &TabItem_Control_GUID, UIA_TabItemControlTypeId },
5507 { &Text_Control_GUID, UIA_TextControlTypeId },
5508 { &ToolBar_Control_GUID, UIA_ToolBarControlTypeId },
5509 { &ToolTip_Control_GUID, UIA_ToolTipControlTypeId },
5510 { &Tree_Control_GUID, UIA_TreeControlTypeId },
5511 { &TreeItem_Control_GUID, UIA_TreeItemControlTypeId },
5512 { &Custom_Control_GUID, UIA_CustomControlTypeId },
5513 { &Group_Control_GUID, UIA_GroupControlTypeId },
5514 { &Thumb_Control_GUID, UIA_ThumbControlTypeId },
5515 { &DataGrid_Control_GUID, UIA_DataGridControlTypeId },
5516 { &DataItem_Control_GUID, UIA_DataItemControlTypeId },
5517 { &Document_Control_GUID, UIA_DocumentControlTypeId },
5518 { &SplitButton_Control_GUID, UIA_SplitButtonControlTypeId },
5519 { &Window_Control_GUID, UIA_WindowControlTypeId },
5520 { &Pane_Control_GUID, UIA_PaneControlTypeId },
5521 { &Header_Control_GUID, UIA_HeaderControlTypeId },
5522 { &HeaderItem_Control_GUID, UIA_HeaderItemControlTypeId },
5523 { &Table_Control_GUID, UIA_TableControlTypeId },
5524 { &TitleBar_Control_GUID, UIA_TitleBarControlTypeId },
5525 { &Separator_Control_GUID, UIA_SeparatorControlTypeId },
5526 /* Implemented on Win8+ */
5527 { &SemanticZoom_Control_GUID, UIA_SemanticZoomControlTypeId },
5528 { &AppBar_Control_GUID, UIA_AppBarControlTypeId },
5531 static void test_UiaLookupId(void)
5533 static const struct {
5534 const char *id_type_name;
5535 int id_type;
5536 const struct uia_lookup_id *ids;
5537 int ids_count;
5538 } tests[] =
5540 { "property", AutomationIdentifierType_Property, uia_property_lookup_ids, ARRAY_SIZE(uia_property_lookup_ids) },
5541 { "event", AutomationIdentifierType_Event, uia_event_lookup_ids, ARRAY_SIZE(uia_event_lookup_ids) },
5542 { "pattern", AutomationIdentifierType_Pattern, uia_pattern_lookup_ids, ARRAY_SIZE(uia_pattern_lookup_ids) },
5543 { "control_type", AutomationIdentifierType_ControlType, uia_control_type_lookup_ids, ARRAY_SIZE(uia_control_type_lookup_ids) },
5545 unsigned int i, y;
5547 for (i = 0; i < ARRAY_SIZE(tests); i++)
5549 for (y = 0; y < tests[i].ids_count; y++)
5551 int id = UiaLookupId(tests[i].id_type, tests[i].ids[y].guid);
5553 if (!id)
5555 win_skip("No %s id for GUID %s, skipping further tests.\n", tests[i].id_type_name, debugstr_guid(tests[i].ids[y].guid));
5556 break;
5559 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);
5564 static const struct prov_method_sequence node_from_prov1[] = {
5565 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5566 { 0 }
5569 static const struct prov_method_sequence node_from_prov2[] = {
5570 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5571 /* Win10v1507 and below call this. */
5572 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5573 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5574 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5575 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5576 /* Only called on Windows versions past Win10v1507. */
5577 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5578 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5579 { 0 }
5582 static const struct prov_method_sequence node_from_prov3[] = {
5583 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5584 /* Win10v1507 and below call this. */
5585 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5586 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5587 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5588 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5589 /* Only called on Windows versions past Win10v1507. */
5590 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5591 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5592 { 0 }
5595 static const struct prov_method_sequence node_from_prov4[] = {
5596 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5597 /* Win10v1507 and below call this. */
5598 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5599 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5600 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5601 /* Only called on Windows versions past Win10v1507. */
5602 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5603 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5604 { 0 }
5607 static const struct prov_method_sequence node_from_prov5[] = {
5608 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5609 /* Win10v1507 and below call this. */
5610 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5611 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5612 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5613 /* Win10v1507 and below call this. */
5614 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5615 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5616 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5617 /* These three are only done on Win10v1507 and below. */
5618 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5619 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5620 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
5621 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5622 /* This is only done on Win10v1507. */
5623 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5624 /* Only called on Windows versions past Win10v1507. */
5625 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5626 /* Win10v1507 and below call this. */
5627 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
5628 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5629 { 0 }
5632 static const struct prov_method_sequence node_from_prov6[] = {
5633 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5634 /* Win10v1507 and below call this. */
5635 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5636 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5637 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5638 /* Win10v1507 and below call this. */
5639 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5640 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5641 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5642 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5643 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5644 /* Only called on Windows versions past Win10v1507. */
5645 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5646 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
5647 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5648 /* This is only done on Win10v1507. */
5649 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5650 /* Only called on Windows versions past Win10v1507. */
5651 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5652 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5653 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5654 { 0 }
5657 static const struct prov_method_sequence node_from_prov7[] = {
5658 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
5659 /* Win10v1507 and below call this. */
5660 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5661 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5662 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5663 /* Win10v1507 and below call this. */
5664 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5665 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5666 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5667 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5668 { &Provider2, PROV_GET_PROVIDER_OPTIONS },
5669 /* Only called on Windows versions past Win10v1507. */
5670 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
5671 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
5672 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5673 /* This is only done on Win10v1507. */
5674 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5675 /* Only called on Windows versions past Win10v1507. */
5676 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5677 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5678 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
5679 { 0 }
5682 static const struct prov_method_sequence node_from_prov8[] = {
5683 { &Provider, PROV_GET_PROVIDER_OPTIONS },
5684 /* Win10v1507 and below call this. */
5685 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
5686 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
5687 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
5688 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
5689 /* Only called on Windows versions past Win10v1507. */
5690 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
5691 { 0 }
5694 static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com);
5695 static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param)
5697 HUIANODE node = param;
5698 HRESULT hr;
5699 VARIANT v;
5702 * Since this is a node representing an IRawElementProviderSimple with
5703 * ProviderOptions_UseComThreading set, it is only usable in threads that
5704 * have initialized COM.
5706 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
5707 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
5709 CoInitializeEx(NULL, COINIT_MULTITHREADED);
5711 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
5712 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5713 check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v, FALSE);
5716 * When retrieving a UIAutomationType_Element property, if UseComThreading
5717 * is set, we'll get an HUIANODE that will make calls inside of the
5718 * apartment of the node it is retrieved from. I.e, if we received a node
5719 * with UseComThreading set from another node with UseComThreading set
5720 * inside of an STA, the returned node will have all of its methods called
5721 * from the STA thread.
5723 Provider_child.prov_opts = ProviderOptions_UseComThreading | ProviderOptions_ServerSideProvider;
5724 Provider_child.expected_tid = Provider.expected_tid;
5725 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
5726 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5727 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
5729 /* Unset ProviderOptions_UseComThreading. */
5730 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
5731 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
5732 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5735 * ProviderOptions_UseComThreading not set, GetPropertyValue will be
5736 * called on the current thread.
5738 Provider_child.expected_tid = GetCurrentThreadId();
5739 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
5741 CoUninitialize();
5743 return 0;
5746 static void test_uia_node_from_prov_com_threading(void)
5748 HANDLE thread;
5749 HUIANODE node;
5750 HRESULT hr;
5752 /* Test ProviderOptions_UseComThreading. */
5753 Provider.hwnd = NULL;
5754 prov_root = NULL;
5755 Provider.prov_opts = ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading;
5756 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5757 ok_method_sequence(node_from_prov8, "node_from_prov8");
5760 * On Windows versions prior to Windows 10, UiaNodeFromProvider ignores the
5761 * ProviderOptions_UseComThreading flag.
5763 if (hr == S_OK)
5765 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
5766 UiaNodeRelease(node);
5767 return;
5769 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx.\n", hr);
5771 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
5772 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5773 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5774 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5775 ok_method_sequence(node_from_prov8, "node_from_prov8");
5777 Provider.expected_tid = GetCurrentThreadId();
5778 thread = CreateThread(NULL, 0, uia_node_from_provider_test_com_thread, (void *)node, 0, NULL);
5779 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
5781 MSG msg;
5782 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
5784 TranslateMessage(&msg);
5785 DispatchMessageW(&msg);
5788 CloseHandle(thread);
5790 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5791 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
5792 Provider_child.expected_tid = Provider.expected_tid = 0;
5794 CoUninitialize();
5796 static void test_UiaNodeFromProvider(void)
5798 WNDCLASSA cls;
5799 HUIANODE node;
5800 HRESULT hr;
5801 ULONG ref;
5802 HWND hwnd;
5803 VARIANT v;
5805 cls.style = 0;
5806 cls.lpfnWndProc = test_wnd_proc;
5807 cls.cbClsExtra = 0;
5808 cls.cbWndExtra = 0;
5809 cls.hInstance = GetModuleHandleA(NULL);
5810 cls.hIcon = 0;
5811 cls.hCursor = NULL;
5812 cls.hbrBackground = NULL;
5813 cls.lpszMenuName = NULL;
5814 cls.lpszClassName = "UiaNodeFromProvider class";
5816 RegisterClassA(&cls);
5818 hwnd = CreateWindowA("UiaNodeFromProvider class", "Test window", WS_OVERLAPPEDWINDOW,
5819 0, 0, 100, 100, NULL, NULL, NULL, NULL);
5821 /* Run these tests early, we end up in an implicit MTA later. */
5822 test_uia_node_from_prov_com_threading();
5824 CoInitializeEx(NULL, COINIT_MULTITHREADED);
5826 hr = UiaNodeFromProvider(NULL, &node);
5827 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5829 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, NULL);
5830 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5832 /* Must have a successful call to get_ProviderOptions. */
5833 Provider.prov_opts = 0;
5834 node = (void *)0xdeadbeef;
5835 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5836 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5837 ok(!node, "node != NULL\n");
5838 ok_method_sequence(node_from_prov1, "node_from_prov1");
5840 /* No HWND exposed through Provider. */
5841 Provider.prov_opts = ProviderOptions_ServerSideProvider;
5842 node = (void *)0xdeadbeef;
5843 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5844 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5846 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5847 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5848 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
5849 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
5850 VariantClear(&v);
5852 ok_method_sequence(node_from_prov2, "node_from_prov2");
5854 /* HUIANODE represents a COM interface. */
5855 ref = IUnknown_AddRef((IUnknown *)node);
5856 ok(ref == 2, "Unexpected refcnt %ld\n", ref);
5858 ref = IUnknown_AddRef((IUnknown *)node);
5859 ok(ref == 3, "Unexpected refcnt %ld\n", ref);
5861 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5863 ref = IUnknown_Release((IUnknown *)node);
5864 ok(ref == 1, "Unexpected refcnt %ld\n", ref);
5866 ref = IUnknown_Release((IUnknown *)node);
5867 ok(ref == 0, "Unexpected refcnt %ld\n", ref);
5868 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
5871 * No HWND exposed through Provider_child, but it returns a parent from
5872 * NavigateDirection_Parent. Behavior doesn't change.
5874 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
5875 node = (void *)0xdeadbeef;
5876 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
5877 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
5879 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5880 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5881 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
5882 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
5883 VariantClear(&v);
5885 ok_method_sequence(node_from_prov3, "node_from_prov3");
5886 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5887 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
5889 /* HWND exposed, but Provider2 not returned from WM_GETOBJECT. */
5890 Provider.hwnd = hwnd;
5891 prov_root = NULL;
5892 node = (void *)0xdeadbeef;
5893 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
5894 /* Win10v1507 and below send this, Windows 7 sends it twice. */
5895 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
5896 Provider.ignore_hwnd_prop = TRUE;
5897 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5898 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5899 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5900 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
5901 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
5903 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5904 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5905 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
5906 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
5907 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
5908 check_node_provider_desc_todo(V_BSTR(&v), L"Hwnd", NULL, TRUE);
5909 VariantClear(&v);
5911 Provider.ignore_hwnd_prop = FALSE;
5912 ok_method_sequence(node_from_prov4, "node_from_prov4");
5914 ok(!!node, "node == NULL\n");
5915 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5916 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
5919 * Provider is our main provider, since Provider2 is also a main, it won't
5920 * get added.
5922 Provider.hwnd = Provider2.hwnd = hwnd;
5923 Provider.prov_opts = Provider2.prov_opts = ProviderOptions_ServerSideProvider;
5924 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = TRUE;
5925 prov_root = &Provider2.IRawElementProviderSimple_iface;
5926 node = (void *)0xdeadbeef;
5927 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
5928 /* Windows 7 sends this. */
5929 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5930 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5931 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5932 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
5933 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
5935 /* Win10v1507 and below hold a reference to the root provider for the HWND */
5936 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5937 ok(!!node, "node == NULL\n");
5939 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5940 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5941 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
5942 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
5943 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
5944 check_node_provider_desc_todo(V_BSTR(&v), L"Hwnd", NULL, TRUE);
5945 VariantClear(&v);
5947 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = FALSE;
5948 ok_method_sequence(node_from_prov5, "node_from_prov5");
5950 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5951 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
5952 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
5955 * Provider is classified as an Hwnd provider, Provider2 will become our
5956 * Main provider since we don't have one already.
5958 Provider.prov_opts = ProviderOptions_ClientSideProvider;
5959 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
5960 prov_root = &Provider2.IRawElementProviderSimple_iface;
5961 node = (void *)0xdeadbeef;
5962 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
5963 /* Windows 7 sends this. */
5964 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5965 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
5966 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5967 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
5968 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
5970 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
5971 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5972 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
5973 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
5974 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
5975 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
5976 VariantClear(&v);
5978 ok_method_sequence(node_from_prov6, "node_from_prov6");
5980 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
5981 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
5983 ok(!!node, "node == NULL\n");
5984 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
5985 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
5986 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
5988 /* Provider_child has a parent, so it will be "(parent link)". */
5989 Provider_child.prov_opts = ProviderOptions_ClientSideProvider;
5990 Provider_child.hwnd = hwnd;
5991 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
5992 prov_root = &Provider2.IRawElementProviderSimple_iface;
5993 node = (void *)0xdeadbeef;
5994 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
5995 /* Windows 7 sends this. */
5996 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5997 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
5998 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
5999 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6000 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6002 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6003 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6004 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6005 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", FALSE);
6006 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6007 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_child", TRUE);
6008 VariantClear(&v);
6010 ok_method_sequence(node_from_prov7, "node_from_prov7");
6012 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
6013 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6015 ok(!!node, "node == NULL\n");
6016 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6017 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6018 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6020 CoUninitialize();
6021 DestroyWindow(hwnd);
6022 UnregisterClassA("UiaNodeFromProvider class", NULL);
6023 prov_root = NULL;
6026 /* Sequence for types other than UIAutomationType_Element. */
6027 static const struct prov_method_sequence get_prop_seq[] = {
6028 { &Provider, PROV_GET_PROPERTY_VALUE },
6029 { 0 }
6032 /* Sequence for getting a property that returns an invalid type. */
6033 static const struct prov_method_sequence get_prop_invalid_type_seq[] = {
6034 { &Provider, PROV_GET_PROPERTY_VALUE },
6035 /* Windows 7 calls this. */
6036 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6037 { 0 }
6040 /* UIAutomationType_Element sequence. */
6041 static const struct prov_method_sequence get_elem_prop_seq[] = {
6042 { &Provider, PROV_GET_PROPERTY_VALUE },
6043 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
6044 /* Win10v1507 and below call this. */
6045 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6046 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6047 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6048 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6049 /* Only called on Windows versions past Win10v1507. */
6050 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6051 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL },
6052 { 0 }
6055 /* UIAutomationType_ElementArray sequence. */
6056 static const struct prov_method_sequence get_elem_arr_prop_seq[] = {
6057 { &Provider, PROV_GET_PROPERTY_VALUE },
6058 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
6059 /* Win10v1507 and below call this. */
6060 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6061 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6062 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6063 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6064 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
6065 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS },
6066 /* Win10v1507 and below call this. */
6067 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6068 { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6069 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6070 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6071 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS },
6072 { &Provider_child, PROV_GET_PROPERTY_VALUE },
6073 { &Provider_child2, PROV_GET_PROPERTY_VALUE },
6074 { 0 }
6077 static const struct prov_method_sequence get_pattern_prop_seq[] = {
6078 { &Provider, PROV_GET_PATTERN_PROV },
6079 { 0 }
6082 static const struct prov_method_sequence get_pattern_prop_seq2[] = {
6083 { &Provider, PROV_GET_PATTERN_PROV },
6084 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_TODO },
6085 { 0 }
6088 static const struct prov_method_sequence get_bounding_rect_seq[] = {
6089 NODE_CREATE_SEQ(&Provider_child),
6090 { &Provider_child, FRAG_GET_BOUNDING_RECT },
6092 * Win10v21H2+ and above call these, attempting to get the fragment root's
6093 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6095 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6096 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6097 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6098 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6099 { 0 }
6102 static const struct prov_method_sequence get_bounding_rect_seq2[] = {
6103 { &Provider, PROV_GET_PROPERTY_VALUE },
6104 NODE_CREATE_SEQ(&Provider_child),
6105 { &Provider_child, FRAG_GET_BOUNDING_RECT },
6107 * Win10v21H2+ and above call these, attempting to get the fragment root's
6108 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6110 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6111 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6112 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6113 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6114 { 0 }
6117 static const struct prov_method_sequence get_bounding_rect_seq3[] = {
6118 { &Provider_child, FRAG_GET_BOUNDING_RECT },
6120 * Win10v21H2+ and above call these, attempting to get the fragment root's
6121 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6123 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6124 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6125 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6126 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6127 { 0 }
6130 static const struct prov_method_sequence get_empty_bounding_rect_seq[] = {
6131 { &Provider_child, FRAG_GET_BOUNDING_RECT },
6132 { 0 }
6135 static void set_uia_rect(struct UiaRect *rect, double left, double top, double width, double height)
6137 rect->left = left;
6138 rect->top = top;
6139 rect->width = width;
6140 rect->height = height;
6143 #define check_uia_rect_val( v, rect ) \
6144 check_uia_rect_val_( (v), (rect), __FILE__, __LINE__)
6145 static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *file, int line)
6147 LONG lbound, ubound, elems, idx;
6148 SAFEARRAY *sa;
6149 double tmp[4];
6150 VARTYPE vt;
6151 HRESULT hr;
6152 UINT dims;
6154 ok_(file, line)(V_VT(v) == (VT_R8 | VT_ARRAY), "Unexpected rect VT hr %d.\n", V_VT(v));
6155 if (V_VT(v) != (VT_R8 | VT_ARRAY))
6156 return;
6158 sa = V_ARRAY(v);
6159 hr = SafeArrayGetVartype(sa, &vt);
6160 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6161 ok_(file, line)(vt == VT_R8, "Unexpected vt %d\n", vt);
6163 dims = SafeArrayGetDim(sa);
6164 ok_(file, line)(dims == 1, "Unexpected dims %d\n", dims);
6166 lbound = ubound = elems = 0;
6167 hr = SafeArrayGetLBound(sa, 1, &lbound);
6168 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
6169 ok_(file, line)(lbound == 0, "Unexpected lbound %ld\n", lbound);
6171 hr = SafeArrayGetUBound(sa, 1, &ubound);
6172 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
6173 ok_(file, line)(ubound == 3, "Unexpected ubound %ld\n", ubound);
6175 elems = (ubound - lbound) + 1;
6176 ok_(file, line)(elems == 4, "Unexpected rect elems %ld\n", elems);
6178 for (idx = 0; idx < ARRAY_SIZE(tmp); idx++)
6180 hr = SafeArrayGetElement(sa, &idx, &tmp[idx]);
6181 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetElement at idx %ld.\n", hr, idx);
6184 ok_(file, line)(tmp[0] == rect->left, "Unexpected left value %f, expected %f\n", tmp[0], rect->left);
6185 ok_(file, line)(tmp[1] == rect->top, "Unexpected top value %f, expected %f\n", tmp[1], rect->top);
6186 ok_(file, line)(tmp[2] == rect->width, "Unexpected width value %f, expected %f\n", tmp[2], rect->width);
6187 ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height);
6190 #define check_uia_rect_rect_val( rect, uia_rect ) \
6191 check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__)
6192 static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line)
6194 ok_(file, line)(rect->left == (LONG)uia_rect->left, "Unexpected left value %ld, expected %ld\n", rect->left, (LONG)uia_rect->left);
6195 ok_(file, line)(rect->top == (LONG)uia_rect->top, "Unexpected top value %ld, expected %ld\n", rect->top, (LONG)uia_rect->top);
6196 ok_(file, line)(rect->right == (LONG)(uia_rect->left + uia_rect->width), "Unexpected right value %ld, expected %ld\n", rect->right,
6197 (LONG)(uia_rect->left + uia_rect->width));
6198 ok_(file, line)(rect->bottom == (LONG)(uia_rect->top + uia_rect->height), "Unexpected bottom value %ld, expected %ld\n", rect->bottom,
6199 (LONG)(uia_rect->top + uia_rect->height));
6202 static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com)
6204 LONG idx;
6206 switch (type)
6208 case UIAutomationType_String:
6209 ok(V_VT(v) == VT_BSTR, "Unexpected VT %d\n", V_VT(v));
6210 ok(!lstrcmpW(V_BSTR(v), uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(v)));
6211 ok_method_sequence(get_prop_seq, NULL);
6212 break;
6214 case UIAutomationType_Bool:
6215 ok(V_VT(v) == VT_BOOL, "Unexpected VT %d\n", V_VT(v));
6217 /* UIA_IsKeyboardFocusablePropertyId is broken on Win8 and Win10v1507. */
6218 if (prop_id == UIA_IsKeyboardFocusablePropertyId)
6219 ok(check_variant_bool(v, TRUE) || broken(check_variant_bool(v, FALSE)),
6220 "Unexpected BOOL %#x\n", V_BOOL(v));
6221 else
6222 ok(check_variant_bool(v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(v));
6223 ok_method_sequence(get_prop_seq, NULL);
6224 break;
6226 case UIAutomationType_Int:
6227 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
6229 if (prop_id == UIA_NativeWindowHandlePropertyId)
6230 ok(ULongToHandle(V_I4(v)) == Provider.hwnd, "Unexpected I4 %#lx\n", V_I4(v));
6231 else
6232 ok(V_I4(v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(v));
6233 ok_method_sequence(get_prop_seq, NULL);
6234 break;
6236 case UIAutomationType_IntArray:
6237 ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v));
6239 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
6241 ULONG val;
6243 SafeArrayGetElement(V_ARRAY(v), &idx, &val);
6244 ok(val == uia_i4_arr_prop_val[idx], "Unexpected I4 %#lx at idx %ld\n", val, idx);
6246 ok_method_sequence(get_prop_seq, NULL);
6247 break;
6249 case UIAutomationType_Double:
6250 ok(V_VT(v) == VT_R8, "Unexpected VT %d\n", V_VT(v));
6251 ok(V_R8(v) == uia_r8_prop_val, "Unexpected R8 %lf\n", V_R8(v));
6252 ok_method_sequence(get_prop_seq, NULL);
6253 break;
6255 case UIAutomationType_DoubleArray:
6256 ok(V_VT(v) == (VT_ARRAY | VT_R8), "Unexpected VT %d\n", V_VT(v));
6257 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
6259 double val;
6261 SafeArrayGetElement(V_ARRAY(v), &idx, &val);
6262 ok(val == uia_r8_arr_prop_val[idx], "Unexpected R8 %lf at idx %ld\n", val, idx);
6264 ok_method_sequence(get_prop_seq, NULL);
6265 break;
6267 case UIAutomationType_Element:
6269 HUIANODE tmp_node;
6270 HRESULT hr;
6271 VARIANT v1;
6273 if (from_com)
6275 IUIAutomationElement *elem;
6277 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
6278 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElement, (void **)&elem);
6279 VariantClear(v);
6280 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6281 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6283 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_ControlTypePropertyId, TRUE, &v1);
6284 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6285 IUIAutomationElement_Release(elem);
6287 else
6289 #ifdef _WIN64
6290 ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
6291 tmp_node = (HUIANODE)V_I8(v);
6292 #else
6293 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
6294 tmp_node = (HUIANODE)V_I4(v);
6295 #endif
6296 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6298 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
6299 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6300 ok(UiaNodeRelease(tmp_node), "Failed to release node\n");
6303 ok(V_VT(&v1) == VT_I4, "Unexpected VT %d\n", V_VT(&v1));
6304 ok(V_I4(&v1) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v1));
6305 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6307 ok_method_sequence(get_elem_prop_seq, NULL);
6308 break;
6311 case UIAutomationType_ElementArray:
6312 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6313 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
6314 if (from_com)
6316 IUIAutomationElementArray *elem_arr = NULL;
6317 HRESULT hr;
6318 int len;
6320 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
6321 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
6322 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6323 ok(!!elem_arr, "elem_arr == NULL\n");
6324 if (!elem_arr)
6326 VariantClear(v);
6327 break;
6330 hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
6331 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6332 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
6334 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
6336 IUIAutomationElement *tmp_elem = NULL;
6337 VARIANT v1;
6339 hr = IUIAutomationElementArray_GetElement(elem_arr, idx, &tmp_elem);
6340 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6341 ok(!!tmp_elem, "tmp_elem == NULL\n");
6343 hr = IUIAutomationElement_GetCurrentPropertyValueEx(tmp_elem, UIA_ControlTypePropertyId, TRUE, &v1);
6344 ok(hr == S_OK, "elem[%ld] Unexpected hr %#lx\n", idx, hr);
6345 ok(V_VT(&v1) == VT_I4, "elem[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
6346 ok(V_I4(&v1) == uia_i4_prop_val, "elem[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
6348 IUIAutomationElement_Release(tmp_elem);
6349 VariantClear(&v1);
6352 IUIAutomationElementArray_Release(elem_arr);
6354 else
6356 ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v));
6357 if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN))
6358 break;
6360 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
6362 HUIANODE tmp_node;
6363 HRESULT hr;
6364 VARIANT v1;
6366 SafeArrayGetElement(V_ARRAY(v), &idx, &tmp_node);
6368 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
6369 ok(hr == S_OK, "node[%ld] Unexpected hr %#lx\n", idx, hr);
6370 ok(V_VT(&v1) == VT_I4, "node[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
6371 ok(V_I4(&v1) == uia_i4_prop_val, "node[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
6373 ok(UiaNodeRelease(tmp_node), "Failed to release node[%ld]\n", idx);
6374 VariantClear(&v1);
6378 VariantClear(v);
6379 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6380 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
6381 ok_method_sequence(get_elem_arr_prop_seq, NULL);
6382 break;
6384 default:
6385 break;
6388 VariantClear(v);
6389 V_VT(v) = VT_EMPTY;
6392 struct uia_element_property {
6393 const GUID *prop_guid;
6394 enum UIAutomationType type;
6395 BOOL skip_invalid;
6398 static const struct uia_element_property element_properties[] = {
6399 { &ProcessId_Property_GUID, UIAutomationType_Int, TRUE },
6400 { &ControlType_Property_GUID, UIAutomationType_Int },
6401 { &LocalizedControlType_Property_GUID, UIAutomationType_String, TRUE },
6402 { &Name_Property_GUID, UIAutomationType_String },
6403 { &AcceleratorKey_Property_GUID, UIAutomationType_String },
6404 { &AccessKey_Property_GUID, UIAutomationType_String },
6405 { &HasKeyboardFocus_Property_GUID, UIAutomationType_Bool },
6406 { &IsKeyboardFocusable_Property_GUID, UIAutomationType_Bool },
6407 { &IsEnabled_Property_GUID, UIAutomationType_Bool },
6408 { &AutomationId_Property_GUID, UIAutomationType_String },
6409 { &ClassName_Property_GUID, UIAutomationType_String },
6410 { &HelpText_Property_GUID, UIAutomationType_String },
6411 { &Culture_Property_GUID, UIAutomationType_Int },
6412 { &IsControlElement_Property_GUID, UIAutomationType_Bool },
6413 { &IsContentElement_Property_GUID, UIAutomationType_Bool },
6414 { &LabeledBy_Property_GUID, UIAutomationType_Element },
6415 { &IsPassword_Property_GUID, UIAutomationType_Bool },
6416 { &NewNativeWindowHandle_Property_GUID, UIAutomationType_Int },
6417 { &ItemType_Property_GUID, UIAutomationType_String },
6418 { &IsOffscreen_Property_GUID, UIAutomationType_Bool },
6419 { &Orientation_Property_GUID, UIAutomationType_Int },
6420 { &FrameworkId_Property_GUID, UIAutomationType_String },
6421 { &IsRequiredForForm_Property_GUID, UIAutomationType_Bool },
6422 { &ItemStatus_Property_GUID, UIAutomationType_String },
6423 { &AriaRole_Property_GUID, UIAutomationType_String },
6424 { &AriaProperties_Property_GUID, UIAutomationType_String },
6425 { &IsDataValidForForm_Property_GUID, UIAutomationType_Bool },
6426 { &ControllerFor_Property_GUID, UIAutomationType_ElementArray },
6427 { &DescribedBy_Property_GUID, UIAutomationType_ElementArray },
6428 { &FlowsTo_Property_GUID, UIAutomationType_ElementArray },
6429 /* Implemented on Win8+ */
6430 { &OptimizeForVisualContent_Property_GUID, UIAutomationType_Bool },
6431 { &LiveSetting_Property_GUID, UIAutomationType_Int },
6432 { &FlowsFrom_Property_GUID, UIAutomationType_ElementArray },
6433 { &IsPeripheral_Property_GUID, UIAutomationType_Bool },
6434 /* Implemented on Win10v1507+. */
6435 { &PositionInSet_Property_GUID, UIAutomationType_Int },
6436 { &SizeOfSet_Property_GUID, UIAutomationType_Int },
6437 { &Level_Property_GUID, UIAutomationType_Int },
6438 { &AnnotationTypes_Property_GUID, UIAutomationType_IntArray },
6439 { &AnnotationObjects_Property_GUID, UIAutomationType_ElementArray },
6440 /* Implemented on Win10v1809+. */
6441 { &LandmarkType_Property_GUID, UIAutomationType_Int },
6442 { &LocalizedLandmarkType_Property_GUID, UIAutomationType_String, TRUE },
6443 { &FullDescription_Property_GUID, UIAutomationType_String },
6444 { &FillColor_Property_GUID, UIAutomationType_Int },
6445 { &OutlineColor_Property_GUID, UIAutomationType_IntArray },
6446 { &FillType_Property_GUID, UIAutomationType_Int },
6447 { &VisualEffects_Property_GUID, UIAutomationType_Int },
6448 { &OutlineThickness_Property_GUID, UIAutomationType_DoubleArray },
6449 { &Rotation_Property_GUID, UIAutomationType_Double },
6450 { &Size_Property_GUID, UIAutomationType_DoubleArray },
6451 { &HeadingLevel_Property_GUID, UIAutomationType_Int },
6452 { &IsDialog_Property_GUID, UIAutomationType_Bool },
6455 static void test_UiaGetPropertyValue(void)
6457 const struct uia_element_property *elem_prop;
6458 struct UiaRect rect;
6459 IUnknown *unk_ns;
6460 unsigned int i;
6461 HUIANODE node;
6462 int prop_id;
6463 HRESULT hr;
6464 VARIANT v;
6466 CoInitializeEx(NULL, COINIT_MULTITHREADED);
6468 Provider.prov_opts = ProviderOptions_ServerSideProvider;
6469 Provider_child.prov_opts = Provider_child2.prov_opts = ProviderOptions_ServerSideProvider;
6470 Provider.hwnd = Provider_child.hwnd = Provider_child2.hwnd = NULL;
6471 node = (void *)0xdeadbeef;
6472 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
6473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6474 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6475 ok_method_sequence(node_from_prov8, NULL);
6477 hr = UiaGetReservedNotSupportedValue(&unk_ns);
6478 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6480 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
6482 elem_prop = &element_properties[i];
6484 Provider.ret_invalid_prop_type = FALSE;
6485 VariantClear(&v);
6486 prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid);
6487 if (!prop_id)
6489 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
6490 break;
6492 winetest_push_context("prop_id %d", prop_id);
6493 hr = UiaGetPropertyValue(node, prop_id, &v);
6494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6495 check_uia_prop_val(prop_id, elem_prop->type, &v, FALSE);
6498 * Some properties have special behavior if an invalid value is
6499 * returned, skip them here.
6501 if (!elem_prop->skip_invalid)
6503 Provider.ret_invalid_prop_type = TRUE;
6504 hr = UiaGetPropertyValue(node, prop_id, &v);
6505 if (hr == E_NOTIMPL)
6506 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6507 else
6508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6509 if (SUCCEEDED(hr))
6511 ok_method_sequence(get_prop_invalid_type_seq, NULL);
6512 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
6513 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
6514 VariantClear(&v);
6518 winetest_pop_context();
6521 /* IValueProvider pattern property IDs. */
6522 Provider.value_pattern_data.is_supported = FALSE;
6523 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
6524 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6525 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
6526 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
6527 ok_method_sequence(get_pattern_prop_seq, NULL);
6528 VariantClear(&v);
6530 Provider.value_pattern_data.is_supported = TRUE;
6531 for (i = 0; i < 2; i++)
6533 Provider.value_pattern_data.is_read_only = i;
6535 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
6536 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6537 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
6538 ok(check_variant_bool(&v, i), "Unexpected BOOL %#x\n", V_BOOL(&v));
6539 ok_method_sequence(get_pattern_prop_seq, NULL);
6540 VariantClear(&v);
6543 /* ILegacyIAccessibleProvider pattern property IDs. */
6544 Provider.legacy_acc_pattern_data.is_supported = FALSE;
6545 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v);
6546 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6547 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
6548 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
6549 ok_method_sequence(get_pattern_prop_seq2, NULL);
6550 VariantClear(&v);
6552 Provider.legacy_acc_pattern_data.is_supported = TRUE;
6553 for (i = 0; i < 2; i++)
6555 Provider.legacy_acc_pattern_data.child_id = i;
6557 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v);
6558 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6559 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
6560 ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v));
6561 ok_method_sequence(get_pattern_prop_seq, NULL);
6562 VariantClear(&v);
6565 for (i = 0; i < 2; i++)
6567 Provider.legacy_acc_pattern_data.role = i;
6569 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleRolePropertyId, &v);
6570 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6571 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
6572 ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v));
6573 ok_method_sequence(get_pattern_prop_seq, NULL);
6574 VariantClear(&v);
6577 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6578 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6579 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
6582 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
6583 * It's the only version with this behavior.
6585 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
6587 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
6588 goto exit;
6591 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
6592 node = (void *)0xdeadbeef;
6593 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
6594 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6595 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6597 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
6598 set_uia_rect(&rect, 0, 0, 50, 50);
6599 Provider_child.bounds_rect = rect;
6600 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
6601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6602 check_uia_rect_val(&v, &rect);
6603 VariantClear(&v);
6605 ok_method_sequence(get_bounding_rect_seq, "get_bounding_rect_seq");
6607 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
6608 set_uia_rect(&rect, 0, 0, 0, 0);
6609 Provider_child.bounds_rect = rect;
6610 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
6611 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6612 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
6613 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
6614 VariantClear(&v);
6615 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
6617 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6618 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6619 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
6621 exit:
6623 IUnknown_Release(unk_ns);
6624 CoUninitialize();
6627 static const struct prov_method_sequence get_runtime_id1[] = {
6628 { &Provider_child, FRAG_GET_RUNTIME_ID },
6629 { 0 }
6632 static const struct prov_method_sequence get_runtime_id2[] = {
6633 { &Provider_child, FRAG_GET_RUNTIME_ID },
6634 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
6635 { 0 }
6638 static const struct prov_method_sequence get_runtime_id3[] = {
6639 { &Provider_child, FRAG_GET_RUNTIME_ID },
6640 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
6641 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6642 /* Not called on Windows 7. */
6643 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6644 /* Only called on Win8+. */
6645 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6646 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6647 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6648 { &Provider2, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6649 { 0 }
6652 static const struct prov_method_sequence get_runtime_id4[] = {
6653 { &Provider_child, FRAG_GET_RUNTIME_ID },
6654 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
6655 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6656 /* Not called on Windows 7. */
6657 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6658 /* These methods are only called on Win8+. */
6659 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
6660 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
6661 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6662 { 0 }
6665 static const struct prov_method_sequence get_runtime_id5[] = {
6666 { &Provider_child, FRAG_GET_RUNTIME_ID },
6667 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
6668 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6669 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6670 { 0 }
6673 static void test_UiaGetRuntimeId(void)
6675 const int root_prov_opts[] = { ProviderOptions_ServerSideProvider, ProviderOptions_ServerSideProvider | ProviderOptions_OverrideProvider,
6676 ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider };
6677 int rt_id[4], tmp, i;
6678 IUnknown *unk_ns;
6679 SAFEARRAY *sa;
6680 WNDCLASSA cls;
6681 HUIANODE node;
6682 HRESULT hr;
6683 HWND hwnd;
6684 VARIANT v;
6686 VariantInit(&v);
6687 cls.style = 0;
6688 cls.lpfnWndProc = test_wnd_proc;
6689 cls.cbClsExtra = 0;
6690 cls.cbWndExtra = 0;
6691 cls.hInstance = GetModuleHandleA(NULL);
6692 cls.hIcon = 0;
6693 cls.hCursor = NULL;
6694 cls.hbrBackground = NULL;
6695 cls.lpszMenuName = NULL;
6696 cls.lpszClassName = "UiaGetRuntimeId class";
6698 RegisterClassA(&cls);
6700 hwnd = CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW,
6701 0, 0, 100, 100, NULL, NULL, NULL, NULL);
6703 hr = UiaGetReservedNotSupportedValue(&unk_ns);
6704 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6706 CoInitializeEx(NULL, COINIT_MULTITHREADED);
6707 Provider.prov_opts = Provider2.prov_opts = Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
6708 Provider.hwnd = Provider2.hwnd = Provider_child.hwnd = NULL;
6709 node = (void *)0xdeadbeef;
6710 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
6711 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6712 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6714 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6715 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6716 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
6717 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6718 VariantClear(&v);
6720 ok_method_sequence(node_from_prov3, NULL);
6722 /* NULL runtime ID. */
6723 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0;
6724 sa = (void *)0xdeadbeef;
6725 hr = UiaGetRuntimeId(node, &sa);
6726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6727 ok(!sa, "sa != NULL\n");
6728 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
6730 /* No UiaAppendRuntimeId prefix, returns GetRuntimeId array directly. */
6731 Provider_child.runtime_id[0] = rt_id[0] = 5;
6732 Provider_child.runtime_id[1] = rt_id[1] = 2;
6733 sa = (void *)0xdeadbeef;
6734 hr = UiaGetRuntimeId(node, &sa);
6735 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6736 ok(!!sa, "sa == NULL\n");
6737 check_runtime_id(rt_id, 2, sa);
6738 SafeArrayDestroy(sa);
6739 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
6742 * If a provider returns a RuntimeId beginning with the constant
6743 * UiaAppendRuntimeId, UI Automation will add a prefix based on the
6744 * providers HWND fragment root before returning to the client. The added
6745 * prefix is 3 int values, with:
6747 * idx[0] always being 42. (UIA_RUNTIME_ID_PREFIX)
6748 * idx[1] always being the HWND.
6749 * idx[2] has three different values depending on what type of provider
6750 * the fragment root is. Fragment roots can be an override provider, a
6751 * nonclient provider, or a main provider.
6753 Provider_child.frag_root = NULL;
6754 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
6755 Provider_child.runtime_id[1] = 2;
6756 sa = (void *)0xdeadbeef;
6758 /* Provider_child has no fragment root for UiaAppendRuntimeId. */
6759 hr = UiaGetRuntimeId(node, &sa);
6760 /* Windows 7 returns S_OK. */
6761 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
6762 ok(!sa, "sa != NULL\n");
6763 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
6766 * UIA_RuntimeIdPropertyId won't return a failure code from
6767 * UiaGetPropertyValue.
6769 hr = UiaGetPropertyValue(node, UIA_RuntimeIdPropertyId, &v);
6770 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6771 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
6772 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
6773 VariantClear(&v);
6774 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
6777 * Provider_child returns a fragment root that doesn't expose an HWND. On
6778 * Win8+, fragment roots are navigated recursively until either a NULL
6779 * fragment root is returned, the same fragment root as the current one is
6780 * returned, or a fragment root with an HWND is returned.
6782 Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
6783 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
6784 Provider2.hwnd = NULL;
6785 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
6786 Provider.hwnd = NULL;
6787 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
6788 Provider_child.runtime_id[1] = 2;
6789 sa = (void *)0xdeadbeef;
6790 hr = UiaGetRuntimeId(node, &sa);
6791 /* Windows 7 returns S_OK. */
6792 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
6793 ok(!sa, "sa != NULL\n");
6794 ok_method_sequence(get_runtime_id3, "get_runtime_id3");
6796 /* Provider2 returns an HWND. */
6797 Provider.hwnd = NULL;
6798 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
6799 Provider2.hwnd = hwnd;
6800 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
6801 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
6802 Provider_child.runtime_id[1] = rt_id[3] = 2;
6803 sa = NULL;
6804 hr = UiaGetRuntimeId(node, &sa);
6805 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6806 /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */
6807 ok(!!sa || broken(!sa), "sa == NULL\n");
6808 SafeArrayDestroy(sa);
6810 ok_method_sequence(get_runtime_id4, "get_runtime_id4");
6812 /* Test RuntimeId values for different root fragment provider types. */
6813 Provider.frag_root = NULL;
6814 Provider.hwnd = hwnd;
6815 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
6816 Provider_child.runtime_id[1] = rt_id[3] = 2;
6817 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
6818 rt_id[1] = HandleToULong(hwnd);
6819 for (i = 0; i < ARRAY_SIZE(root_prov_opts); i++)
6821 LONG lbound;
6823 Provider.prov_opts = root_prov_opts[i];
6824 sa = NULL;
6825 hr = UiaGetRuntimeId(node, &sa);
6826 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6827 ok(!!sa, "sa == NULL\n");
6829 hr = SafeArrayGetLBound(sa, 1, &lbound);
6830 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
6832 lbound = lbound + 2;
6833 hr = SafeArrayGetElement(sa, &lbound, &tmp);
6834 ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
6835 if (i)
6836 ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n");
6838 rt_id[2] = tmp;
6839 check_runtime_id(rt_id, 4, sa);
6841 SafeArrayDestroy(sa);
6842 ok_method_sequence(get_runtime_id5, "get_runtime_id5");
6845 UiaNodeRelease(node);
6847 /* Test behavior on a node with an associated HWND. */
6848 Provider.prov_opts = ProviderOptions_ClientSideProvider;
6849 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
6850 Provider.hwnd = Provider2.hwnd = hwnd;
6851 prov_root = &Provider2.IRawElementProviderSimple_iface;
6852 node = (void *)0xdeadbeef;
6853 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6854 /* Windows 7 sends this. */
6855 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6856 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
6857 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6858 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6859 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6861 VariantInit(&v);
6862 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6863 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6864 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
6865 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
6866 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
6867 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
6868 VariantClear(&v);
6870 ok_method_sequence(node_from_prov6, "node_from_prov6");
6872 /* No methods called, RuntimeId is based on the node's HWND. */
6873 hr = UiaGetRuntimeId(node, &sa);
6874 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6875 ok(!!sa, "sa == NULL\n");
6876 ok(!sequence_cnt, "Unexpected sequence_cnt %d\n", sequence_cnt);
6878 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
6879 rt_id[1] = HandleToULong(hwnd);
6880 check_runtime_id(rt_id, 2, sa);
6881 SafeArrayDestroy(sa);
6882 UiaNodeRelease(node);
6884 DestroyWindow(hwnd);
6885 UnregisterClassA("UiaGetRuntimeId class", NULL);
6886 CoUninitialize();
6889 static const struct prov_method_sequence node_from_var_seq[] = {
6890 NODE_CREATE_SEQ(&Provider),
6891 { 0 },
6894 static void test_UiaHUiaNodeFromVariant(void)
6896 HUIANODE node, node2;
6897 ULONG node_ref;
6898 HRESULT hr;
6899 VARIANT v;
6901 hr = UiaHUiaNodeFromVariant(NULL, &node);
6902 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6904 hr = UiaHUiaNodeFromVariant(&v, NULL);
6905 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6907 node = (void *)0xdeadbeef;
6908 V_VT(&v) = VT_R8;
6909 hr = UiaHUiaNodeFromVariant(&v, &node);
6910 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6911 ok(!node, "node != NULL\n");
6913 node = NULL;
6914 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
6915 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
6916 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6917 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6918 ok(!!node, "node == NULL\n");
6919 ok_method_sequence(node_from_var_seq, "node_from_var_seq");
6921 node2 = (void *)0xdeadbeef;
6922 V_VT(&v) = VT_UNKNOWN;
6923 V_UNKNOWN(&v) = (IUnknown *)node;
6924 hr = UiaHUiaNodeFromVariant(&v, &node2);
6925 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6926 ok(node == node2, "node != NULL\n");
6928 node_ref = IUnknown_AddRef((IUnknown *)node);
6929 ok(node_ref == 3, "Unexpected node_ref %ld\n", node_ref);
6930 VariantClear(&v);
6931 IUnknown_Release((IUnknown *)node);
6933 #ifdef _WIN64
6934 node2 = (void *)0xdeadbeef;
6935 V_VT(&v) = VT_I4;
6936 V_I4(&v) = 0xbeefdead;
6937 hr = UiaHUiaNodeFromVariant(&v, &node2);
6938 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6939 ok(!node2, "node2 != NULL\n");
6941 node2 = (void *)0xdeadbeef;
6942 V_VT(&v) = VT_I8;
6943 V_I8(&v) = (UINT64)node;
6944 hr = UiaHUiaNodeFromVariant(&v, &node2);
6945 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6946 ok(node2 == (void *)V_I8(&v), "node2 != V_I8\n");
6947 #else
6948 node2 = (void *)0xdeadbeef;
6949 V_VT(&v) = VT_I8;
6950 V_I8(&v) = 0xbeefdead;
6951 hr = UiaHUiaNodeFromVariant(&v, &node2);
6952 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6953 ok(!node2, "node2 != NULL\n");
6955 node2 = (void *)0xdeadbeef;
6956 V_VT(&v) = VT_I4;
6957 V_I4(&v) = (UINT32)node;
6958 hr = UiaHUiaNodeFromVariant(&v, &node2);
6959 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6960 ok(node2 == (void *)V_I4(&v), "node2 != V_I4\n");
6961 #endif
6963 UiaNodeRelease(node);
6966 static const struct prov_method_sequence node_from_hwnd1[] = {
6967 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6968 { 0 }
6971 static const struct prov_method_sequence node_from_hwnd2[] = {
6972 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6973 /* Win10v1507 and below call this. */
6974 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6975 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
6976 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6977 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6978 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6979 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6980 /* Windows 10+ calls this. */
6981 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6982 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6983 { 0 }
6986 static const struct prov_method_sequence node_from_hwnd3[] = {
6987 NODE_CREATE_SEQ2(&Provider),
6988 { &Provider, PROV_GET_PROVIDER_OPTIONS },
6989 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
6990 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
6991 NODE_CREATE_SEQ2_OPTIONAL(&Provider),
6992 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6993 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
6994 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6995 { 0 }
6998 static const struct prov_method_sequence node_from_hwnd4[] = {
6999 { &Provider, PROV_GET_PROPERTY_VALUE },
7000 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7001 /* Win10v1507 and below call this. */
7002 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7003 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7004 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7005 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7006 /* Only called on Windows versions past Win10v1507. */
7007 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7008 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7009 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7010 { 0 }
7013 static const struct prov_method_sequence node_from_hwnd5[] = {
7014 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
7015 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7016 /* Win10v1507 and below call this. */
7017 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7018 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7019 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7020 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7021 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7022 /* Only done in Windows 8+. */
7023 { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
7024 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
7025 /* These two are only done on Windows 7. */
7026 { &Provider_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7027 { &Provider_child, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7028 { 0 }
7031 static const struct prov_method_sequence node_from_hwnd6[] = {
7032 { &Provider, PROV_GET_PROPERTY_VALUE },
7033 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7034 /* Win10v1507 and below call this. */
7035 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7036 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7037 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7038 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7039 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7040 /* Next 4 are only done in Windows 8+. */
7041 { &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
7042 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
7043 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7044 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7045 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7046 /* Next two are only done on Win10v1809+. */
7047 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
7048 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7049 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7050 /* Next two are only done on Win10v1809+. */
7051 { &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
7052 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7053 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7054 { 0 }
7057 static const struct prov_method_sequence node_from_hwnd7[] = {
7058 { &Provider, PROV_GET_PROPERTY_VALUE },
7059 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7060 /* Win10v1507 and below call this. */
7061 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7062 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7063 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7064 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7065 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7066 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7067 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7068 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7069 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7070 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7071 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7072 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7073 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7074 { 0 }
7077 static const struct prov_method_sequence node_from_hwnd8[] = {
7078 NODE_CREATE_SEQ2(&Provider),
7079 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7080 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7081 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
7082 NODE_CREATE_SEQ2_OPTIONAL(&Provider),
7083 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7084 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7085 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7086 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7087 { 0 }
7090 static const struct prov_method_sequence node_from_hwnd9[] = {
7091 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7092 /* Win10v1507 and below call this. */
7093 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7094 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7095 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7096 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7097 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7098 /* Only done in Windows 8+. */
7099 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
7100 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
7101 /* These three are only done on Windows 7. */
7102 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7103 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7104 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
7105 { 0 }
7108 static const struct prov_method_sequence node_from_hwnd10[] = {
7109 NODE_CREATE_SEQ(&Provider),
7110 /* Next two only done on Windows 8+. */
7111 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
7112 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL },
7113 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7114 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win11+. */
7115 { 0 }
7118 static const struct prov_method_sequence disconnect_prov1[] = {
7119 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7120 /* Win10v1507 and below call this. */
7121 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7122 { &Provider_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7123 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7124 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7125 { &Provider_child, PROV_GET_PROVIDER_OPTIONS },
7126 { &Provider_child, FRAG_GET_RUNTIME_ID },
7127 { &Provider_child, FRAG_GET_FRAGMENT_ROOT },
7128 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7129 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7130 { 0 }
7133 static const struct prov_method_sequence disconnect_prov2[] = {
7134 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7135 /* Win10v1507 and below call this. */
7136 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7137 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7138 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7139 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7140 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7141 { &Provider, FRAG_GET_RUNTIME_ID },
7142 { &Provider, FRAG_GET_FRAGMENT_ROOT },
7143 { 0 }
7146 static const struct prov_method_sequence disconnect_prov3[] = {
7147 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7148 /* Win10v1507 and below call this. */
7149 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7150 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7151 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7152 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7153 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7154 { &Provider, FRAG_GET_RUNTIME_ID },
7155 { 0 }
7158 static const struct prov_method_sequence disconnect_prov4[] = {
7159 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7160 /* Win10v1507 and below call this. */
7161 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7162 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7163 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7164 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7165 { 0 }
7168 static void test_UiaNodeFromHandle_client_proc(void)
7170 APTTYPEQUALIFIER apt_qualifier;
7171 APTTYPE apt_type;
7172 WCHAR buf[2048];
7173 HUIANODE node;
7174 HRESULT hr;
7175 DWORD pid;
7176 HWND hwnd;
7177 VARIANT v;
7179 hwnd = FindWindowA("UiaNodeFromHandle class", "Test window");
7181 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7182 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
7184 hr = UiaNodeFromHandle(hwnd, &node);
7185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7187 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7188 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7190 memset(buf, 0, sizeof(buf));
7191 GetWindowThreadProcessId(hwnd, &pid);
7192 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7193 check_node_provider_desc_prefix(buf, pid, hwnd);
7194 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7195 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7196 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7197 check_node_provider_desc_todo(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7199 VariantClear(&v);
7201 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7202 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7203 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
7204 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7207 * On Windows 8 and above, if a node contains a nested provider, the
7208 * process will be in an implicit MTA until the node is released.
7210 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7211 ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
7212 if (SUCCEEDED(hr))
7214 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7215 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7218 UiaNodeRelease(node);
7220 /* Node released, we're out of the implicit MTA. */
7221 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7223 /* Windows 10v1709-1809 are stuck in an implicit MTA. */
7224 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
7225 if (SUCCEEDED(hr))
7227 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7228 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7232 static DWORD WINAPI uia_node_from_handle_test_thread(LPVOID param)
7234 HUIANODE node, node2, node3;
7235 HWND hwnd = (HWND)param;
7236 WCHAR buf[2048];
7237 HRESULT hr;
7238 VARIANT v;
7240 CoInitializeEx(NULL, COINIT_MULTITHREADED);
7242 /* Only sent twice on Windows 11. */
7243 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
7244 /* Only sent on Win7. */
7245 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7246 prov_root = &Provider.IRawElementProviderSimple_iface;
7247 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7248 Provider.hwnd = hwnd;
7249 Provider.runtime_id[0] = Provider.runtime_id[1] = 0;
7250 Provider.frag_root = NULL;
7251 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7252 Provider.ignore_hwnd_prop = TRUE;
7253 hr = UiaNodeFromHandle(hwnd, &node);
7254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7255 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
7256 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7257 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7259 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7260 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7262 memset(buf, 0, sizeof(buf));
7263 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7264 check_node_provider_desc_prefix(buf, GetCurrentProcessId(), hwnd);
7265 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7266 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7267 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7268 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7270 VariantClear(&v);
7272 Provider.ignore_hwnd_prop = FALSE;
7273 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
7275 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7276 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7277 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
7280 * On Windows, nested providers are always called on a separate thread if
7281 * UseComThreading isn't set. Since we're doing COM marshaling, if we're
7282 * currently in an MTA, we just call the nested provider from the current
7283 * thread.
7285 todo_wine ok(Provider.last_call_tid != GetCurrentThreadId() &&
7286 Provider.last_call_tid != GetWindowThreadProcessId(hwnd, NULL), "Expected method call on separate thread\n");
7289 * Elements returned from nested providers have to be able to get a
7290 * RuntimeId, or else we'll get E_FAIL on Win8+.
7292 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
7293 Provider_child.expected_tid = Provider.expected_tid;
7294 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7295 Provider_child.runtime_id[1] = 2;
7296 Provider_child.frag_root = NULL;
7297 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7298 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
7299 if (SUCCEEDED(hr))
7301 hr = UiaHUiaNodeFromVariant(&v, &node2);
7302 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7303 UiaNodeRelease(node2);
7306 ok_method_sequence(node_from_hwnd5, "node_from_hwnd5");
7308 /* RuntimeId check succeeds, we'll get a nested node. */
7309 Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
7310 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7311 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7312 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7314 hr = UiaHUiaNodeFromVariant(&v, &node2);
7315 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7316 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
7317 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7320 * Even though this is a nested node, without any additional
7321 * providers, it will not have the 'Nested' prefix.
7323 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
7324 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
7325 VariantClear(&v);
7327 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
7328 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7329 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7330 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7331 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
7333 UiaNodeRelease(node2);
7336 * There is a delay between nested nodes being released and the
7337 * corresponding IRawElementProviderSimple release on newer Windows
7338 * versions.
7340 if (Provider_child.ref != 1)
7341 Sleep(50);
7342 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7345 * Returned nested elements with an HWND will have client-side providers
7346 * added to them.
7348 Provider_child.hwnd = hwnd;
7349 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7350 /* Only sent on Win7. */
7351 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7352 Provider_child.ignore_hwnd_prop = TRUE;
7353 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7354 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7355 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7356 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7357 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7359 hr = UiaHUiaNodeFromVariant(&v, &node2);
7360 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7361 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
7362 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7364 memset(buf, 0, sizeof(buf));
7365 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", TRUE, buf), "Failed to get nested provider description\n");
7367 check_node_provider_desc_prefix(buf, GetCurrentProcessId(), hwnd);
7368 check_node_provider_desc(buf, L"Main", L"Provider_child", TRUE);
7370 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7371 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7372 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, FALSE);
7373 VariantClear(&v);
7375 Provider_child.ignore_hwnd_prop = FALSE;
7376 ok_method_sequence(node_from_hwnd7, "node_from_hwnd7");
7377 UiaNodeRelease(node2);
7379 if (Provider_child.ref != 1)
7380 Sleep(50);
7381 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7383 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7384 /* Win10v1809 can be slow to call Release on Provider. */
7385 if (Provider.ref != 1)
7386 Sleep(50);
7387 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
7389 /* ProviderOptions_UseComThreading test from a separate thread. */
7390 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7391 /* Only sent on Win7. */
7392 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7393 prov_root = &Provider.IRawElementProviderSimple_iface;
7394 initialize_provider(&Provider, ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading, NULL, FALSE);
7395 Provider.frag_root = NULL;
7396 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
7397 hr = UiaNodeFromHandle(hwnd, &node);
7398 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7399 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7400 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7401 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7403 ok_method_sequence(node_from_hwnd10, "node_from_hwnd10");
7405 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7406 /* Win10v1809 can be slow to call Release on Provider. */
7407 if (Provider.ref != 1)
7408 Sleep(50);
7409 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
7411 if (!pUiaDisconnectProvider)
7413 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
7414 goto exit;
7418 * UiaDisconnectProvider tests.
7420 /* Only sent twice on Windows 11. */
7421 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
7422 prov_root = &Provider.IRawElementProviderSimple_iface;
7423 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7424 Provider.hwnd = hwnd;
7425 Provider.runtime_id[0] = Provider.runtime_id[1] = 0;
7426 Provider.frag_root = NULL;
7427 Provider.ignore_hwnd_prop = TRUE;
7428 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7429 hr = UiaNodeFromHandle(hwnd, &node);
7430 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7431 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
7432 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7434 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7435 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7437 memset(buf, 0, sizeof(buf));
7438 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7439 check_node_provider_desc_prefix(buf, GetCurrentProcessId(), hwnd);
7440 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7441 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7442 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7443 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7444 VariantClear(&v);
7446 Provider.ignore_hwnd_prop = FALSE;
7447 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
7449 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7450 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7451 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
7453 /* Nodes returned from a nested node will be tracked and disconnectable. */
7454 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
7455 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7456 Provider_child.runtime_id[1] = 2;
7457 Provider_child.hwnd = NULL;
7458 Provider_child.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
7459 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7460 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7461 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7463 hr = UiaHUiaNodeFromVariant(&v, &node2);
7464 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7465 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
7466 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7467 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
7468 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
7469 VariantClear(&v);
7471 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
7472 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7473 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7474 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7475 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
7477 /* Get a new node for the same provider. */
7478 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7479 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7480 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
7482 hr = UiaHUiaNodeFromVariant(&v, &node3);
7483 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7484 hr = UiaGetPropertyValue(node3, UIA_ProviderDescriptionPropertyId, &v);
7485 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7486 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
7487 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
7488 VariantClear(&v);
7490 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
7491 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7492 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7493 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7494 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
7497 * Both node2 and node3 represent Provider_child, one call to
7498 * UiaDisconnectProvider disconnects both.
7500 hr = pUiaDisconnectProvider(&Provider_child.IRawElementProviderSimple_iface);
7501 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7502 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7504 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
7505 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
7507 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
7508 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
7509 ok_method_sequence(disconnect_prov1, "disconnect_prov1");
7511 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
7512 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
7515 * Returns same failure code as UiaGetRuntimeId when we fail to get a
7516 * fragment root for AppendRuntimeId.
7518 Provider.hwnd = NULL;
7519 Provider.runtime_id[0] = UiaAppendRuntimeId;
7520 Provider.runtime_id[1] = 2;
7521 Provider.frag_root = NULL;
7522 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
7523 ok(hr == E_FAIL, "Unexpected hr %#lx\n", hr);
7524 ok_method_sequence(disconnect_prov2, "disconnect_prov2");
7527 * Comparisons for disconnection are only based on RuntimeId comparisons,
7528 * not interface pointer values. If an interface returns a NULL RuntimeId,
7529 * no disconnection will occur.
7531 Provider.runtime_id[0] = Provider.runtime_id[1] = 0;
7532 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
7533 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
7534 ok_method_sequence(disconnect_prov3, "disconnect_prov3");
7536 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7537 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7538 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
7540 /* Finally, disconnect node. */
7541 Provider.hwnd = hwnd;
7542 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
7543 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7545 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7546 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
7547 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7548 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
7550 exit:
7551 CoUninitialize();
7553 return 0;
7556 static void test_UiaNodeFromHandle(const char *name)
7558 APTTYPEQUALIFIER apt_qualifier;
7559 PROCESS_INFORMATION proc;
7560 char cmdline[MAX_PATH];
7561 STARTUPINFOA startup;
7562 HUIANODE node, node2;
7563 APTTYPE apt_type;
7564 DWORD exit_code;
7565 WNDCLASSA cls;
7566 HANDLE thread;
7567 HRESULT hr;
7568 HWND hwnd;
7569 VARIANT v;
7571 cls.style = 0;
7572 cls.lpfnWndProc = test_wnd_proc;
7573 cls.cbClsExtra = 0;
7574 cls.cbWndExtra = 0;
7575 cls.hInstance = GetModuleHandleA(NULL);
7576 cls.hIcon = 0;
7577 cls.hCursor = NULL;
7578 cls.hbrBackground = NULL;
7579 cls.lpszMenuName = NULL;
7580 cls.lpszClassName = "UiaNodeFromHandle class";
7581 RegisterClassA(&cls);
7583 hwnd = CreateWindowA("UiaNodeFromHandle class", "Test window", WS_OVERLAPPEDWINDOW,
7584 0, 0, 100, 100, NULL, NULL, NULL, NULL);
7586 hr = UiaNodeFromHandle(hwnd, NULL);
7587 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7589 hr = UiaNodeFromHandle(NULL, &node);
7590 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
7592 /* COM uninitialized, no provider returned by UiaReturnRawElementProvider. */
7593 prov_root = NULL;
7594 node = (void *)0xdeadbeef;
7595 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7596 /* Only sent twice on Win7. */
7597 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
7598 hr = UiaNodeFromHandle(hwnd, &node);
7600 * On all versions of Windows prior to Windows 11, this would fail due to
7601 * COM being uninitialized, presumably because it tries to get an MSAA
7602 * proxy. Windows 11 now has the thread end up in an implicit MTA after
7603 * the call to UiaNodeFromHandle, which is probably why this now succeeds.
7604 * I don't know of anything that relies on this behavior, so for now we
7605 * won't match it.
7607 todo_wine ok(hr == S_OK || broken(hr == E_FAIL), "Unexpected hr %#lx.\n", hr);
7608 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7609 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
7610 if (SUCCEEDED(hr))
7611 UiaNodeRelease(node);
7614 * COM initialized, no provider returned by UiaReturnRawElementProvider.
7615 * In this case, we get a default MSAA proxy.
7617 CoInitializeEx(NULL, COINIT_MULTITHREADED);
7618 prov_root = NULL;
7619 node = (void *)0xdeadbeef;
7620 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7621 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
7622 hr = UiaNodeFromHandle(hwnd, &node);
7623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7624 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7625 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
7627 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7628 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7629 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7630 check_node_provider_desc_todo(V_BSTR(&v), L"Annotation", NULL, FALSE);
7631 check_node_provider_desc_todo(V_BSTR(&v), L"Main", NULL, FALSE);
7632 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7633 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7634 VariantClear(&v);
7636 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7639 * COM initialized, but provider passed into UiaReturnRawElementProvider
7640 * returns a failure code on get_ProviderOptions. Same behavior as before.
7642 Provider.prov_opts = 0;
7643 Provider.hwnd = hwnd;
7644 prov_root = &Provider.IRawElementProviderSimple_iface;
7645 node = (void *)0xdeadbeef;
7646 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7647 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
7648 hr = UiaNodeFromHandle(hwnd, &node);
7649 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7650 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7651 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
7653 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7654 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7655 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7656 check_node_provider_desc_todo(V_BSTR(&v), L"Annotation", NULL, FALSE);
7657 check_node_provider_desc_todo(V_BSTR(&v), L"Main", NULL, FALSE);
7658 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7659 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7660 VariantClear(&v);
7662 ok_method_sequence(node_from_hwnd1, "node_from_hwnd1");
7664 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7667 * COM initialized, but provider passed into UiaReturnRawElementProvider
7668 * on Win8+ will have its RuntimeId queried for UiaDisconnectProvider.
7669 * It will fail due to the lack of a valid fragment root, and we'll fall
7670 * back to an MSAA proxy. On Win7, RuntimeId isn't queried because the
7671 * disconnection functions weren't implemented yet.
7673 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7674 Provider.hwnd = NULL;
7675 prov_root = &Provider.IRawElementProviderSimple_iface;
7676 node = (void *)0xdeadbeef;
7677 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7678 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
7679 Provider.frag_root = NULL;
7680 Provider.runtime_id[0] = UiaAppendRuntimeId;
7681 Provider.runtime_id[1] = 1;
7682 hr = UiaNodeFromHandle(hwnd, &node);
7683 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7684 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
7685 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7686 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
7688 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7689 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7691 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7692 if (Provider.ref == 1 || get_provider_desc(V_BSTR(&v), L"Annotation:", NULL))
7694 check_node_provider_desc_todo(V_BSTR(&v), L"Annotation", NULL, FALSE);
7695 check_node_provider_desc_todo(V_BSTR(&v), L"Main", NULL, FALSE);
7697 else
7698 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
7700 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7701 check_node_provider_desc(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7702 VariantClear(&v);
7704 ok_method_sequence(node_from_hwnd9, "node_from_hwnd9");
7705 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7707 * Bug on Windows 8 through Win10v1709 - if we have a RuntimeId failure,
7708 * refcount doesn't get decremented.
7710 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
7711 if (Provider.ref == 2)
7712 IRawElementProviderSimple_Release(&Provider.IRawElementProviderSimple_iface);
7714 CoUninitialize();
7717 * COM uninitialized, return a Provider from UiaReturnRawElementProvider
7718 * with ProviderOptions_ServerSideProvider.
7720 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7721 Provider.hwnd = hwnd;
7722 prov_root = &Provider.IRawElementProviderSimple_iface;
7723 node = (void *)0xdeadbeef;
7724 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7725 /* Only sent on Win7. */
7726 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7727 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
7728 hr = UiaNodeFromHandle(hwnd, &node);
7729 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7730 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7731 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7732 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7734 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7735 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7736 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
7737 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
7738 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
7739 check_node_provider_desc_todo(V_BSTR(&v), L"Hwnd", NULL, TRUE);
7740 VariantClear(&v);
7742 ok_method_sequence(node_from_hwnd2, "node_from_hwnd2");
7744 /* For same-thread HWND nodes, no disconnection will occur. */
7745 if (pUiaDisconnectProvider)
7747 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
7748 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7750 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
7754 * This is relevant too: Since we don't get a 'nested' node, all calls
7755 * will occur on the current thread.
7757 Provider.expected_tid = GetCurrentThreadId();
7758 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7759 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7760 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
7762 /* UIAutomationType_Element properties will return a normal node. */
7763 Provider_child.prov_opts = ProviderOptions_ServerSideProvider;
7764 Provider_child.hwnd = NULL;
7765 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7766 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7768 hr = UiaHUiaNodeFromVariant(&v, &node2);
7769 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7770 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
7771 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7772 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
7773 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
7774 VariantClear(&v);
7776 Provider_child.expected_tid = GetCurrentThreadId();
7777 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
7778 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7779 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7780 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7781 ok_method_sequence(node_from_hwnd4, "node_from_hwnd4");
7783 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
7785 Provider.expected_tid = Provider_child.expected_tid = 0;
7786 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7789 * On Windows 8 and above, after the first successful call to
7790 * UiaReturnRawElementProvider the process ends up in an implicit MTA
7791 * until the process exits.
7793 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7794 /* Wine's provider thread doesn't always terminate immediately. */
7795 if (hr == S_OK && !strcmp(winetest_platform, "wine"))
7797 Sleep(10);
7798 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7800 todo_wine ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
7801 if (SUCCEEDED(hr))
7803 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7804 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7807 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
7808 thread = CreateThread(NULL, 0, uia_node_from_handle_test_thread, (void *)hwnd, 0, NULL);
7809 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
7811 MSG msg;
7812 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
7814 TranslateMessage(&msg);
7815 DispatchMessageW(&msg);
7818 CloseHandle(thread);
7820 /* Test behavior from separate process. */
7821 Provider.prov_opts = ProviderOptions_ServerSideProvider;
7822 Provider.hwnd = hwnd;
7823 Provider.ignore_hwnd_prop = TRUE;
7824 prov_root = &Provider.IRawElementProviderSimple_iface;
7825 sprintf(cmdline, "\"%s\" uiautomation UiaNodeFromHandle_client_proc", name);
7826 memset(&startup, 0, sizeof(startup));
7827 startup.cb = sizeof(startup);
7828 /* Only called twice on Windows 11. */
7829 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
7830 /* Only sent on Win7. */
7831 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7832 CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
7833 while (MsgWaitForMultipleObjects(1, &proc.hProcess, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
7835 MSG msg;
7836 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
7838 TranslateMessage(&msg);
7839 DispatchMessageW(&msg);
7843 GetExitCodeProcess(proc.hProcess, &exit_code);
7844 if (exit_code > 255)
7845 ok(0, "unhandled exception %08x in child process %04x\n", (UINT)exit_code, (UINT)GetProcessId(proc.hProcess));
7846 else if (exit_code)
7847 ok(0, "%u failures in child process\n", (UINT)exit_code);
7849 CloseHandle(proc.hProcess);
7850 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7851 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7852 Provider.ignore_hwnd_prop = FALSE;
7853 ok_method_sequence(node_from_hwnd8, "node_from_hwnd8");
7855 CoUninitialize();
7857 DestroyWindow(hwnd);
7858 UnregisterClassA("UiaNodeFromHandle class", NULL);
7859 prov_root = NULL;
7862 static const struct prov_method_sequence reg_prov_cb1[] = {
7863 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7864 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
7865 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7866 { 0 }
7869 static const struct prov_method_sequence reg_prov_cb2[] = {
7870 /* These two are only done on Win10v1809+. */
7871 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7872 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7873 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7874 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
7875 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7876 { 0 }
7879 static const struct prov_method_sequence reg_prov_cb3[] = {
7880 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
7881 /* These two are only done on Win10v1809+. */
7882 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7883 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7884 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7885 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7886 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7887 /* These three only done on Win10+. */
7888 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7889 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7890 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7891 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7892 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7893 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7894 { 0 }
7897 static const struct prov_method_sequence reg_prov_cb4[] = {
7898 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
7899 /* These two are only done on Win10v1809+. */
7900 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7901 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7902 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
7903 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7904 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7905 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7906 /* These four only done on Win10+. */
7907 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7908 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7909 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7910 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7911 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
7912 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7913 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7914 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7915 { 0 }
7918 static const struct prov_method_sequence reg_prov_cb5[] = {
7919 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
7920 { 0 }
7923 static const struct prov_method_sequence reg_prov_cb6[] = {
7924 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
7925 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7926 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7927 { 0 }
7930 static const struct prov_method_sequence reg_prov_cb7[] = {
7931 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
7932 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7933 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7934 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7935 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7936 { 0 }
7939 static const struct prov_method_sequence reg_prov_cb8[] = {
7940 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
7941 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7942 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7943 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7944 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7945 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7946 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7947 { 0 }
7950 static const struct prov_method_sequence reg_prov_cb9[] = {
7951 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
7952 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7953 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7954 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7955 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7956 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7957 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7958 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
7959 { 0 }
7962 static const struct prov_method_sequence reg_prov_cb10[] = {
7963 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
7964 /* These two are only done on Win10v1809+. */
7965 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7966 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7967 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
7968 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7969 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7970 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7971 /* These four only done on Win10+. */
7972 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7973 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7974 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7975 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7976 { 0 }
7979 static const struct prov_method_sequence reg_prov_cb11[] = {
7980 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7981 /* Win10v1507 and below call this. */
7982 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7983 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
7984 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7985 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7986 { &Provider, PROV_GET_PROVIDER_OPTIONS },
7987 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
7988 /* These two are only done on Win10v1809+. */
7989 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
7990 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7991 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7992 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7993 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7994 /* These three only done on Win10+. */
7995 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7996 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7997 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
7998 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7999 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8000 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8001 { 0 }
8004 static const struct prov_method_sequence reg_prov_cb12[] = {
8005 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8006 /* Win10v1507 and below call this. */
8007 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8008 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8009 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8010 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8011 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8012 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8013 /* Win10v1507 and below call this. */
8014 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8015 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
8016 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8017 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8018 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8019 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_TODO },
8020 /* These two are only done on Win10v1809+. */
8021 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8022 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8023 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8024 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8025 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8026 /* These three only done on Win10+. */
8027 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8028 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8029 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8030 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8031 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8032 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8033 { 0 }
8036 static const struct prov_method_sequence reg_prov_cb13[] = {
8037 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8038 /* Win10v1507 and below call this. */
8039 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8040 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
8041 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8042 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8043 { &Provider, PROV_GET_PROVIDER_OPTIONS },
8044 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8045 /* Win10v1507 and below call this. */
8046 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8047 { &Provider2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
8048 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8049 { &Provider2, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
8050 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8051 /* Provider override only retrieved successfully on Win10v1809+ */
8052 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8053 { &Provider_override, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8054 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8055 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8056 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8057 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1507 and below. */
8058 /* These two are only done on Win10v1809+. */
8059 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
8060 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8061 /* Only done on Win10v1809+. */
8062 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8063 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8064 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8065 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8066 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8067 /* These three only done on Win10+. */
8068 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8069 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8070 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
8071 /* Only done on Win10v1809+. */
8072 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
8073 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8074 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8075 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8076 { 0 }
8079 static IRawElementProviderSimple *base_hwnd_prov, *proxy_prov, *parent_proxy_prov, *nc_prov;
8080 static SAFEARRAY WINAPI *test_uia_provider_callback(HWND hwnd, enum ProviderType prov_type)
8082 IRawElementProviderSimple *elprov = NULL;
8084 switch (prov_type)
8086 case ProviderType_BaseHwnd:
8087 CHECK_EXPECT(prov_callback_base_hwnd);
8088 if (hwnd == Provider_hwnd3.hwnd)
8089 elprov = &Provider_hwnd3.IRawElementProviderSimple_iface;
8090 else if (hwnd == Provider_hwnd2.hwnd)
8091 elprov = &Provider_hwnd2.IRawElementProviderSimple_iface;
8092 else
8093 elprov = base_hwnd_prov;
8094 break;
8096 case ProviderType_Proxy:
8097 if (Provider_proxy.hwnd == hwnd)
8099 CHECK_EXPECT(prov_callback_proxy);
8100 elprov = proxy_prov;
8102 else if (hwnd == GetParent(Provider_proxy.hwnd))
8104 CHECK_EXPECT(prov_callback_parent_proxy);
8105 elprov = parent_proxy_prov;
8107 break;
8109 case ProviderType_NonClientArea:
8110 CHECK_EXPECT(prov_callback_nonclient);
8111 if (hwnd == Provider_nc3.hwnd)
8112 elprov = &Provider_nc3.IRawElementProviderSimple_iface;
8113 else if (hwnd == Provider_nc2.hwnd)
8114 elprov = &Provider_nc2.IRawElementProviderSimple_iface;
8115 else
8116 elprov = nc_prov;
8117 break;
8119 default:
8120 break;
8123 if (elprov)
8125 SAFEARRAY *sa;
8126 LONG idx = 0;
8128 sa = SafeArrayCreateVector(VT_UNKNOWN, 0, 1);
8129 if (sa)
8130 SafeArrayPutElement(sa, &idx, (void *)elprov);
8132 return sa;
8135 return NULL;
8138 static void test_UiaRegisterProviderCallback(void)
8140 HWND hwnd, hwnd2;
8141 WNDCLASSA cls;
8142 HUIANODE node;
8143 HRESULT hr;
8144 VARIANT v;
8146 cls.style = 0;
8147 cls.lpfnWndProc = test_wnd_proc;
8148 cls.cbClsExtra = 0;
8149 cls.cbWndExtra = 0;
8150 cls.hInstance = GetModuleHandleA(NULL);
8151 cls.hIcon = 0;
8152 cls.hCursor = NULL;
8153 cls.hbrBackground = NULL;
8154 cls.lpszMenuName = NULL;
8155 cls.lpszClassName = "UiaRegisterProviderCallback class";
8157 RegisterClassA(&cls);
8159 cls.lpfnWndProc = child_test_wnd_proc;
8160 cls.lpszClassName = "UiaRegisterProviderCallback child class";
8161 RegisterClassA(&cls);
8163 hwnd = CreateWindowA("UiaRegisterProviderCallback class", "Test window", WS_OVERLAPPEDWINDOW,
8164 0, 0, 100, 100, NULL, NULL, NULL, NULL);
8166 hwnd2 = CreateWindowA("UiaRegisterProviderCallback child class", "Test child window", WS_CHILD,
8167 0, 0, 100, 100, hwnd, NULL, NULL, NULL);
8169 UiaRegisterProviderCallback(test_uia_provider_callback);
8171 /* No providers returned by UiaRootObjectId or the provider callback. */
8172 Provider_proxy.hwnd = hwnd2;
8173 child_win_prov_root = prov_root = NULL;
8174 node = (void *)0xdeadbeef;
8175 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8176 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8177 SET_EXPECT(prov_callback_base_hwnd);
8178 SET_EXPECT(prov_callback_nonclient);
8179 SET_EXPECT(prov_callback_proxy);
8180 SET_EXPECT(prov_callback_parent_proxy);
8181 hr = UiaNodeFromHandle(hwnd2, &node);
8182 /* Windows 7 returns S_OK with a NULL HUIANODE. */
8183 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
8184 ok(!node, "node != NULL\n");
8185 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8186 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8187 CHECK_CALLED(prov_callback_base_hwnd);
8188 CHECK_CALLED(prov_callback_nonclient);
8189 CHECK_CALLED(prov_callback_proxy);
8190 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8192 /* Return only nonclient proxy provider. */
8193 base_hwnd_prov = proxy_prov = parent_proxy_prov = NULL;
8194 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
8195 child_win_prov_root = prov_root = NULL;
8196 node = (void *)0xdeadbeef;
8197 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8198 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8199 SET_EXPECT(prov_callback_base_hwnd);
8200 SET_EXPECT(prov_callback_nonclient);
8201 SET_EXPECT(prov_callback_proxy);
8202 SET_EXPECT(prov_callback_parent_proxy);
8203 hr = UiaNodeFromHandle(hwnd2, &node);
8204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8205 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
8206 ok(!!node, "node == NULL\n");
8207 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8208 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8209 CHECK_CALLED(prov_callback_base_hwnd);
8210 CHECK_CALLED(prov_callback_nonclient);
8211 CHECK_CALLED(prov_callback_proxy);
8212 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8214 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8215 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8216 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8217 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
8218 VariantClear(&v);
8220 ok_method_sequence(reg_prov_cb1, "reg_prov_cb1");
8222 UiaNodeRelease(node);
8223 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
8225 /* Return only base_hwnd provider. */
8226 nc_prov = proxy_prov = parent_proxy_prov = NULL;
8227 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
8228 child_win_prov_root = prov_root = NULL;
8229 node = (void *)0xdeadbeef;
8230 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8231 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8232 SET_EXPECT(prov_callback_base_hwnd);
8233 SET_EXPECT(prov_callback_nonclient);
8234 SET_EXPECT(prov_callback_proxy);
8235 SET_EXPECT(prov_callback_parent_proxy);
8236 hr = UiaNodeFromHandle(hwnd2, &node);
8237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8238 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8239 ok(!!node, "node == NULL\n");
8240 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8241 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8242 CHECK_CALLED(prov_callback_base_hwnd);
8243 CHECK_CALLED(prov_callback_nonclient);
8244 CHECK_CALLED(prov_callback_proxy);
8245 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8247 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8248 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8249 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8250 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", TRUE);
8251 VariantClear(&v);
8253 ok_method_sequence(reg_prov_cb2, "reg_prov_cb2");
8255 UiaNodeRelease(node);
8256 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8258 /* Return providers for all ProviderTypes. */
8259 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
8260 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
8261 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
8262 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
8263 Provider_proxy.hwnd = hwnd2;
8264 child_win_prov_root = prov_root = NULL;
8265 node = (void *)0xdeadbeef;
8266 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8267 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8268 SET_EXPECT(prov_callback_base_hwnd);
8269 SET_EXPECT(prov_callback_nonclient);
8270 SET_EXPECT(prov_callback_proxy);
8271 SET_EXPECT(prov_callback_parent_proxy);
8272 hr = UiaNodeFromHandle(hwnd2, &node);
8273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8274 ok(!!node, "node == NULL\n");
8275 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
8276 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
8277 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
8278 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8279 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8280 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8281 CHECK_CALLED(prov_callback_base_hwnd);
8282 CHECK_CALLED(prov_callback_nonclient);
8283 CHECK_CALLED(prov_callback_proxy);
8284 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8286 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8287 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8288 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8289 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
8290 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
8291 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8292 VariantClear(&v);
8294 ok_method_sequence(reg_prov_cb3, "reg_prov_cb3");
8296 UiaNodeRelease(node);
8297 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
8298 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
8299 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8301 /* Return an override provider from Provider_proxy2. */
8302 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
8303 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
8304 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
8305 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
8306 Provider_proxy2.override_hwnd = hwnd2;
8307 child_win_prov_root = prov_root = NULL;
8308 node = (void *)0xdeadbeef;
8309 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8310 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8311 SET_EXPECT(prov_callback_base_hwnd);
8312 SET_EXPECT(prov_callback_nonclient);
8313 SET_EXPECT(prov_callback_proxy);
8314 SET_EXPECT(prov_callback_parent_proxy);
8315 hr = UiaNodeFromHandle(hwnd2, &node);
8316 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8317 ok(!!node, "node == NULL\n");
8318 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
8319 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
8320 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
8321 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8322 todo_wine ok(Provider_override.ref == 2, "Unexpected refcnt %ld\n", Provider_override.ref);
8323 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8324 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8325 CHECK_CALLED(prov_callback_base_hwnd);
8326 CHECK_CALLED(prov_callback_nonclient);
8327 CHECK_CALLED(prov_callback_proxy);
8328 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8330 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8331 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8332 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8333 check_node_provider_desc_todo(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
8334 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider_proxy", FALSE);
8335 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
8336 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8337 VariantClear(&v);
8339 ok_method_sequence(reg_prov_cb4, "reg_prov_cb4");
8342 * Test the order that Providers are queried for properties. The order is:
8343 * Override provider.
8344 * Main provider.
8345 * Nonclient provider.
8346 * Hwnd provider.
8348 * UI Automation tries to get a property from each in this order until one
8349 * returns a value. If none do, the property isn't supported.
8351 if (Provider_override.ref == 2)
8353 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8354 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8355 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
8356 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8357 ok_method_sequence(reg_prov_cb5, "reg_prov_cb5");
8360 /* Property retrieved from Provider_proxy (Main) */
8361 Provider_override.ret_invalid_prop_type = TRUE;
8362 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8363 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8364 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
8365 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8366 ok_method_sequence(reg_prov_cb6, "reg_prov_cb6");
8368 /* Property retrieved from Provider_nc (Nonclient) */
8369 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
8370 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8371 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8372 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
8373 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8374 ok_method_sequence(reg_prov_cb7, "reg_prov_cb7");
8376 /* Property retrieved from Provider_hwnd (Hwnd) */
8377 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
8378 Provider_nc.ret_invalid_prop_type = TRUE;
8379 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8380 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8381 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
8382 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8383 ok_method_sequence(reg_prov_cb8, "reg_prov_cb8");
8385 /* Property retrieved from none of the providers. */
8386 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
8387 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = TRUE;
8388 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8389 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8390 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
8391 ok_method_sequence(reg_prov_cb9, "reg_prov_cb9");
8393 UiaNodeRelease(node);
8394 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
8395 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
8396 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
8397 ok(Provider_override.ref == 1, "Unexpected refcnt %ld\n", Provider_override.ref);
8398 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = FALSE;
8399 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = FALSE;
8402 * Provider_hwnd has ProviderOptions_UseComThreading, and COM hasn't been
8403 * initialized. One provider failing will cause the entire node to fail
8404 * creation on Win10+.
8406 Provider_hwnd.prov_opts = ProviderOptions_ClientSideProvider | ProviderOptions_UseComThreading;
8407 node = (void *)0xdeadbeef;
8408 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8409 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8410 SET_EXPECT(prov_callback_base_hwnd);
8411 SET_EXPECT(prov_callback_nonclient);
8412 SET_EXPECT(prov_callback_proxy);
8413 SET_EXPECT(prov_callback_parent_proxy);
8414 hr = UiaNodeFromHandle(hwnd2, &node);
8415 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
8416 ok(!node || broken(!!node), "node != NULL\n");
8417 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8418 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8419 CHECK_CALLED(prov_callback_base_hwnd);
8420 CHECK_CALLED(prov_callback_nonclient);
8421 CHECK_CALLED(prov_callback_proxy);
8422 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8423 ok_method_sequence(reg_prov_cb10, "reg_prov_cb10");
8424 UiaNodeRelease(node);
8425 Provider_hwnd.prov_opts = ProviderOptions_ClientSideProvider;
8428 * Provider returned by UiaRootObjectId on hwnd2. No ProviderType_Proxy
8429 * callback for hwnd2.
8431 Provider.hwnd = hwnd2;
8432 Provider.prov_opts = ProviderOptions_ServerSideProvider;
8433 child_win_prov_root = &Provider.IRawElementProviderSimple_iface;
8434 Provider_proxy2.override_hwnd = NULL;
8435 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8436 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8437 SET_EXPECT(prov_callback_base_hwnd);
8438 SET_EXPECT(prov_callback_nonclient);
8439 SET_EXPECT(prov_callback_parent_proxy);
8440 hr = UiaNodeFromHandle(hwnd2, &node);
8441 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8442 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8443 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8444 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8445 CHECK_CALLED(prov_callback_base_hwnd);
8446 CHECK_CALLED(prov_callback_nonclient);
8447 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8449 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8450 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8451 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8452 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
8453 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8454 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
8455 VariantClear(&v);
8457 ok_method_sequence(reg_prov_cb11, "reg_prov_cb11");
8459 UiaNodeRelease(node);
8462 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
8463 * doesn't give an HWND override provider, UIA will attempt to get a proxy
8464 * provider to check it for an HWND override provider.
8466 Provider.hwnd = hwnd2;
8467 Provider2.hwnd = hwnd;
8468 Provider.prov_opts = Provider2.prov_opts = ProviderOptions_ServerSideProvider;
8469 child_win_prov_root = &Provider.IRawElementProviderSimple_iface;
8470 prov_root = &Provider2.IRawElementProviderSimple_iface;
8471 Provider_proxy2.override_hwnd = NULL;
8472 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8473 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8474 SET_EXPECT(prov_callback_base_hwnd);
8475 SET_EXPECT(prov_callback_nonclient);
8476 SET_EXPECT(prov_callback_parent_proxy);
8477 hr = UiaNodeFromHandle(hwnd2, &node);
8478 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8479 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8480 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8481 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8482 CHECK_CALLED(prov_callback_base_hwnd);
8483 CHECK_CALLED(prov_callback_nonclient);
8484 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
8486 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8487 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8488 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8489 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
8490 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8491 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
8492 VariantClear(&v);
8494 ok_method_sequence(reg_prov_cb12, "reg_prov_cb12");
8496 UiaNodeRelease(node);
8499 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
8500 * returns an HWND override, no ProviderType_Proxy callback for hwnd.
8502 Provider.hwnd = hwnd2;
8503 Provider2.hwnd = hwnd;
8504 Provider2.override_hwnd = Provider_override.hwnd = hwnd2;
8505 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = TRUE;
8506 Provider.prov_opts = Provider2.prov_opts = ProviderOptions_ServerSideProvider;
8507 child_win_prov_root = &Provider.IRawElementProviderSimple_iface;
8508 prov_root = &Provider2.IRawElementProviderSimple_iface;
8509 Provider_proxy2.override_hwnd = NULL;
8510 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8511 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
8512 SET_EXPECT(prov_callback_base_hwnd);
8513 SET_EXPECT(prov_callback_nonclient);
8514 SET_EXPECT(prov_callback_parent_proxy);
8515 hr = UiaNodeFromHandle(hwnd2, &node);
8516 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8517 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8518 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8519 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
8520 CHECK_CALLED(prov_callback_base_hwnd);
8521 CHECK_CALLED(prov_callback_nonclient);
8523 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8524 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8525 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
8526 check_node_provider_desc_todo(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
8527 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
8528 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
8529 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
8530 VariantClear(&v);
8532 ok_method_sequence(reg_prov_cb13, "reg_prov_cb13");
8534 UiaNodeRelease(node);
8536 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = FALSE;
8537 UiaRegisterProviderCallback(NULL);
8539 DestroyWindow(hwnd);
8540 UnregisterClassA("UiaRegisterProviderCallback class", NULL);
8541 UnregisterClassA("UiaRegisterProviderCallback child class", NULL);
8544 static void set_cache_request(struct UiaCacheRequest *req, struct UiaCondition *view_cond, int scope,
8545 PROPERTYID *prop_ids, int prop_ids_count, PATTERNID *pattern_ids, int pattern_ids_count, int elem_mode)
8547 req->pViewCondition = view_cond;
8548 req->Scope = scope;
8550 req->pProperties = prop_ids;
8551 req->cProperties = prop_ids_count;
8552 req->pPatterns = pattern_ids;
8553 req->cPatterns = pattern_ids_count;
8555 req->automationElementMode = elem_mode;
8558 static void set_property_condition(struct UiaPropertyCondition *cond, int prop_id, VARIANT *val, int flags)
8560 cond->ConditionType = ConditionType_Property;
8561 cond->PropertyId = prop_id;
8562 cond->Value = *val;
8563 cond->Flags = flags;
8566 static void set_and_or_condition(struct UiaAndOrCondition *cond, int cond_type,
8567 struct UiaCondition **conds, int cond_count)
8569 cond->ConditionType = cond_type;
8570 cond->ppConditions = conds;
8571 cond->cConditions = cond_count;
8574 static void set_not_condition(struct UiaNotCondition *cond, struct UiaCondition *not_cond)
8576 cond->ConditionType = ConditionType_Not;
8577 cond->pConditions = not_cond;
8580 #define MAX_NODE_PROVIDERS 4
8581 struct node_provider_desc {
8582 DWORD pid;
8583 HWND hwnd;
8585 const WCHAR *prov_type[MAX_NODE_PROVIDERS];
8586 const WCHAR *prov_name[MAX_NODE_PROVIDERS];
8587 BOOL parent_link[MAX_NODE_PROVIDERS];
8588 struct node_provider_desc *nested_desc[MAX_NODE_PROVIDERS];
8589 int prov_count;
8592 static void init_node_provider_desc(struct node_provider_desc *desc, DWORD pid, HWND hwnd)
8594 memset(desc, 0, sizeof(*desc));
8595 desc->pid = pid;
8596 desc->hwnd = hwnd;
8599 static void add_nested_provider_desc(struct node_provider_desc *desc, const WCHAR *prov_type, const WCHAR *prov_name,
8600 BOOL parent_link, struct node_provider_desc *nested_desc)
8602 desc->prov_type[desc->prov_count] = prov_type;
8603 desc->prov_name[desc->prov_count] = prov_name;
8604 desc->parent_link[desc->prov_count] = parent_link;
8605 desc->nested_desc[desc->prov_count] = nested_desc;
8606 desc->prov_count++;
8609 static void add_provider_desc(struct node_provider_desc *desc, const WCHAR *prov_type, const WCHAR *prov_name,
8610 BOOL parent_link)
8612 add_nested_provider_desc(desc, prov_type, prov_name, parent_link, NULL);
8615 #define test_node_provider_desc( desc, desc_str ) \
8616 test_node_provider_desc_( (desc), (desc_str), __FILE__, __LINE__)
8617 static void test_node_provider_desc_(struct node_provider_desc *desc, BSTR desc_str, const char *file, int line)
8619 int i;
8621 check_node_provider_desc_prefix_(desc_str, desc->pid, desc->hwnd, file, line);
8622 for (i = 0; i < desc->prov_count; i++)
8624 if (desc->nested_desc[i])
8626 WCHAR buf[2048];
8628 ok_(file, line)(get_nested_provider_desc(desc_str, desc->prov_type[i], desc->parent_link[i], buf),
8629 "Failed to get nested provider description\n");
8630 test_node_provider_desc_(desc->nested_desc[i], buf, file, line);
8632 else
8633 check_node_provider_desc_(desc_str, desc->prov_type[i], desc->prov_name[i], desc->parent_link[i], FALSE, file, line);
8638 * Cache requests are returned as a two dimensional safearray, with the first
8639 * dimension being the element index, and the second index being the
8640 * node/property/pattern value index for the element. The first element value is
8641 * always an HUIANODE, followed by requested property values, and finally
8642 * requested pattern handles.
8644 #define test_cache_req_sa( sa, exp_lbound, exp_elems, exp_node_desc ) \
8645 test_cache_req_sa_( (sa), (exp_lbound), (exp_elems), (exp_node_desc), __FILE__, __LINE__)
8646 static void test_cache_req_sa_(SAFEARRAY *sa, LONG exp_lbound[2], LONG exp_elems[2],
8647 struct node_provider_desc *exp_node_desc, const char *file, int line)
8649 HUIANODE node;
8650 HRESULT hr;
8651 VARTYPE vt;
8652 VARIANT v;
8653 UINT dims;
8654 int i;
8656 hr = SafeArrayGetVartype(sa, &vt);
8657 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8658 ok_(file, line)(vt == VT_VARIANT, "Unexpected vt %d\n", vt);
8660 dims = SafeArrayGetDim(sa);
8661 ok_(file, line)(dims == 2, "Unexpected dims %d\n", dims);
8663 for (i = 0; i < 2; i++)
8665 LONG lbound, ubound, elems;
8667 lbound = ubound = elems = 0;
8668 hr = SafeArrayGetLBound(sa, 1 + i, &lbound);
8669 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
8670 ok_(file, line)(exp_lbound[i] == lbound, "Unexpected lbound[%d] %ld\n", i, lbound);
8672 hr = SafeArrayGetUBound(sa, 1 + i, &ubound);
8673 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
8675 elems = (ubound - lbound) + 1;
8676 ok_(file, line)(exp_elems[i] == elems, "Unexpected elems[%d] %ld\n", i, elems);
8679 for (i = 0; i < exp_elems[0]; i++)
8681 LONG idx[2] = { (exp_lbound[0] + i), exp_lbound[1] };
8683 hr = SafeArrayGetElement(sa, idx, &v);
8684 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8686 hr = UiaHUiaNodeFromVariant(&v, &node);
8687 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8688 VariantClear(&v);
8690 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8691 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8692 test_node_provider_desc_(&exp_node_desc[i], V_BSTR(&v), file, line);
8693 VariantClear(&v);
8695 UiaNodeRelease(node);
8699 static const struct prov_method_sequence cache_req_seq1[] = {
8700 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8701 { 0 }
8705 * Win10v1507 and below will attempt to do parent navigation if the
8706 * conditional check fails.
8708 static const struct prov_method_sequence cache_req_seq2[] = {
8709 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8710 { 0 }
8713 static const struct prov_method_sequence cache_req_seq3[] = {
8714 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
8715 NODE_CREATE_SEQ(&Provider_child),
8716 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8717 NODE_CREATE_SEQ(&Provider_child2),
8718 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
8719 /* Navigates towards parent to check for clientside provider siblings. */
8720 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8721 NODE_CREATE_SEQ(&Provider),
8722 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8723 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8724 { 0 }
8727 static const struct prov_method_sequence cache_req_seq4[] = {
8728 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
8729 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8730 { 0 }
8733 /* Sequence for non-matching property condition. */
8734 static const struct prov_method_sequence cache_req_seq5[] = {
8735 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
8736 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* Dependent upon property condition. */
8737 /* Only done on Win10v1507 and below. */
8738 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8739 { 0 }
8742 static const struct prov_method_sequence cache_req_seq6[] = {
8743 { &Provider, FRAG_GET_RUNTIME_ID },
8744 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8745 /* Only done on Win10v1507 and below. */
8746 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8747 { 0 }
8750 static const struct prov_method_sequence cache_req_seq7[] = {
8751 { &Provider, FRAG_GET_RUNTIME_ID },
8752 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId. */
8753 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8754 { 0 }
8757 static const struct prov_method_sequence cache_req_seq8[] = {
8758 NODE_CREATE_SEQ(&Provider_child),
8759 { 0 }
8762 static const struct prov_method_sequence cache_req_seq9[] = {
8763 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
8764 /* Done twice on Windows, but we shouldn't need to replicate this. */
8765 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_IsControlElementPropertyId */
8766 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8767 NODE_CREATE_SEQ(&Provider),
8768 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
8769 /* Only done on Win10v1507 and below. */
8770 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8771 { 0 }
8774 static const struct prov_method_sequence cache_req_seq10[] = {
8775 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
8776 /* Done twice on Windows, but we shouldn't need to replicate this. */
8777 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_IsControlElementPropertyId */
8778 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8779 NODE_CREATE_SEQ(&Provider),
8780 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
8781 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
8782 { 0 }
8785 static const struct UiaCondition UiaTrueCondition = { ConditionType_True };
8786 static const struct UiaCondition UiaFalseCondition = { ConditionType_False };
8787 static void test_UiaGetUpdatedCache(void)
8789 LONG exp_lbound[2], exp_elems[2], idx[2], i;
8790 struct Provider_prop_override prop_override;
8791 struct node_provider_desc exp_node_desc[2];
8792 struct UiaPropertyCondition prop_cond;
8793 struct UiaAndOrCondition and_or_cond;
8794 struct UiaCacheRequest cache_req;
8795 struct UiaCondition *cond_arr[2];
8796 struct UiaNotCondition not_cond;
8797 VARIANT v, v_arr[2];
8798 SAFEARRAY *out_req;
8799 IUnknown *unk_ns;
8800 BSTR tree_struct;
8801 int prop_ids[2];
8802 HUIANODE node;
8803 HRESULT hr;
8805 CoInitializeEx(NULL, COINIT_MULTITHREADED);
8807 hr = UiaGetReservedNotSupportedValue(&unk_ns);
8808 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8810 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
8811 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
8813 Provider.prov_opts = ProviderOptions_ServerSideProvider;
8814 Provider.hwnd = NULL;
8815 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
8816 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8817 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8819 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8820 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8821 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
8822 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
8823 VariantClear(&v);
8825 ok_method_sequence(node_from_prov2, NULL);
8827 /* NULL arg tests. */
8828 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8829 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, NULL);
8830 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
8832 hr = UiaGetUpdatedCache(node, NULL, NormalizeState_None, NULL, &out_req, &tree_struct);
8833 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
8835 hr = UiaGetUpdatedCache(NULL, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
8836 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
8839 * Cache request with NULL view condition, doesn't matter with
8840 * NormalizeState_None as passed in HUIANODE isn't evaluated against any
8841 * condition.
8843 tree_struct = NULL; out_req = NULL;
8844 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
8845 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8846 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
8847 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8848 ok(!!out_req, "out_req == NULL\n");
8849 ok(!!tree_struct, "tree_struct == NULL\n");
8851 exp_lbound[0] = exp_lbound[1] = 0;
8852 exp_elems[0] = exp_elems[1] = 1;
8853 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8854 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8855 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
8857 SafeArrayDestroy(out_req);
8858 SysFreeString(tree_struct);
8861 * NormalizeState_View, HUIANODE gets checked against the ConditionType_False
8862 * condition within the cache request structure, nothing is returned.
8864 tree_struct = NULL; out_req = NULL;
8865 set_cache_request(&cache_req, (struct UiaCondition *)&UiaFalseCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8866 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
8867 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8868 ok(!out_req, "out_req != NULL\n");
8870 /* Empty tree structure string. */
8871 ok(!!tree_struct, "tree_struct == NULL\n");
8872 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
8873 SysFreeString(tree_struct);
8874 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
8877 * NormalizeState_View, HUIANODE gets checked against the ConditionType_True
8878 * condition within the cache request structure, returns this HUIANODE.
8880 tree_struct = NULL; out_req = NULL;
8881 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8882 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
8883 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8884 ok(!!out_req, "out_req == NULL\n");
8885 ok(!!tree_struct, "tree_struct == NULL\n");
8887 exp_lbound[0] = exp_lbound[1] = 0;
8888 exp_elems[0] = exp_elems[1] = 1;
8889 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8890 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8891 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
8893 SafeArrayDestroy(out_req);
8894 SysFreeString(tree_struct);
8897 * NormalizeState_Custom, HUIANODE gets checked against our passed in
8898 * ConditionType_False condition.
8900 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8901 tree_struct = NULL; out_req = NULL;
8902 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaFalseCondition, &out_req, &tree_struct);
8903 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8904 ok(!out_req, "out_req != NULL\n");
8906 /* Empty tree structure string. */
8907 ok(!!tree_struct, "tree_struct == NULL\n");
8908 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
8909 SysFreeString(tree_struct);
8911 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
8914 * NormalizeState_Custom, HUIANODE gets checked against the ConditionType_True
8915 * condition we pass in, returns this HUIANODE.
8917 tree_struct = NULL; out_req = NULL;
8918 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
8919 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaTrueCondition, &out_req, &tree_struct);
8920 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8921 ok(!!out_req, "out_req == NULL\n");
8922 ok(!!tree_struct, "tree_struct == NULL\n");
8924 exp_lbound[0] = exp_lbound[1] = 0;
8925 exp_elems[0] = exp_elems[1] = 1;
8926 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8927 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8928 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
8930 SafeArrayDestroy(out_req);
8931 SysFreeString(tree_struct);
8934 * CacheRequest with TreeScope_Children.
8936 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
8937 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
8938 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
8939 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
8940 tree_struct = NULL; out_req = NULL;
8941 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Children, NULL, 0, NULL, 0, AutomationElementMode_Full);
8942 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
8943 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8944 todo_wine ok(!!out_req, "out_req == NULL\n");
8945 todo_wine ok(!!tree_struct, "tree_struct == NULL\n");
8946 todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
8947 todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
8948 if (out_req)
8950 exp_elems[0] = 2;
8951 exp_elems[1] = 1;
8952 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8954 ok(!wcscmp(tree_struct, L"(P)P))"), "tree structure %s\n", debugstr_w(tree_struct));
8955 ok_method_sequence(cache_req_seq3, "cache_req_seq3");
8958 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8959 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
8960 SafeArrayDestroy(out_req);
8961 SysFreeString(tree_struct);
8964 * ConditionType_And tests.
8966 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
8967 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
8968 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
8969 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
8970 cond_arr[1] = (struct UiaCondition *)&UiaTrueCondition;
8971 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
8972 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
8973 AutomationElementMode_Full);
8974 tree_struct = NULL; out_req = NULL;
8976 /* Equivalent to: if (1 && 1) */
8977 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
8978 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8979 ok(!!out_req, "out_req == NULL\n");
8980 ok(!!tree_struct, "tree_struct == NULL\n");
8982 exp_lbound[0] = exp_lbound[1] = 0;
8983 exp_elems[0] = exp_elems[1] = 1;
8984 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
8985 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
8986 ok_method_sequence(cache_req_seq1, NULL);
8988 SafeArrayDestroy(out_req);
8989 SysFreeString(tree_struct);
8991 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
8992 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
8993 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
8994 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
8995 AutomationElementMode_Full);
8996 tree_struct = NULL; out_req = NULL;
8998 /* Equivalent to: if (1 && 0) */
8999 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9000 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9001 ok_method_sequence(cache_req_seq2, NULL);
9002 ok(!out_req, "out_req != NULL\n");
9003 ok(!!tree_struct, "tree_struct == NULL\n");
9004 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9006 SysFreeString(tree_struct);
9009 * ConditionType_Or tests.
9011 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9012 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9013 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
9014 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9015 AutomationElementMode_Full);
9016 tree_struct = NULL; out_req = NULL;
9018 /* Equivalent to: if (1 || 0) */
9019 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9020 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9021 ok(!!out_req, "out_req == NULL\n");
9022 ok(!!tree_struct, "tree_struct == NULL\n");
9024 exp_lbound[0] = exp_lbound[1] = 0;
9025 exp_elems[0] = exp_elems[1] = 1;
9026 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9027 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9028 ok_method_sequence(cache_req_seq1, NULL);
9030 SafeArrayDestroy(out_req);
9031 SysFreeString(tree_struct);
9033 cond_arr[0] = (struct UiaCondition *)&UiaFalseCondition;
9034 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9035 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
9036 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9037 AutomationElementMode_Full);
9038 tree_struct = NULL; out_req = NULL;
9040 /* Equivalent to: if (0 || 0) */
9041 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9043 ok_method_sequence(cache_req_seq2, NULL);
9044 ok(!out_req, "out_req != NULL\n");
9045 ok(!!tree_struct, "tree_struct == NULL\n");
9046 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9048 SysFreeString(tree_struct);
9051 * ConditionType_Not tests.
9053 set_not_condition(&not_cond, (struct UiaCondition *)&UiaFalseCondition);
9054 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
9055 AutomationElementMode_Full);
9056 tree_struct = NULL; out_req = NULL;
9058 /* Equivalent to: if (!0) */
9059 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9060 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9061 ok(!!out_req, "out_req == NULL\n");
9062 ok(!!tree_struct, "tree_struct == NULL\n");
9064 exp_lbound[0] = exp_lbound[1] = 0;
9065 exp_elems[0] = exp_elems[1] = 1;
9066 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9067 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9068 ok_method_sequence(cache_req_seq1, NULL);
9070 SafeArrayDestroy(out_req);
9071 SysFreeString(tree_struct);
9073 set_not_condition(&not_cond, (struct UiaCondition *)&UiaTrueCondition);
9074 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
9075 AutomationElementMode_Full);
9076 tree_struct = NULL; out_req = NULL;
9078 /* Equivalent to: if (!1) */
9079 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9080 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9081 ok(!out_req, "out_req != NULL\n");
9082 ok(!!tree_struct, "tree_struct == NULL\n");
9083 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9084 SysFreeString(tree_struct);
9085 ok_method_sequence(cache_req_seq2, NULL);
9088 * ConditionType_Property tests.
9090 Provider.ret_invalid_prop_type = FALSE;
9092 /* Test UIAutomationType_IntArray property conditions. */
9093 if (UiaLookupId(AutomationIdentifierType_Property, &OutlineColor_Property_GUID))
9095 V_VT(&v) = VT_I4 | VT_ARRAY;
9096 V_ARRAY(&v) = create_i4_safearray();
9097 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
9098 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
9099 AutomationElementMode_Full);
9100 tree_struct = NULL; out_req = NULL;
9102 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9104 ok(!!out_req, "out_req == NULL\n");
9105 ok(!!tree_struct, "tree_struct == NULL\n");
9107 exp_lbound[0] = exp_lbound[1] = 0;
9108 exp_elems[0] = exp_elems[1] = 1;
9109 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9110 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9111 ok_method_sequence(cache_req_seq4, NULL);
9113 SafeArrayDestroy(out_req);
9114 SysFreeString(tree_struct);
9115 VariantClear(&v);
9117 /* Same values, except we're short by one element. */
9118 V_VT(&v) = VT_I4 | VT_ARRAY;
9119 V_ARRAY(&v) = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(uia_i4_arr_prop_val) - 1);
9121 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val) - 1; i++)
9122 SafeArrayPutElement(V_ARRAY(&prop_cond.Value), &i, (void *)&uia_i4_arr_prop_val[i]);
9124 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
9125 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
9126 AutomationElementMode_Full);
9127 tree_struct = NULL; out_req = NULL;
9129 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9130 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9131 ok_method_sequence(cache_req_seq5, NULL);
9132 ok(!out_req, "out_req != NULL\n");
9133 ok(!!tree_struct, "tree_struct == NULL\n");
9134 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9136 SysFreeString(tree_struct);
9137 VariantClear(&v);
9139 else
9140 win_skip("UIA_OutlineColorPropertyId unavailable, skipping property condition tests for it.\n");
9142 /* UIA_RuntimeIdPropertyId comparison. */
9143 Provider.runtime_id[0] = 0xdeadbeef; Provider.runtime_id[1] = 0xfeedbeef;
9144 V_VT(&v) = VT_I4 | VT_ARRAY;
9145 V_ARRAY(&v) = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(Provider.runtime_id));
9146 for (i = 0; i < ARRAY_SIZE(Provider.runtime_id); i++)
9147 SafeArrayPutElement(V_ARRAY(&v), &i, (void *)&Provider.runtime_id[i]);
9149 set_property_condition(&prop_cond, UIA_RuntimeIdPropertyId, &v, PropertyConditionFlags_None);
9150 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
9151 AutomationElementMode_Full);
9152 tree_struct = NULL; out_req = NULL;
9154 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9155 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9156 ok(!!out_req, "out_req == NULL\n");
9157 ok(!!tree_struct, "tree_struct == NULL\n");
9159 exp_lbound[0] = exp_lbound[1] = 0;
9160 exp_elems[0] = exp_elems[1] = 1;
9161 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9162 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9163 ok_method_sequence(cache_req_seq6, NULL);
9165 SafeArrayDestroy(out_req);
9166 SysFreeString(tree_struct);
9167 VariantClear(&prop_cond.Value);
9169 /* UIAutomationType_Bool property condition tests. */
9170 prop_override.prop_id = UIA_IsControlElementPropertyId;
9171 V_VT(&prop_override.val) = VT_BOOL;
9172 V_BOOL(&prop_override.val) = VARIANT_FALSE;
9173 Provider.prop_override = &prop_override;
9174 Provider.prop_override_count = 1;
9176 V_VT(&v) = VT_BOOL;
9177 V_BOOL(&v) = VARIANT_FALSE;
9178 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
9179 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
9180 AutomationElementMode_Full);
9181 tree_struct = NULL; out_req = NULL;
9183 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9184 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9185 ok(!!out_req, "out_req == NULL\n");
9186 ok(!!tree_struct, "tree_struct == NULL\n");
9188 exp_lbound[0] = exp_lbound[1] = 0;
9189 exp_elems[0] = exp_elems[1] = 1;
9190 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9191 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9192 ok_method_sequence(cache_req_seq4, NULL);
9194 SafeArrayDestroy(out_req);
9195 SysFreeString(tree_struct);
9196 VariantClear(&v);
9199 * Provider now returns VARIANT_TRUE for UIA_IsControlElementPropertyId,
9200 * conditional check will fail.
9202 prop_override.prop_id = UIA_IsControlElementPropertyId;
9203 V_VT(&prop_override.val) = VT_BOOL;
9204 V_BOOL(&prop_override.val) = VARIANT_TRUE;
9205 Provider.prop_override = &prop_override;
9206 Provider.prop_override_count = 1;
9208 V_VT(&v) = VT_BOOL;
9209 V_BOOL(&v) = VARIANT_FALSE;
9210 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
9211 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
9212 AutomationElementMode_Full);
9213 tree_struct = NULL; out_req = NULL;
9215 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9217 ok_method_sequence(cache_req_seq5, NULL);
9218 ok(!out_req, "out_req != NULL\n");
9219 ok(!!tree_struct, "tree_struct == NULL\n");
9220 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9222 SysFreeString(tree_struct);
9223 VariantClear(&v);
9225 Provider.prop_override = NULL;
9226 Provider.prop_override_count = 0;
9229 * Tests for property value caching.
9231 prop_ids[0] = UIA_RuntimeIdPropertyId;
9232 /* Invalid property ID, no work will be done. */
9233 prop_ids[1] = 1;
9234 tree_struct = NULL; out_req = NULL;
9235 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
9236 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9237 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9238 ok(!out_req, "out_req != NULL\n");
9239 ok(!tree_struct, "tree_struct != NULL\n");
9242 * Retrieve values for UIA_RuntimeIdPropertyId and
9243 * UIA_IsControlElementPropertyId in the returned cache.
9245 prop_ids[0] = UIA_RuntimeIdPropertyId;
9246 prop_ids[1] = UIA_IsControlElementPropertyId;
9247 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
9248 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9249 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9251 tree_struct = NULL; out_req = NULL;
9252 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
9253 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9255 ok(!!out_req, "out_req == NULL\n");
9256 ok(!!tree_struct, "tree_struct == NULL\n");
9258 exp_lbound[0] = exp_lbound[1] = 0;
9259 exp_elems[0] = 1;
9260 exp_elems[1] = 3;
9261 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9262 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9264 idx[0] = 0;
9265 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
9267 idx[1] = 1 + i;
9268 VariantInit(&v_arr[i]);
9269 hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
9270 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9273 ok(V_VT(&v_arr[0]) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
9274 ok(V_UNKNOWN(&v_arr[0]) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v_arr[0]));
9275 VariantClear(&v_arr[0]);
9277 ok(check_variant_bool(&v_arr[1], TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
9278 VariantClear(&v_arr[1]);
9280 ok_method_sequence(cache_req_seq7, "cache_req_seq7");
9281 SafeArrayDestroy(out_req);
9282 SysFreeString(tree_struct);
9285 * Again, but return a valid runtime ID and a different value for
9286 * UIA_IsControlElementPropertyId.
9288 V_VT(&v) = VT_BOOL;
9289 V_BOOL(&v) = VARIANT_FALSE;
9290 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
9291 set_provider_prop_override(&Provider, &prop_override, 1);
9292 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
9293 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9294 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9296 tree_struct = NULL; out_req = NULL;
9297 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
9298 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9300 ok(!!out_req, "out_req == NULL\n");
9301 ok(!!tree_struct, "tree_struct == NULL\n");
9303 exp_lbound[0] = exp_lbound[1] = 0;
9304 exp_elems[0] = 1;
9305 exp_elems[1] = 3;
9306 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9307 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9309 idx[0] = 0;
9310 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
9312 idx[1] = 1 + i;
9313 VariantInit(&v_arr[i]);
9314 hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
9315 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9318 ok(V_VT(&v_arr[0]) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v_arr[0]));
9319 check_runtime_id(Provider.runtime_id, ARRAY_SIZE(Provider.runtime_id), V_ARRAY(&v_arr[0]));
9320 VariantClear(&v_arr[0]);
9322 ok(check_variant_bool(&v_arr[1], FALSE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
9323 VariantClear(&v_arr[1]);
9325 ok_method_sequence(cache_req_seq7, "cache_req_seq7");
9326 SafeArrayDestroy(out_req);
9327 SysFreeString(tree_struct);
9329 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
9330 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
9332 /* Normalization navigation tests. */
9333 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
9334 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
9336 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
9337 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9338 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9339 ok_method_sequence(cache_req_seq8, "cache_req_seq8");
9342 * Neither Provider_child or Provider match this condition, return
9343 * nothing.
9345 variant_init_bool(&v, FALSE);
9346 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
9347 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
9348 tree_struct = NULL; out_req = NULL;
9349 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9350 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9351 ok(!out_req, "out_req != NULL\n");
9352 ok(!!tree_struct, "tree_struct == NULL\n");
9353 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9354 SysFreeString(tree_struct);
9355 ok_method_sequence(cache_req_seq9, "cache_req_seq9");
9358 * Provider now matches our condition, we'll get Provider in the cache
9359 * request.
9361 variant_init_bool(&v, FALSE);
9362 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
9363 set_provider_prop_override(&Provider, &prop_override, 1);
9364 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9365 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9367 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
9368 tree_struct = NULL; out_req = NULL;
9369 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9371 ok(!!out_req, "out_req == NULL\n");
9372 ok(!!tree_struct, "tree_struct == NULL\n");
9373 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9375 exp_lbound[0] = exp_lbound[1] = 0;
9376 exp_elems[0] = exp_elems[1] = 1;
9377 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9378 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9379 ok_method_sequence(cache_req_seq10, "cache_req_seq10");
9381 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
9382 SafeArrayDestroy(out_req);
9383 SysFreeString(tree_struct);
9384 VariantClear(&v);
9386 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
9387 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
9388 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
9389 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
9391 IUnknown_Release(unk_ns);
9392 CoUninitialize();
9395 static const struct prov_method_sequence nav_seq1[] = {
9396 NODE_CREATE_SEQ2(&Provider),
9397 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9398 /* Only done on Win10v1809+ */
9399 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9400 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9401 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9402 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9403 /* Windows 10+ calls these. */
9404 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9405 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9406 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9407 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9408 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9409 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9410 { 0 }
9413 static const struct prov_method_sequence nav_seq2[] = {
9414 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9415 NODE_CREATE_SEQ(&Provider_hwnd_child),
9416 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9417 { 0 }
9420 static const struct prov_method_sequence nav_seq3[] = {
9421 { &Provider_hwnd_child, FRAG_NAVIGATE}, /* NavigateDirection_NextSibling */
9422 NODE_CREATE_SEQ(&Provider_hwnd_child2),
9423 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9424 { 0 }
9427 static const struct prov_method_sequence nav_seq4[] = {
9428 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9429 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9430 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS },
9431 /* All Windows versions use the NativeWindowHandle provider type check here. */
9432 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
9433 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9434 NODE_CREATE_SEQ2(&Provider),
9435 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9436 /* Only done on Win10v1809+ */
9437 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9438 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9439 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9440 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9441 /* Windows 10+ calls these. */
9442 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9443 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9444 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9445 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9446 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS },
9447 /* Win10v1507 and below call this. */
9448 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
9449 { &Provider_nc_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9450 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
9451 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9452 /* Only called on Windows versions past Win10v1507. */
9453 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9454 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9455 { 0 }
9458 static const struct prov_method_sequence nav_seq5[] = {
9459 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
9460 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9461 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS },
9462 { &Provider_nc, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9463 NODE_CREATE_SEQ2(&Provider),
9464 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9465 /* Only done on Win10v1809+ */
9466 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9467 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9468 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9469 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9470 /* Windows 10+ calls these. */
9471 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9472 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9473 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9474 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
9475 NODE_CREATE_SEQ(&Provider_hwnd_child2),
9476 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9477 { 0 }
9480 static const struct prov_method_sequence nav_seq6[] = {
9481 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9482 NODE_CREATE_SEQ(&Provider_nc_child2),
9483 { &Provider_nc_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9484 { 0 }
9487 static const struct prov_method_sequence nav_seq7[] = {
9488 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9489 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9490 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS },
9491 { &Provider_nc, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9492 NODE_CREATE_SEQ2(&Provider),
9493 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9494 /* Only done on Win10v1809+ */
9495 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9496 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9497 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9498 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9499 /* Windows 10+ calls these. */
9500 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9501 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9502 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9503 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9504 NODE_CREATE_SEQ(&Provider_child),
9505 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9506 { 0 }
9509 static const struct prov_method_sequence nav_seq8[] = {
9510 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9511 NODE_CREATE_SEQ(&Provider_child2),
9512 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9513 { 0 }
9516 static const struct prov_method_sequence nav_seq9[] = {
9517 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9518 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9519 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9520 /* Win10v1507 and below call this. */
9521 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
9522 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9523 NODE_CREATE_SEQ2(&Provider),
9524 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9525 /* Only done on Win10v1809+ */
9526 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9527 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9528 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9529 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9530 /* Windows 10+ calls these. */
9531 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9532 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9533 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9534 /* Navigates to parent a second time. */
9535 { &Provider_child2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
9536 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
9537 /* Win10v1507 and below call this. */
9538 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
9539 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
9540 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
9541 /* Win10v1507 and below call this. */
9542 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
9543 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO },
9544 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
9545 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
9546 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
9547 /* Only done on Win10v1809+ */
9548 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9549 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
9550 { &Provider_nc, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
9551 { &Provider_hwnd, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
9552 /* Windows 10+ calls these. */
9553 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9554 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9555 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9558 static const struct prov_method_sequence nav_seq10[] = {
9559 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
9560 NODE_CREATE_SEQ(&Provider_child2),
9561 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9562 { 0 }
9565 static const struct prov_method_sequence nav_seq11[] = {
9566 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9567 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS },
9568 /* All Windows versions use the NativeWindowHandle provider type check here. */
9569 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
9570 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9571 NODE_CREATE_SEQ2(&Provider),
9572 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9573 /* Only done on Win10v1809+ */
9574 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9575 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9576 /* Windows 10+ calls these. */
9577 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9578 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9579 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9580 { &Provider_hwnd_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9581 NODE_CREATE_SEQ(&Provider_hwnd_child2),
9582 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9583 { 0 }
9586 static const struct prov_method_sequence nav_seq12[] = {
9587 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
9588 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS },
9589 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
9590 { &Provider_child2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
9591 NODE_CREATE_SEQ2(&Provider),
9592 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9593 /* Only done on Win10v1809+ */
9594 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9595 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9596 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9597 /* Windows 10+ calls these. */
9598 { &Provider_child2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9599 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9600 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9601 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
9602 NODE_CREATE_SEQ(&Provider_child),
9603 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9604 { 0 }
9607 static const struct prov_method_sequence nav_seq13[] = {
9608 NODE_CREATE_SEQ2(&Provider),
9609 { &Provider, PROV_GET_PROVIDER_OPTIONS },
9610 /* Only done on Win10v1809+ */
9611 { &Provider_hwnd, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
9612 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9613 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9614 /* Windows 10+ calls these. */
9615 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9616 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9617 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
9618 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9619 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9620 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9621 { 0 }
9624 static const struct prov_method_sequence nav_seq14[] = {
9625 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9626 NODE_CREATE_SEQ(&Provider2),
9627 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9628 { 0 }
9631 static const struct prov_method_sequence nav_seq15[] = {
9632 NODE_CREATE_SEQ(&Provider_child2_child_child),
9633 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9636 static const struct prov_method_sequence nav_seq16[] = {
9637 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9638 NODE_CREATE_SEQ(&Provider_child2_child),
9639 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9640 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9641 NODE_CREATE_SEQ(&Provider_child2),
9642 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9643 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9644 NODE_CREATE_SEQ(&Provider),
9645 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9646 /* Only done on Win10v1507 and below. */
9647 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9648 { 0 }
9651 static const struct prov_method_sequence nav_seq17[] = {
9652 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9653 NODE_CREATE_SEQ(&Provider_child2_child),
9654 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9655 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9656 NODE_CREATE_SEQ(&Provider_child2),
9657 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9658 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9659 NODE_CREATE_SEQ(&Provider),
9660 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9661 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
9662 { 0 }
9665 static void set_provider_nav_ifaces(struct Provider *prov, struct Provider *parent, struct Provider *frag_root,
9666 struct Provider *prev_sibling, struct Provider *next_sibling, struct Provider *first_child,
9667 struct Provider *last_child)
9669 prov->parent = NULL;
9670 prov->frag_root = NULL;
9671 prov->prev_sibling = NULL;
9672 prov->next_sibling = NULL;
9673 prov->first_child = NULL;
9674 prov->last_child = NULL;
9676 if (parent)
9677 prov->parent = &parent->IRawElementProviderFragment_iface;
9678 if (frag_root)
9679 prov->frag_root = &frag_root->IRawElementProviderFragmentRoot_iface;
9680 if (prev_sibling)
9681 prov->prev_sibling = &prev_sibling->IRawElementProviderFragment_iface;
9682 if (next_sibling)
9683 prov->next_sibling = &next_sibling->IRawElementProviderFragment_iface;
9684 if (first_child)
9685 prov->first_child = &first_child->IRawElementProviderFragment_iface;
9686 if (last_child)
9687 prov->last_child = &last_child->IRawElementProviderFragment_iface;
9690 static void test_UiaNavigate(void)
9692 struct Provider_prop_override prop_override;
9693 LONG exp_lbound[2], exp_elems[2], idx[2], i;
9694 struct node_provider_desc exp_node_desc[4];
9695 struct UiaPropertyCondition prop_cond;
9696 struct UiaCacheRequest cache_req;
9697 HUIANODE node, node2, node3;
9698 SAFEARRAY *out_req;
9699 BSTR tree_struct;
9700 WNDCLASSA cls;
9701 HRESULT hr;
9702 VARIANT v;
9703 HWND hwnd;
9705 CoInitializeEx(NULL, COINIT_MULTITHREADED);
9706 cls.style = 0;
9707 cls.lpfnWndProc = test_wnd_proc;
9708 cls.cbClsExtra = 0;
9709 cls.cbWndExtra = 0;
9710 cls.hInstance = GetModuleHandleA(NULL);
9711 cls.hIcon = 0;
9712 cls.hCursor = NULL;
9713 cls.hbrBackground = NULL;
9714 cls.lpszMenuName = NULL;
9715 cls.lpszClassName = "UiaNavigate class";
9717 RegisterClassA(&cls);
9719 hwnd = CreateWindowA("UiaNavigate class", "Test window", WS_OVERLAPPEDWINDOW,
9720 0, 0, 100, 100, NULL, NULL, NULL, NULL);
9722 UiaRegisterProviderCallback(test_uia_provider_callback);
9723 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9724 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9726 set_provider_nav_ifaces(&Provider_nc, NULL, NULL, NULL, NULL, &Provider_nc_child, &Provider_nc_child2);
9727 set_provider_nav_ifaces(&Provider_nc_child, &Provider_nc, &Provider_nc, NULL,
9728 &Provider_nc_child2, NULL, NULL);
9729 set_provider_nav_ifaces(&Provider_nc_child2, &Provider_nc, &Provider_nc, &Provider_nc_child,
9730 NULL, NULL, NULL);
9732 set_provider_nav_ifaces(&Provider_hwnd, NULL, NULL, NULL, NULL, &Provider_hwnd_child, &Provider_hwnd_child2);
9733 set_provider_nav_ifaces(&Provider_hwnd_child, &Provider_hwnd, &Provider_hwnd, NULL,
9734 &Provider_hwnd_child2, NULL, NULL);
9735 set_provider_nav_ifaces(&Provider_hwnd_child2, &Provider_hwnd, &Provider_hwnd, &Provider_hwnd_child,
9736 NULL, NULL, NULL);
9739 * Show navigation behavior for multi-provider nodes. Navigation order is:
9740 * HWND provider children.
9741 * Non-Client provider children.
9742 * Main provider children.
9743 * Override provider children.
9745 Provider.prov_opts = ProviderOptions_ServerSideProvider;
9746 Provider.hwnd = Provider_hwnd.hwnd = Provider_nc.hwnd = hwnd;
9747 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = TRUE;
9748 prov_root = &Provider.IRawElementProviderSimple_iface;
9749 node = (void *)0xdeadbeef;
9750 /* Only sent on Win7. */
9751 SET_EXPECT(winproc_GETOBJECT_CLIENT);
9752 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9753 SET_EXPECT(prov_callback_base_hwnd);
9754 SET_EXPECT(prov_callback_nonclient);
9755 hr = UiaNodeFromHandle(hwnd, &node);
9756 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9757 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9758 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9759 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9760 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9761 CHECK_CALLED(prov_callback_base_hwnd);
9762 CHECK_CALLED(prov_callback_nonclient);
9763 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
9765 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9766 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9767 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
9768 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9769 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9770 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9771 VariantClear(&v);
9773 ok_method_sequence(nav_seq1, "nav_seq1");
9775 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9776 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
9777 idx[0] = idx[1] = 0;
9779 /* Navigate to Provider_hwnd_child. */
9780 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child", TRUE);
9781 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
9782 tree_struct = NULL; out_req = NULL;
9783 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &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 ok(Provider_hwnd_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
9789 node2 = node3 = NULL;
9790 hr = SafeArrayGetElement(out_req, idx, &v);
9791 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9793 hr = UiaHUiaNodeFromVariant(&v, &node2);
9794 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9795 IUnknown_AddRef((IUnknown *)node2);
9797 exp_lbound[0] = exp_lbound[1] = 0;
9798 exp_elems[0] = exp_elems[1] = 1;
9799 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9801 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9802 ok_method_sequence(nav_seq2, "nav_seq2");
9804 SafeArrayDestroy(out_req);
9805 SysFreeString(tree_struct);
9807 /* Navigate to Provider_hwnd_child2. */
9808 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9809 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
9810 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
9811 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9812 ok(!!out_req, "out_req == NULL\n");
9813 ok(!!tree_struct, "tree_struct == NULL\n");
9814 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
9816 hr = SafeArrayGetElement(out_req, idx, &v);
9817 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9819 hr = UiaHUiaNodeFromVariant(&v, &node3);
9820 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9821 IUnknown_AddRef((IUnknown *)node3);
9823 exp_lbound[0] = exp_lbound[1] = 0;
9824 exp_elems[0] = exp_elems[1] = 1;
9825 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(nav_seq3, "nav_seq3");
9830 SafeArrayDestroy(out_req);
9831 SysFreeString(tree_struct);
9833 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9834 ok(Provider_hwnd_child.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
9835 node2 = node3;
9837 /* Navigate to Provider_nc_child. */
9838 SET_EXPECT(prov_callback_nonclient);
9839 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9840 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9841 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child", TRUE);
9842 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
9843 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9844 ok(!!out_req, "out_req == NULL\n");
9845 ok(!!tree_struct, "tree_struct == NULL\n");
9846 ok(Provider_nc_child.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
9847 CHECK_CALLED(prov_callback_nonclient);
9848 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9850 hr = SafeArrayGetElement(out_req, idx, &v);
9851 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9853 hr = UiaHUiaNodeFromVariant(&v, &node3);
9854 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9855 IUnknown_AddRef((IUnknown *)node3);
9857 exp_lbound[0] = exp_lbound[1] = 0;
9858 exp_elems[0] = exp_elems[1] = 1;
9859 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9861 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9862 ok_method_sequence(nav_seq4, "nav_seq4");
9864 SafeArrayDestroy(out_req);
9865 SysFreeString(tree_struct);
9867 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9868 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
9869 node2 = node3;
9871 /* Navigate back to Provider_hwnd_child2. */
9872 SET_EXPECT(prov_callback_base_hwnd);
9873 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9874 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9875 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
9876 hr = UiaNavigate(node2, NavigateDirection_PreviousSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
9877 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9878 ok(!!out_req, "out_req == NULL\n");
9879 ok(!!tree_struct, "tree_struct == NULL\n");
9880 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
9881 CHECK_CALLED(prov_callback_base_hwnd);
9882 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9884 hr = SafeArrayGetElement(out_req, idx, &v);
9885 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9887 hr = UiaHUiaNodeFromVariant(&v, &node3);
9888 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9889 IUnknown_AddRef((IUnknown *)node3);
9891 exp_lbound[0] = exp_lbound[1] = 0;
9892 exp_elems[0] = exp_elems[1] = 1;
9893 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9895 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9896 ok_method_sequence(nav_seq5, "nav_seq5");
9898 SafeArrayDestroy(out_req);
9899 SysFreeString(tree_struct);
9901 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
9902 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
9904 /* Navigate to Provider_nc_child2. */
9905 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9906 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child2", TRUE);
9907 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
9908 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9909 ok(!!out_req, "out_req == NULL\n");
9910 ok(!!tree_struct, "tree_struct == NULL\n");
9911 ok(Provider_nc_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
9913 hr = SafeArrayGetElement(out_req, idx, &v);
9914 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9916 hr = UiaHUiaNodeFromVariant(&v, &node3);
9917 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9918 IUnknown_AddRef((IUnknown *)node3);
9920 exp_lbound[0] = exp_lbound[1] = 0;
9921 exp_elems[0] = exp_elems[1] = 1;
9922 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9924 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9925 ok_method_sequence(nav_seq6, "nav_seq6");
9927 SafeArrayDestroy(out_req);
9928 SysFreeString(tree_struct);
9930 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9931 ok(Provider_nc_child.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
9932 node2 = node3;
9934 /* Navigate to Provider_child. */
9935 SET_EXPECT(prov_callback_base_hwnd);
9936 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9937 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9938 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9939 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
9940 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9941 ok(!!out_req, "out_req == NULL\n");
9942 ok(!!tree_struct, "tree_struct == NULL\n");
9943 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9944 CHECK_CALLED(prov_callback_base_hwnd);
9945 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9947 hr = SafeArrayGetElement(out_req, idx, &v);
9948 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9950 hr = UiaHUiaNodeFromVariant(&v, &node3);
9951 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9952 IUnknown_AddRef((IUnknown *)node3);
9954 exp_lbound[0] = exp_lbound[1] = 0;
9955 exp_elems[0] = exp_elems[1] = 1;
9956 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9958 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9959 ok_method_sequence(nav_seq7, "nav_seq7");
9961 SafeArrayDestroy(out_req);
9962 SysFreeString(tree_struct);
9964 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9965 ok(Provider_nc_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
9966 node2 = node3;
9968 /* Navigate to Provider_child2. */
9969 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
9970 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
9971 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
9972 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9973 ok(!!out_req, "out_req == NULL\n");
9974 ok(!!tree_struct, "tree_struct == NULL\n");
9975 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9977 hr = SafeArrayGetElement(out_req, idx, &v);
9978 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9980 hr = UiaHUiaNodeFromVariant(&v, &node3);
9981 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9982 IUnknown_AddRef((IUnknown *)node3);
9984 exp_lbound[0] = exp_lbound[1] = 0;
9985 exp_elems[0] = exp_elems[1] = 1;
9986 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9988 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9989 ok_method_sequence(nav_seq8, "nav_seq8");
9991 SafeArrayDestroy(out_req);
9992 SysFreeString(tree_struct);
9994 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
9995 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
9996 node2 = node3;
9998 /* Try navigating to next sibling on the final child of the node. */
9999 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
10000 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
10001 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
10002 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10003 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10004 ok_method_sequence(nav_seq9, "nav_seq9");
10005 ok(!out_req, "out_req != NULL\n");
10006 ok(!tree_struct, "tree_struct != NULL\n");
10007 todo_wine CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
10008 todo_wine CHECK_CALLED_MULTI(prov_callback_base_hwnd, 2);
10009 todo_wine CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, 2);
10011 SafeArrayDestroy(out_req);
10012 SysFreeString(tree_struct);
10013 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10014 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
10016 /* Navigate to Provider_child2, last child. */
10017 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10018 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
10019 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10020 tree_struct = NULL;
10021 out_req = NULL;
10022 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10023 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10024 ok(!!out_req, "out_req == NULL\n");
10025 ok(!!tree_struct, "tree_struct == NULL\n");
10026 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10028 exp_lbound[0] = exp_lbound[1] = 0;
10029 exp_elems[0] = exp_elems[1] = 1;
10030 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10032 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10033 ok_method_sequence(nav_seq10, "nav_seq10");
10035 SafeArrayDestroy(out_req);
10036 SysFreeString(tree_struct);
10039 * If the child we navigate to from a parent isn't considered the "parent
10040 * link" of it's HUIANODE, it is skipped. Here, we set Provider_hwnd_child
10041 * to an HWND provider, and set its main provider as Provider, which is
10042 * the parent link of the node.
10044 Provider_hwnd_child.hwnd = hwnd;
10045 Provider_hwnd_child.prov_opts = ProviderOptions_ClientSideProvider;
10046 Provider.parent = &Provider2.IRawElementProviderFragment_iface;
10047 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10048 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10049 tree_struct = NULL;
10050 out_req = NULL;
10051 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10052 SET_EXPECT(prov_callback_nonclient);
10053 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10054 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10055 ok(!!out_req, "out_req == NULL\n");
10056 ok(!!tree_struct, "tree_struct == NULL\n");
10057 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10058 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10059 CHECK_CALLED(prov_callback_nonclient);
10061 hr = SafeArrayGetElement(out_req, idx, &v);
10062 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10064 hr = UiaHUiaNodeFromVariant(&v, &node2);
10065 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10066 IUnknown_AddRef((IUnknown *)node2);
10068 exp_lbound[0] = exp_lbound[1] = 0;
10069 exp_elems[0] = exp_elems[1] = 1;
10070 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10072 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10073 ok_method_sequence(nav_seq11, "nav_seq11");
10075 SafeArrayDestroy(out_req);
10076 SysFreeString(tree_struct);
10078 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10079 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10082 * Same test as before, except with NavigateDirection_LastChild. This will
10083 * end up with Provider_nc as the parent link for the node instead of
10084 * Provider_child2.
10086 Provider_child2.hwnd = hwnd;
10087 Provider_child2.ignore_hwnd_prop = TRUE;
10088 Provider_child2.parent = NULL;
10089 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
10090 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
10091 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10092 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10093 tree_struct = NULL;
10094 out_req = NULL;
10095 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10096 SET_EXPECT(prov_callback_nonclient);
10097 SET_EXPECT(prov_callback_base_hwnd);
10098 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10099 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10100 ok(!!out_req, "out_req == NULL\n");
10101 ok(!!tree_struct, "tree_struct == NULL\n");
10102 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10103 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10104 CHECK_CALLED(prov_callback_nonclient);
10105 CHECK_CALLED(prov_callback_base_hwnd);
10107 hr = SafeArrayGetElement(out_req, idx, &v);
10108 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10110 hr = UiaHUiaNodeFromVariant(&v, &node2);
10111 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10112 IUnknown_AddRef((IUnknown *)node2);
10114 exp_lbound[0] = exp_lbound[1] = 0;
10115 exp_elems[0] = exp_elems[1] = 1;
10116 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10118 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10119 ok_method_sequence(nav_seq12, "nav_seq12");
10121 SafeArrayDestroy(out_req);
10122 SysFreeString(tree_struct);
10124 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10125 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10127 Provider_child2.hwnd = NULL;
10128 Provider_child2.ignore_hwnd_prop = FALSE;
10129 Provider_child2.parent = &Provider.IRawElementProviderFragment_iface;
10131 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10132 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10133 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
10134 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
10136 /* Create a node with Provider_nc as the parent link. */
10137 Provider.parent = Provider_hwnd.parent = NULL;
10138 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
10139 Provider2.prov_opts = ProviderOptions_ServerSideProvider;
10140 Provider2.hwnd = NULL;
10142 node = (void *)0xdeadbeef;
10143 /* Only sent on Win7. */
10144 SET_EXPECT(winproc_GETOBJECT_CLIENT);
10145 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10146 SET_EXPECT(prov_callback_base_hwnd);
10147 SET_EXPECT(prov_callback_nonclient);
10148 hr = UiaNodeFromHandle(hwnd, &node);
10149 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10150 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10151 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
10152 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
10153 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10154 CHECK_CALLED(prov_callback_base_hwnd);
10155 CHECK_CALLED(prov_callback_nonclient);
10156 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
10158 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
10159 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10160 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
10161 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
10162 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
10163 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
10164 VariantClear(&v);
10166 ok_method_sequence(nav_seq13, "nav_seq13");
10168 /* Navigate to Provider2, parent of Provider_nc. */
10169 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10170 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider2", TRUE);
10171 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10172 tree_struct = NULL;
10173 out_req = NULL;
10174 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10175 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10176 ok(!!out_req, "out_req == NULL\n");
10177 ok(!!tree_struct, "tree_struct == NULL\n");
10178 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
10180 exp_lbound[0] = exp_lbound[1] = 0;
10181 exp_elems[0] = exp_elems[1] = 1;
10182 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10184 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10186 SafeArrayDestroy(out_req);
10187 SysFreeString(tree_struct);
10188 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
10189 ok_method_sequence(nav_seq14, "nav_seq14");
10191 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10192 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10193 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
10194 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
10196 Provider_hwnd_child.hwnd = NULL;
10197 Provider_hwnd_child.prov_opts = ProviderOptions_ServerSideProvider;
10198 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = FALSE;
10199 base_hwnd_prov = nc_prov = NULL;
10200 prov_root = NULL;
10201 UiaRegisterProviderCallback(NULL);
10204 * Conditional navigation for conditions other than ConditionType_True.
10206 initialize_provider_tree(TRUE);
10207 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
10208 provider_add_child(&Provider, &Provider_child2);
10209 provider_add_child(&Provider_child2, &Provider_child2_child);
10210 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
10212 hr = UiaNodeFromProvider(&Provider_child2_child_child.IRawElementProviderSimple_iface, &node);
10213 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10214 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
10216 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
10217 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10218 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
10219 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child2_child_child", TRUE);
10220 VariantClear(&v);
10222 ok_method_sequence(nav_seq15, "nav_seq15");
10225 * Navigate from Provider_child2_child_child to a parent that has
10226 * UIA_IsControlElementPropertyId set to FALSE.
10228 V_VT(&v) = VT_BOOL;
10229 V_BOOL(&v) = VARIANT_FALSE;
10230 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10232 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10233 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10234 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10235 tree_struct = NULL;
10236 out_req = NULL;
10237 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&prop_cond, &cache_req, &out_req, &tree_struct);
10238 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10239 ok(!out_req, "out_req != NULL\n");
10240 ok(!tree_struct, "tree_struct != NULL\n");
10241 ok_method_sequence(nav_seq16, "nav_seq16");
10243 /* Provider will now return FALSE for UIA_IsControlElementPropertyId. */
10244 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
10245 set_provider_prop_override(&Provider, &prop_override, 1);
10247 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10248 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10249 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10250 set_cache_request(&cache_req, NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10251 tree_struct = NULL;
10252 out_req = NULL;
10253 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&prop_cond, &cache_req, &out_req, &tree_struct);
10254 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10255 ok(!!out_req, "out_req == NULL\n");
10256 ok(!!tree_struct, "tree_struct == NULL\n");
10257 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10259 exp_lbound[0] = exp_lbound[1] = 0;
10260 exp_elems[0] = exp_elems[1] = 1;
10261 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10263 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10264 ok_method_sequence(nav_seq17, "nav_seq17");
10265 SafeArrayDestroy(out_req);
10266 SysFreeString(tree_struct);
10268 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10269 ok(Provider_child2_child_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
10271 CoUninitialize();
10272 DestroyWindow(hwnd);
10273 UnregisterClassA("UiaNavigate class", NULL);
10276 static void set_find_params(struct UiaFindParams *params, int max_depth, BOOL find_first, BOOL exclude_root,
10277 struct UiaCondition *find_cond)
10279 params->MaxDepth = max_depth;
10280 params->FindFirst = find_first;
10281 params->ExcludeRoot = exclude_root;
10282 params->pFindCondition = find_cond;
10285 static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count)
10287 prov->prop_override = override;
10288 prov->prop_override_count = count;
10291 static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val)
10293 override->prop_id = prop_id;
10294 override->val = *val;
10297 static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links)
10299 prov->prov_opts = prov_opts;
10300 prov->hwnd = hwnd;
10301 prov->ret_invalid_prop_type = FALSE;
10302 prov->expected_tid = 0;
10303 prov->runtime_id[0] = prov->runtime_id[1] = 0;
10304 prov->last_call_tid = 0;
10305 prov->ignore_hwnd_prop = FALSE;
10306 prov->override_hwnd = NULL;
10307 prov->prop_override = NULL;
10308 prov->prop_override_count = 0;
10309 memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect));
10310 memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data));
10311 memset(&prov->legacy_acc_pattern_data, 0, sizeof(prov->legacy_acc_pattern_data));
10312 prov->focus_prov = NULL;
10313 prov->embedded_frag_roots = NULL;
10314 prov->embedded_frag_roots_count = 0;
10315 prov->advise_events_added_event_id = prov->advise_events_removed_event_id = 0;
10316 if (initialize_nav_links)
10318 prov->frag_root = NULL;
10319 prov->parent = prov->prev_sibling = prov->next_sibling = prov->first_child = prov->last_child = NULL;
10323 static void initialize_provider_tree(BOOL initialize_nav_links)
10325 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10326 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10327 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10328 initialize_provider(&Provider_child_child2, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10329 initialize_provider(&Provider_child2, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10330 initialize_provider(&Provider_child2_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10331 initialize_provider(&Provider_child2_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
10334 static void provider_add_child(struct Provider *prov, struct Provider *child)
10336 if (!prov->first_child)
10338 prov->first_child = prov->last_child = &child->IRawElementProviderFragment_iface;
10339 child->next_sibling = child->prev_sibling = NULL;
10341 else
10343 struct Provider *tmp = impl_from_ProviderFragment(prov->last_child);
10345 tmp->next_sibling = &child->IRawElementProviderFragment_iface;
10346 child->prev_sibling = prov->last_child;
10347 prov->last_child = &child->IRawElementProviderFragment_iface;
10350 child->parent = &prov->IRawElementProviderFragment_iface;
10351 child->frag_root = prov->frag_root;
10354 #define test_find_sa_results( tree_structs, offsets, exp_elems, exp_tree_struct, exp_offsets ) \
10355 test_find_sa_results_( (tree_structs), (offsets), (exp_elems), (exp_tree_struct), (exp_offsets), __FILE__, __LINE__)
10356 static void test_find_sa_results_(SAFEARRAY *tree_structs, SAFEARRAY *offsets, LONG exp_elems,
10357 const WCHAR **exp_tree_struct, int *exp_offset, const char *file, int line)
10359 LONG lbound, ubound, elems;
10360 HRESULT hr;
10361 VARTYPE vt;
10362 UINT dims;
10363 LONG i;
10365 /* Tree structures SA. */
10366 hr = SafeArrayGetVartype(tree_structs, &vt);
10367 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10368 ok_(file, line)(vt == VT_BSTR, "Unexpected tree structures sa vt %d\n", vt);
10369 dims = SafeArrayGetDim(tree_structs);
10370 ok_(file, line)(dims == 1, "Unexpected tree structures sa dims %d\n", dims);
10372 lbound = ubound = elems = 0;
10373 hr = SafeArrayGetLBound(tree_structs, 1, &lbound);
10374 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
10375 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
10377 hr = SafeArrayGetUBound(tree_structs, 1, &ubound);
10378 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
10380 elems = (ubound - lbound) + 1;
10381 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
10383 /* Offsets SA. */
10384 hr = SafeArrayGetVartype(offsets, &vt);
10385 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10386 ok_(file, line)(vt == VT_I4, "Unexpected offsets sa vt %d\n", vt);
10387 dims = SafeArrayGetDim(offsets);
10388 ok_(file, line)(dims == 1, "Unexpected offsets sa dims %d\n", dims);
10390 lbound = ubound = elems = 0;
10391 hr = SafeArrayGetLBound(offsets, 1, &lbound);
10392 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
10393 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
10395 hr = SafeArrayGetUBound(offsets, 1, &ubound);
10396 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
10398 elems = (ubound - lbound) + 1;
10399 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
10401 for (i = 0; i < exp_elems; i++)
10403 BSTR tree_struct;
10404 int offset;
10406 hr = SafeArrayGetElement(tree_structs, &i, &tree_struct);
10407 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
10408 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct[i]), "Unexpected tree structure %s\n", debugstr_w(tree_struct));
10409 SysFreeString(tree_struct);
10411 hr = SafeArrayGetElement(offsets, &i, &offset);
10412 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
10413 ok_(file, line)(exp_offset[i] == offset, "Unexpected offset %d\n", offset);
10417 static const struct prov_method_sequence find_seq1[] = {
10418 { &Provider, FRAG_GET_RUNTIME_ID },
10419 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10420 NODE_CREATE_SEQ(&Provider_child),
10421 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10422 NODE_CREATE_SEQ(&Provider_child_child),
10423 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10424 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10425 NODE_CREATE_SEQ(&Provider_child_child2),
10426 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10427 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10428 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10429 NODE_CREATE_SEQ(&Provider_child),
10430 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10431 NODE_CREATE_SEQ(&Provider_child2),
10432 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10433 NODE_CREATE_SEQ(&Provider_child2_child),
10434 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10435 NODE_CREATE_SEQ(&Provider_child2_child_child),
10436 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10437 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10438 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10439 NODE_CREATE_SEQ(&Provider_child2_child),
10440 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10441 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10442 NODE_CREATE_SEQ(&Provider_child2),
10443 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10444 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10445 NODE_CREATE_SEQ(&Provider),
10446 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10447 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10448 /* Only done on Win10v1507 and below. */
10449 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10450 { &Provider, FRAG_GET_RUNTIME_ID },
10451 { &Provider_child, FRAG_GET_RUNTIME_ID },
10452 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
10453 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10454 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10455 { &Provider_child2_child, FRAG_GET_RUNTIME_ID },
10456 { &Provider_child2_child_child, FRAG_GET_RUNTIME_ID },
10457 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10458 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10459 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10460 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10461 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10462 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10463 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10464 { 0 },
10467 static const struct prov_method_sequence find_seq2[] = {
10468 { &Provider, FRAG_GET_RUNTIME_ID },
10469 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10470 NODE_CREATE_SEQ(&Provider_child),
10471 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10472 NODE_CREATE_SEQ(&Provider_child2),
10473 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10474 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10475 NODE_CREATE_SEQ(&Provider),
10476 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10477 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10478 /* Only done on Win10v1507 and below. */
10479 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10480 { &Provider, FRAG_GET_RUNTIME_ID },
10481 { &Provider_child, FRAG_GET_RUNTIME_ID },
10482 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10483 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10484 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10485 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10486 { 0 },
10489 static const struct prov_method_sequence find_seq3[] = {
10490 { &Provider, FRAG_GET_RUNTIME_ID },
10491 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10492 NODE_CREATE_SEQ(&Provider_child),
10493 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10494 NODE_CREATE_SEQ(&Provider_child2),
10495 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10496 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10497 NODE_CREATE_SEQ(&Provider),
10498 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10499 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10500 /* Only done on Win10v1507 and below. */
10501 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10502 { &Provider_child, FRAG_GET_RUNTIME_ID },
10503 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10504 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10505 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10506 { 0 },
10509 static const struct prov_method_sequence find_seq4[] = {
10510 { &Provider, FRAG_GET_RUNTIME_ID },
10511 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10512 NODE_CREATE_SEQ(&Provider_child),
10513 { &Provider_child, FRAG_GET_RUNTIME_ID },
10514 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10515 { 0 },
10518 static const struct prov_method_sequence find_seq5[] = {
10519 { &Provider_child, FRAG_GET_RUNTIME_ID },
10520 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10521 NODE_CREATE_SEQ(&Provider_child2),
10522 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10523 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10524 NODE_CREATE_SEQ(&Provider),
10525 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10526 NODE_CREATE_SEQ(&Provider),
10527 { &Provider_child, FRAG_GET_RUNTIME_ID },
10528 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10529 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10530 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10531 { 0 },
10534 static const struct prov_method_sequence find_seq6[] = {
10535 { &Provider_child, FRAG_GET_RUNTIME_ID },
10536 { &Provider_child, FRAG_GET_RUNTIME_ID },
10537 { &Provider_child, FRAG_GET_RUNTIME_ID },
10538 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10539 { 0 },
10542 static const struct prov_method_sequence find_seq7[] = {
10543 { &Provider, FRAG_GET_RUNTIME_ID },
10544 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10545 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10546 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10547 NODE_CREATE_SEQ(&Provider_child),
10548 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10549 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10550 NODE_CREATE_SEQ(&Provider_child_child),
10551 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10552 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10553 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10554 NODE_CREATE_SEQ(&Provider_child_child2),
10555 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10556 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10557 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10558 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10559 NODE_CREATE_SEQ(&Provider_child),
10560 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10561 NODE_CREATE_SEQ(&Provider_child2),
10562 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10563 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10564 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10565 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10566 NODE_CREATE_SEQ(&Provider),
10567 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10568 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10569 /* Only done on Win10v1507 and below. */
10570 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10571 { &Provider, FRAG_GET_RUNTIME_ID },
10572 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
10573 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10574 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10575 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10576 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10577 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10578 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10579 { 0 },
10582 static const struct prov_method_sequence find_seq8[] = {
10583 { &Provider, FRAG_GET_RUNTIME_ID },
10584 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10585 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10586 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10587 NODE_CREATE_SEQ(&Provider_child),
10588 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10589 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10590 NODE_CREATE_SEQ(&Provider_child_child),
10591 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10592 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10593 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
10594 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10595 NODE_CREATE_SEQ(&Provider_child_child2),
10596 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10597 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10598 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10599 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10600 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10601 NODE_CREATE_SEQ(&Provider_child),
10602 { &Provider_child, FRAG_GET_RUNTIME_ID },
10603 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10604 NODE_CREATE_SEQ(&Provider_child2),
10605 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10606 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10607 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10608 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10609 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10610 NODE_CREATE_SEQ(&Provider),
10611 { &Provider, FRAG_GET_RUNTIME_ID },
10612 { &Provider, FRAG_GET_RUNTIME_ID },
10613 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
10614 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10615 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10616 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10617 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10618 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10619 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10620 { 0 },
10623 static const struct prov_method_sequence find_seq9[] = {
10624 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10625 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10626 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10627 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10628 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10629 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10630 NODE_CREATE_SEQ(&Provider_child),
10631 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10632 NODE_CREATE_SEQ(&Provider_child),
10633 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10634 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10635 NODE_CREATE_SEQ(&Provider_child2),
10636 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10637 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10638 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10639 NODE_CREATE_SEQ(&Provider_child2_child),
10640 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10641 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10642 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10643 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10644 NODE_CREATE_SEQ(&Provider_child2),
10645 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10646 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10647 NODE_CREATE_SEQ(&Provider),
10648 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10649 NODE_CREATE_SEQ(&Provider),
10650 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10651 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10652 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10653 /* Only done on Win10v1507 and below. */
10654 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10655 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10656 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10657 { &Provider_child2_child, FRAG_GET_RUNTIME_ID },
10658 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10659 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10660 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10661 { 0 },
10664 static const struct prov_method_sequence find_seq10[] = {
10665 { &Provider, FRAG_GET_RUNTIME_ID },
10666 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10667 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10668 NODE_CREATE_SEQ(&Provider_child),
10669 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10670 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10671 NODE_CREATE_SEQ(&Provider_child_child),
10672 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10673 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10674 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10675 NODE_CREATE_SEQ(&Provider_child_child2),
10676 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10677 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10678 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10679 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10680 NODE_CREATE_SEQ(&Provider_child),
10681 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10682 NODE_CREATE_SEQ(&Provider_child2),
10683 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10684 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10685 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10686 NODE_CREATE_SEQ(&Provider_child2_child),
10687 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10688 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10689 NODE_CREATE_SEQ(&Provider_child2_child_child),
10690 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10691 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10692 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10693 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10694 NODE_CREATE_SEQ(&Provider_child2_child),
10695 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10696 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10697 NODE_CREATE_SEQ(&Provider_child2),
10698 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10699 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10700 NODE_CREATE_SEQ(&Provider),
10701 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10702 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10703 /* Only done on Win10v1507 and below. */
10704 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10705 { &Provider_child2, FRAG_GET_RUNTIME_ID },
10706 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10707 { 0 },
10710 static const struct prov_method_sequence find_seq11[] = {
10711 { &Provider, FRAG_GET_RUNTIME_ID },
10712 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10713 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10714 NODE_CREATE_SEQ(&Provider_child),
10715 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10716 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10717 NODE_CREATE_SEQ(&Provider_child_child),
10718 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10719 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10720 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10721 NODE_CREATE_SEQ(&Provider_child_child2),
10722 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
10723 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10724 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
10725 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10726 { 0 },
10729 static void test_UiaFind(void)
10731 struct Provider_prop_override prop_override;
10732 LONG exp_lbound[2], exp_elems[2], idx[2], i;
10733 SAFEARRAY *out_req, *offsets, *tree_structs;
10734 struct node_provider_desc exp_node_desc[7];
10735 struct UiaPropertyCondition prop_cond[2];
10736 struct UiaCacheRequest cache_req;
10737 struct UiaFindParams find_params;
10738 const WCHAR *exp_tree_struct[7];
10739 int exp_offset[7], cache_prop;
10740 HUIANODE node, node2;
10741 HRESULT hr;
10742 VARIANT v;
10744 CoInitializeEx(NULL, COINIT_MULTITHREADED);
10746 initialize_provider_tree(TRUE);
10747 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
10748 provider_add_child(&Provider, &Provider_child);
10749 provider_add_child(&Provider, &Provider_child2);
10750 provider_add_child(&Provider_child, &Provider_child_child);
10751 provider_add_child(&Provider_child, &Provider_child_child2);
10752 provider_add_child(&Provider_child2, &Provider_child2_child);
10753 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
10755 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10756 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
10758 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
10759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10760 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10762 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
10763 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10764 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
10765 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
10766 VariantClear(&v);
10768 ok_method_sequence(node_from_prov2, NULL);
10771 * Maximum find depth of -1, find first is FALSE, exclude root is FALSE. A
10772 * maximum depth of -1 will search the entire tree.
10774 out_req = offsets = tree_structs = NULL;
10775 cache_prop = UIA_RuntimeIdPropertyId;
10776 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
10777 AutomationElementMode_Full);
10778 set_find_params(&find_params, -1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
10779 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
10780 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10781 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10782 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
10783 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
10784 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
10785 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
10786 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
10788 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10789 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
10790 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child", TRUE);
10791 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child_child2", TRUE);
10792 add_provider_desc(&exp_node_desc[4], L"Main", L"Provider_child2", TRUE);
10793 add_provider_desc(&exp_node_desc[5], L"Main", L"Provider_child2_child", TRUE);
10794 add_provider_desc(&exp_node_desc[6], L"Main", L"Provider_child2_child_child", TRUE);
10795 exp_lbound[0] = exp_lbound[1] = 0;
10796 exp_elems[0] = 7;
10797 exp_elems[1] = 2;
10799 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10801 for (i = 0; i < exp_elems[0]; i++)
10803 exp_offset[i] = i;
10804 exp_tree_struct[i] = L"P)";
10806 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
10807 ok_method_sequence(find_seq1, "find_seq1");
10809 SafeArrayDestroy(out_req);
10810 SafeArrayDestroy(offsets);
10811 SafeArrayDestroy(tree_structs);
10813 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10814 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
10817 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
10819 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
10820 AutomationElementMode_Full);
10821 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
10822 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
10823 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10824 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10825 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
10827 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10828 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
10829 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2", TRUE);
10830 exp_lbound[0] = exp_lbound[1] = 0;
10831 exp_elems[0] = 3;
10832 exp_elems[1] = 2;
10834 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10836 for (i = 0; i < exp_elems[0]; i++)
10838 exp_offset[i] = i;
10839 exp_tree_struct[i] = L"P)";
10842 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
10843 ok_method_sequence(find_seq2, "find_seq2");
10845 SafeArrayDestroy(out_req);
10846 SafeArrayDestroy(offsets);
10847 SafeArrayDestroy(tree_structs);
10849 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10850 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
10853 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
10855 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
10856 AutomationElementMode_Full);
10857 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
10858 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
10859 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10860 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10861 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
10863 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10864 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
10865 exp_lbound[0] = exp_lbound[1] = 0;
10866 exp_elems[0] = 2;
10867 exp_elems[1] = 2;
10869 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10871 for (i = 0; i < exp_elems[0]; i++)
10873 exp_offset[i] = i;
10874 exp_tree_struct[i] = L"P)";
10876 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
10877 ok_method_sequence(find_seq3, "find_seq3");
10879 SafeArrayDestroy(out_req);
10880 SafeArrayDestroy(offsets);
10881 SafeArrayDestroy(tree_structs);
10883 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10884 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
10887 * Maximum find depth of 1, find first is TRUE, exclude root is TRUE. Will
10888 * retrieve only Provider_child.
10890 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
10891 AutomationElementMode_Full);
10892 set_find_params(&find_params, 1, TRUE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
10893 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
10894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10895 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10897 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10898 exp_lbound[0] = exp_lbound[1] = 0;
10899 exp_elems[0] = 1;
10900 exp_elems[1] = 2;
10902 idx[0] = idx[1] = 0;
10903 hr = SafeArrayGetElement(out_req, idx, &v);
10904 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10906 /* node2 is now set as Provider_child. */
10907 hr = UiaHUiaNodeFromVariant(&v, &node2);
10908 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10909 IUnknown_AddRef((IUnknown *)node2);
10911 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10913 for (i = 0; i < exp_elems[0]; i++)
10915 exp_offset[i] = i;
10916 exp_tree_struct[i] = L"P)";
10918 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
10919 ok_method_sequence(find_seq4, "find_seq4");
10921 SafeArrayDestroy(out_req);
10922 SafeArrayDestroy(offsets);
10923 SafeArrayDestroy(tree_structs);
10925 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10926 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
10929 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
10930 * Provider_child doesn't have a runtime id for UI Automation to use as a
10931 * way to check if it has navigated back to the node that began the
10932 * search, so it will get siblings.
10934 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
10935 AutomationElementMode_Full);
10936 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
10937 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
10938 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10939 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
10941 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10942 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
10943 exp_lbound[0] = exp_lbound[1] = 0;
10944 exp_elems[0] = 2;
10945 exp_elems[1] = 2;
10947 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10949 for (i = 0; i < exp_elems[0]; i++)
10951 exp_offset[i] = i;
10952 exp_tree_struct[i] = L"P)";
10954 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
10955 ok_method_sequence(find_seq5, "find_seq5");
10957 SafeArrayDestroy(out_req);
10958 SafeArrayDestroy(offsets);
10959 SafeArrayDestroy(tree_structs);
10961 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10962 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
10965 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
10966 * Provider_child has a runtime id for UI Automation to use as a
10967 * way to check if it has navigated back to the node that began the
10968 * search, so it will stop at Provider_child.
10970 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
10971 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
10972 AutomationElementMode_Full);
10973 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
10974 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
10975 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10977 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10978 exp_lbound[0] = exp_lbound[1] = 0;
10979 exp_elems[0] = 1;
10980 exp_elems[1] = 2;
10982 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10984 for (i = 0; i < exp_elems[0]; i++)
10986 exp_offset[i] = i;
10987 exp_tree_struct[i] = L"P)";
10989 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
10990 ok_method_sequence(find_seq6, "find_seq6");
10992 SafeArrayDestroy(out_req);
10993 SafeArrayDestroy(offsets);
10994 SafeArrayDestroy(tree_structs);
10996 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10997 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10999 initialize_provider_tree(FALSE);
11000 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11001 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
11004 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
11005 * The cache request view condition is used to determine tree depth, if an
11006 * element matches the cache request view condition, depth is incremented.
11007 * Since Provider_child does not, Provider_child_child, Provider_child_child2,
11008 * and Provider_child2 are all considered to be at depth 1.
11010 V_VT(&v) = VT_BOOL;
11011 V_BOOL(&v) = VARIANT_FALSE;
11012 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11013 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
11015 V_VT(&v) = VT_BOOL;
11016 V_BOOL(&v) = VARIANT_TRUE;
11017 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11019 set_provider_prop_override(&Provider, &prop_override, 1);
11020 set_provider_prop_override(&Provider_child2, &prop_override, 1);
11021 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
11022 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
11024 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
11025 AutomationElementMode_Full);
11026 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
11027 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11028 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11029 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
11030 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
11031 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11033 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11034 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
11035 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
11036 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
11037 exp_lbound[0] = exp_lbound[1] = 0;
11038 exp_elems[0] = 4;
11039 exp_elems[1] = 2;
11041 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11043 for (i = 0; i < exp_elems[0]; i++)
11045 exp_offset[i] = i;
11046 exp_tree_struct[i] = L"P)";
11048 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11049 ok_method_sequence(find_seq7, "find_seq7");
11051 SafeArrayDestroy(out_req);
11052 SafeArrayDestroy(offsets);
11053 SafeArrayDestroy(tree_structs);
11055 initialize_provider_tree(FALSE);
11056 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11057 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
11060 * Same test as before, except Provider has a runtime id.
11062 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
11063 V_VT(&v) = VT_BOOL;
11064 V_BOOL(&v) = VARIANT_FALSE;
11065 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11066 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
11068 V_VT(&v) = VT_BOOL;
11069 V_BOOL(&v) = VARIANT_TRUE;
11070 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11072 set_provider_prop_override(&Provider, &prop_override, 1);
11073 set_provider_prop_override(&Provider_child2, &prop_override, 1);
11074 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
11075 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
11077 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
11078 AutomationElementMode_Full);
11079 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
11080 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11081 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11082 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
11083 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
11084 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11086 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11087 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
11088 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
11089 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
11090 exp_lbound[0] = exp_lbound[1] = 0;
11091 exp_elems[0] = 4;
11092 exp_elems[1] = 2;
11094 idx[0] = 2;
11095 idx[1] = 0;
11096 hr = SafeArrayGetElement(out_req, idx, &v);
11097 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11099 /* node2 is now set as Provider_child_child2. */
11100 hr = UiaHUiaNodeFromVariant(&v, &node2);
11101 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11102 IUnknown_AddRef((IUnknown *)node2);
11104 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11106 for (i = 0; i < exp_elems[0]; i++)
11108 exp_offset[i] = i;
11109 exp_tree_struct[i] = L"P)";
11111 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11112 ok_method_sequence(find_seq8, "find_seq8");
11114 SafeArrayDestroy(out_req);
11115 SafeArrayDestroy(offsets);
11116 SafeArrayDestroy(tree_structs);
11118 initialize_provider_tree(FALSE);
11119 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11120 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
11123 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
11124 * Starting at Provider_child_child2, find will be able to traverse the
11125 * tree in the same order as it would if we had started at the tree root
11126 * Provider, retrieving Provider_child2 as a sibling and
11127 * Provider_child2_child as a node at depth 1.
11129 V_VT(&v) = VT_BOOL;
11130 V_BOOL(&v) = VARIANT_FALSE;
11131 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11133 V_VT(&v) = VT_BOOL;
11134 V_BOOL(&v) = VARIANT_TRUE;
11135 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11137 prop_override.prop_id = UIA_IsContentElementPropertyId;
11138 V_VT(&prop_override.val) = VT_BOOL;
11139 V_BOOL(&prop_override.val) = VARIANT_FALSE;
11140 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
11141 set_provider_prop_override(&Provider_child2, &prop_override, 1);
11142 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
11144 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
11145 AutomationElementMode_Full);
11146 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
11147 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11148 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11149 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11150 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
11152 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
11153 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
11154 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2_child", TRUE);
11155 exp_lbound[0] = exp_lbound[1] = 0;
11156 exp_elems[0] = 3;
11157 exp_elems[1] = 2;
11159 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11161 for (i = 0; i < exp_elems[0]; i++)
11163 exp_offset[i] = i;
11164 exp_tree_struct[i] = L"P)";
11166 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11167 ok_method_sequence(find_seq9, "find_seq9");
11169 SafeArrayDestroy(out_req);
11170 SafeArrayDestroy(offsets);
11171 SafeArrayDestroy(tree_structs);
11173 initialize_provider_tree(FALSE);
11174 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11175 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
11177 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11178 ok(Provider_child_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
11181 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
11182 * Exclude root applies to the first node that matches the view
11183 * condition, and not the node that is passed into UiaFind(). Since
11184 * Provider doesn't match our view condition here, Provider_child will be
11185 * excluded.
11187 V_VT(&v) = VT_BOOL;
11188 V_BOOL(&v) = VARIANT_FALSE;
11189 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11190 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
11192 V_VT(&v) = VT_BOOL;
11193 V_BOOL(&v) = VARIANT_TRUE;
11194 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11196 set_provider_prop_override(&Provider_child, &prop_override, 1);
11197 set_provider_prop_override(&Provider_child2, &prop_override, 1);
11199 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
11200 AutomationElementMode_Full);
11201 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&prop_cond[1]);
11202 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11203 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11204 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11206 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
11207 exp_lbound[0] = exp_lbound[1] = 0;
11208 exp_elems[0] = 1;
11209 exp_elems[1] = 2;
11211 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11213 for (i = 0; i < exp_elems[0]; i++)
11215 exp_offset[i] = i;
11216 exp_tree_struct[i] = L"P)";
11218 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11220 ok_method_sequence(find_seq10, "find_seq10");
11222 SafeArrayDestroy(out_req);
11223 SafeArrayDestroy(offsets);
11224 SafeArrayDestroy(tree_structs);
11226 initialize_provider_tree(FALSE);
11227 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11228 init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
11231 * Maximum find depth of -1, find first is TRUE, exclude root is FALSE.
11232 * Provider_child_child2 is the only element in the tree to match our
11233 * condition.
11235 V_VT(&v) = VT_BOOL;
11236 V_BOOL(&v) = VARIANT_FALSE;
11237 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11238 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
11240 V_VT(&v) = VT_BOOL;
11241 V_BOOL(&v) = VARIANT_TRUE;
11242 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11244 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
11246 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
11247 AutomationElementMode_Full);
11248 set_find_params(&find_params, -1, TRUE, FALSE, (struct UiaCondition *)&prop_cond[1]);
11249 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11250 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11251 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
11253 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
11254 exp_lbound[0] = exp_lbound[1] = 0;
11255 exp_elems[0] = 1;
11256 exp_elems[1] = 2;
11258 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11260 for (i = 0; i < exp_elems[0]; i++)
11262 exp_offset[i] = i;
11263 exp_tree_struct[i] = L"P)";
11265 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11266 ok_method_sequence(find_seq11, "find_seq11");
11268 SafeArrayDestroy(out_req);
11269 SafeArrayDestroy(offsets);
11270 SafeArrayDestroy(tree_structs);
11272 initialize_provider_tree(TRUE);
11274 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11275 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11277 CoUninitialize();
11280 struct marshal_thread_data {
11281 IUnknown *iface;
11282 const GUID *iface_iid;
11283 BOOL expect_proxy;
11284 const char *file;
11285 int line;
11287 IStream *marshal_stream;
11290 static DWORD WINAPI interface_marshal_proxy_thread(LPVOID param)
11292 struct marshal_thread_data *data = (struct marshal_thread_data *)param;
11293 IUnknown *proxy_iface, *unk, *unk2;
11294 HRESULT hr;
11296 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
11298 proxy_iface = unk = unk2 = NULL;
11299 hr = CoGetInterfaceAndReleaseStream(data->marshal_stream, data->iface_iid, (void **)&proxy_iface);
11300 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11302 hr = IUnknown_QueryInterface(data->iface, &IID_IUnknown, (void **)&unk);
11303 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11304 ok_(data->file, data->line)(!!unk, "unk == NULL\n");
11306 hr = IUnknown_QueryInterface(proxy_iface, &IID_IUnknown, (void **)&unk2);
11307 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11308 ok_(data->file, data->line)(!!unk2, "unk2 == NULL\n");
11310 if (data->expect_proxy)
11311 ok_(data->file, data->line)(unk != unk2, "unk == unk2\n");
11312 else
11313 ok_(data->file, data->line)(unk == unk2, "unk != unk2\n");
11315 IUnknown_Release(proxy_iface);
11316 IUnknown_Release(unk);
11317 IUnknown_Release(unk2);
11319 CoUninitialize();
11320 return 0;
11323 #define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
11324 check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
11325 static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file,
11326 int line)
11328 struct marshal_thread_data data = { NULL, iid, expect_proxy, file, line };
11329 HANDLE thread;
11330 HRESULT hr;
11332 hr = IUnknown_QueryInterface(iface, data.iface_iid, (void **)&data.iface);
11333 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11335 hr = CoMarshalInterThreadInterfaceInStream(data.iface_iid, data.iface, &data.marshal_stream);
11336 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11338 thread = CreateThread(NULL, 0, interface_marshal_proxy_thread, (void *)&data, 0, NULL);
11339 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
11341 MSG msg;
11342 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
11344 TranslateMessage(&msg);
11345 DispatchMessageW(&msg);
11348 CloseHandle(thread);
11350 IUnknown_Release(data.iface);
11353 static HWND create_test_hwnd(const char *class_name)
11355 WNDCLASSA cls = { 0 };
11357 cls.lpfnWndProc = test_wnd_proc;
11358 cls.hInstance = GetModuleHandleA(NULL);
11359 cls.lpszClassName = class_name;
11360 RegisterClassA(&cls);
11362 return CreateWindowA(class_name, "Test window", WS_OVERLAPPEDWINDOW,
11363 0, 0, 100, 100, NULL, NULL, NULL, NULL);
11366 static HWND create_child_test_hwnd(const char *class_name, HWND parent)
11368 WNDCLASSA cls = { 0 };
11370 cls.lpfnWndProc = child_test_wnd_proc;
11371 cls.hInstance = GetModuleHandleA(NULL);
11372 cls.lpszClassName = class_name;
11373 RegisterClassA(&cls);
11375 return CreateWindowA(class_name, "Test child window", WS_CHILD,
11376 0, 0, 50, 50, parent, NULL, NULL, NULL);
11379 static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd, BOOL block_hwnd_provs)
11381 IUIAutomationElement *element;
11382 HRESULT hr;
11383 VARIANT v;
11385 if (block_hwnd_provs)
11387 SET_EXPECT(prov_callback_base_hwnd);
11388 SET_EXPECT(prov_callback_nonclient);
11389 base_hwnd_prov = proxy_prov = parent_proxy_prov = nc_prov = NULL;
11390 UiaRegisterProviderCallback(test_uia_provider_callback);
11392 else
11393 UiaRegisterProviderCallback(NULL);
11395 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
11396 prov_root = &Provider.IRawElementProviderSimple_iface;
11397 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
11398 /* Only sent on Win7. */
11399 SET_EXPECT(winproc_GETOBJECT_CLIENT);
11400 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &element);
11401 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11402 ok(!!element, "element == NULL\n");
11403 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11404 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
11405 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
11406 if (block_hwnd_provs)
11408 CHECK_CALLED(prov_callback_base_hwnd);
11409 CHECK_CALLED(prov_callback_nonclient);
11412 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
11413 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11415 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
11416 if (!block_hwnd_provs)
11418 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
11419 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
11420 check_node_provider_desc_todo(V_BSTR(&v), L"Hwnd", NULL, TRUE);
11422 else
11423 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
11425 VariantClear(&v);
11426 ok_method_sequence(node_from_hwnd2, "create_test_element");
11427 UiaRegisterProviderCallback(NULL);
11429 return element;
11432 static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8)
11434 HWND hwnd = create_test_hwnd("test_ElementFromHandle class");
11435 IUIAutomationElement2 *element_2;
11436 IUIAutomationElement *element;
11437 HRESULT hr;
11439 element = create_test_element_from_hwnd(uia_iface, hwnd, FALSE);
11440 hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2);
11441 if (is_cui8)
11443 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11444 ok(!!element_2, "element_2 == NULL\n");
11445 IUIAutomationElement2_Release(element_2);
11447 else
11448 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
11451 * The IUIAutomationElement interface uses the free threaded marshaler, so
11452 * no actual proxy interface will be created.
11454 check_interface_marshal_proxy_creation((IUnknown *)element, &IID_IUIAutomationElement, FALSE);
11456 IUIAutomationElement_Release(element);
11457 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11459 DestroyWindow(hwnd);
11460 UnregisterClassA("test_ElementFromHandle class", NULL);
11461 prov_root = NULL;
11464 static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
11466 HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class");
11467 const struct uia_element_property *elem_prop;
11468 struct Provider_prop_override prop_override;
11469 IUIAutomationElement *element, *element2;
11470 IUIAutomationElementArray *element_arr;
11471 int i, len, prop_id, tmp_int;
11472 struct UiaRect uia_rect;
11473 IUnknown *unk_ns;
11474 BSTR tmp_bstr;
11475 HRESULT hr;
11476 RECT rect;
11477 VARIANT v;
11479 element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
11480 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
11481 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
11482 provider_add_child(&Provider, &Provider_child);
11484 hr = UiaGetReservedNotSupportedValue(&unk_ns);
11485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11487 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ControlTypePropertyId, TRUE, NULL);
11488 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11490 VariantInit(&v);
11491 V_VT(&v) = VT_BOOL;
11492 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, 1, TRUE, &v);
11493 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
11494 ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
11496 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
11498 elem_prop = &element_properties[i];
11500 Provider.ret_invalid_prop_type = FALSE;
11501 VariantClear(&v);
11502 if (!(prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid)))
11504 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
11505 break;
11508 winetest_push_context("Element prop_id %d", prop_id);
11509 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
11510 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11511 check_uia_prop_val(prop_id, elem_prop->type, &v, TRUE);
11514 * Some properties have special behavior if an invalid value is
11515 * returned, skip them here.
11517 if (!elem_prop->skip_invalid)
11519 Provider.ret_invalid_prop_type = TRUE;
11520 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
11521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11522 if (SUCCEEDED(hr))
11524 ok_method_sequence(get_prop_invalid_type_seq, NULL);
11525 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
11526 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
11527 VariantClear(&v);
11531 winetest_pop_context();
11534 /* Test IUIAutomationElementArray interface behavior. */
11535 Provider.ret_invalid_prop_type = FALSE;
11536 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ControllerForPropertyId, TRUE, &v);
11537 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11538 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
11539 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11540 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11542 element_arr = NULL;
11543 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&element_arr);
11544 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11545 ok(!!element_arr, "element_arr == NULL\n");
11546 VariantClear(&v);
11548 hr = IUIAutomationElementArray_get_Length(element_arr, &len);
11549 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11550 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
11552 /* Invalid argument tests. */
11553 hr = IUIAutomationElementArray_get_Length(element_arr, NULL);
11554 ok(hr == E_POINTER, "Unexpected hr %#lx\n", hr);
11556 element2 = (void *)0xdeadbeef;
11557 hr = IUIAutomationElementArray_GetElement(element_arr, len, &element2);
11558 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
11559 /* Pointer isn't cleared. */
11560 ok(!!element2, "element2 == NULL\n");
11562 hr = IUIAutomationElementArray_GetElement(element_arr, -1, &element2);
11563 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
11564 /* Pointer isn't cleared. */
11565 ok(!!element2, "element2 == NULL\n");
11567 hr = IUIAutomationElementArray_GetElement(element_arr, 0, NULL);
11568 ok(hr == E_POINTER, "Unexpected hr %#lx\n", hr);
11570 for (i = 0; i < len; i++)
11572 element2 = NULL;
11573 hr = IUIAutomationElementArray_GetElement(element_arr, i, &element2);
11574 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11575 ok(!!element2, "element2 == NULL\n");
11577 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ControlTypePropertyId, TRUE, &v);
11578 ok(hr == S_OK, "element[%d] Unexpected hr %#lx\n", i, hr);
11579 ok(V_VT(&v) == VT_I4, "element[%d] Unexpected VT %d\n", i, V_VT(&v));
11580 ok(V_I4(&v) == uia_i4_prop_val, "element[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
11582 IUIAutomationElement_Release(element2);
11583 VariantClear(&v);
11586 IUIAutomationElementArray_Release(element_arr);
11587 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
11588 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
11589 ok_method_sequence(get_elem_arr_prop_seq, NULL);
11592 * IUIAutomationElement_get_CurrentControlType tests. If the value
11593 * returned for UIA_ControlTypePropertyId is not a registered control
11594 * type ID, we'll get back UIA_CustomControlTypeId.
11596 tmp_int = 0xdeadb33f;
11597 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
11598 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11601 * Win10v1507 and below don't check whether or not the returned control
11602 * type ID is valid.
11604 ok(tmp_int == UIA_CustomControlTypeId || broken(tmp_int == 0xdeadbeef), "Unexpected control type %#x\n", tmp_int);
11605 ok_method_sequence(get_prop_seq, NULL);
11607 Provider.ret_invalid_prop_type = TRUE;
11608 tmp_int = 0xdeadbeef;
11609 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
11610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11611 ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
11612 Provider.ret_invalid_prop_type = FALSE;
11613 ok_method_sequence(get_prop_invalid_type_seq, NULL);
11615 /* Finally, a valid control type. */
11616 V_VT(&v) = VT_I4;
11617 V_I4(&v) = UIA_HyperlinkControlTypeId;
11618 set_property_override(&prop_override, UIA_ControlTypePropertyId, &v);
11619 set_provider_prop_override(&Provider, &prop_override, 1);
11620 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
11621 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11622 ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
11623 set_provider_prop_override(&Provider, NULL, 0);
11624 ok_method_sequence(get_prop_seq, NULL);
11627 * IUIAutomationElement_get_CurrentName tests.
11629 tmp_bstr = NULL;
11630 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
11631 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11632 ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
11633 SysFreeString(tmp_bstr);
11634 ok_method_sequence(get_prop_seq, NULL);
11636 tmp_bstr = NULL;
11637 Provider.ret_invalid_prop_type = TRUE;
11638 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
11639 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11640 ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
11641 SysFreeString(tmp_bstr);
11642 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
11643 ok_method_sequence(get_prop_invalid_type_seq, NULL);
11646 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
11647 * It's the only version with this behavior.
11649 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
11651 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
11652 goto exit;
11656 * IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests.
11658 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
11659 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11660 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
11661 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11663 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
11664 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11665 ok(!!element2, "element2 == NULL\n");
11666 VariantClear(&v);
11668 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
11669 set_uia_rect(&uia_rect, 0, 0, 50, 50);
11670 Provider_child.bounds_rect = uia_rect;
11671 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
11672 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11673 check_uia_rect_val(&v, &uia_rect);
11674 VariantClear(&v);
11675 ok_method_sequence(get_bounding_rect_seq2, "get_bounding_rect_seq2");
11677 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
11678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11679 check_uia_rect_rect_val(&rect, &uia_rect);
11680 memset(&rect, 0, sizeof(rect));
11681 ok_method_sequence(get_bounding_rect_seq3, "get_bounding_rect_seq3");
11683 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
11684 set_uia_rect(&uia_rect, 0, 0, 0, 0);
11685 Provider_child.bounds_rect = uia_rect;
11686 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
11687 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11688 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
11689 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
11690 VariantClear(&v);
11691 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
11693 /* Returns an all 0 rect. */
11694 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
11695 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11696 check_uia_rect_rect_val(&rect, &uia_rect);
11697 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
11699 IUIAutomationElement_Release(element2);
11700 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
11701 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
11703 exit:
11704 IUIAutomationElement_Release(element);
11705 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11707 DestroyWindow(hwnd);
11708 UnregisterClassA("test_Element_GetPropertyValue class", NULL);
11711 static void test_CUIAutomation_value_conversion(IUIAutomation *uia_iface)
11713 static const VARTYPE invalid_int_vts[] = { VT_I8, VT_INT };
11714 int in_arr[3] = { 0xdeadbeef, 0xfeedbeef, 0x1337b33f };
11715 int *out_arr, out_arr_count, i;
11716 LONG lbound, ubound;
11717 SAFEARRAY *sa;
11718 VARTYPE vt;
11719 HRESULT hr;
11720 UINT dims;
11723 * Conversion from VT_I4 SAFEARRAY to native int array.
11725 for (i = 0; i < ARRAY_SIZE(invalid_int_vts); i++)
11727 vt = invalid_int_vts[i];
11728 sa = SafeArrayCreateVector(vt, 0, 2);
11729 ok(!!sa, "sa == NULL\n");
11731 out_arr_count = 0xdeadbeef;
11732 out_arr = (int *)0xdeadbeef;
11733 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
11734 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
11735 ok(!out_arr, "out_arr != NULL\n");
11736 ok(out_arr_count == 0xdeadbeef, "Unexpected out_arr_count %#x\n", out_arr_count);
11737 SafeArrayDestroy(sa);
11740 /* Only accepts VT_I4 as an input array type. */
11741 sa = create_i4_safearray();
11742 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
11743 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11744 ok(out_arr_count == ARRAY_SIZE(uia_i4_arr_prop_val), "Unexpected out_arr_count %#x\n", out_arr_count);
11745 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val); i++)
11746 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]);
11748 SafeArrayDestroy(sa);
11749 CoTaskMemFree(out_arr);
11752 * Conversion from native int array to VT_I4 SAFEARRAY.
11754 sa = NULL;
11755 hr = IUIAutomation_IntNativeArrayToSafeArray(uia_iface, in_arr, ARRAY_SIZE(in_arr), &sa);
11756 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11758 hr = SafeArrayGetVartype(sa, &vt);
11759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11760 ok(vt == VT_I4, "Unexpected vt %d.\n", vt);
11762 dims = SafeArrayGetDim(sa);
11763 ok(dims == 1, "Unexpected array dims %d\n", dims);
11765 hr = SafeArrayGetLBound(sa, 1, &lbound);
11766 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
11767 ok(lbound == 0, "Unexpected LBound %#lx\n", lbound);
11769 hr = SafeArrayGetUBound(sa, 1, &ubound);
11770 ok(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
11771 ok(((ubound - lbound) + 1) == ARRAY_SIZE(in_arr), "Unexpected array size %#lx\n", ((ubound - lbound) + 1));
11773 for (i = 0; i < ARRAY_SIZE(in_arr); i++)
11775 LONG idx = lbound + i;
11776 int tmp_val;
11778 hr = SafeArrayGetElement(sa, &idx, &tmp_val);
11779 ok(hr == S_OK, "Failed to get element at idx %ld, hr %#lx\n", idx, hr);
11780 ok(tmp_val == in_arr[i], "Expected %d at idx %d, got %d\n", in_arr[i], i, tmp_val);
11783 SafeArrayDestroy(sa);
11786 static HRESULT WINAPI Object_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
11788 *ppv = NULL;
11789 if (IsEqualIID(riid, &IID_IUnknown))
11790 *ppv = iface;
11791 else
11792 return E_NOINTERFACE;
11794 return S_OK;
11797 static ULONG WINAPI Object_AddRef(IUnknown *iface)
11799 return 2;
11802 static ULONG WINAPI Object_Release(IUnknown *iface)
11804 return 1;
11807 static IUnknownVtbl ObjectVtbl = {
11808 Object_QueryInterface,
11809 Object_AddRef,
11810 Object_Release
11812 static IUnknown Object = {&ObjectVtbl};
11814 static void test_CUIAutomation_condition_ifaces(IUIAutomation *uia_iface)
11816 IUIAutomationPropertyCondition *prop_cond, *prop_cond2;
11817 IUIAutomationCondition *cond, **cond_arr;
11818 enum PropertyConditionFlags prop_flags;
11819 IUIAutomationBoolCondition *bool_cond;
11820 IUIAutomationNotCondition *not_cond;
11821 IUIAutomationOrCondition *or_cond;
11822 PROPERTYID prop_id;
11823 int child_count;
11824 BOOL tmp_b;
11825 HRESULT hr;
11826 VARIANT v;
11827 ULONG ref;
11829 hr = IUIAutomation_CreateTrueCondition(uia_iface, NULL);
11830 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11832 cond = NULL;
11833 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
11834 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11835 ok(!!cond, "cond == NULL\n");
11837 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
11838 IUIAutomationCondition_Release(cond);
11839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11840 ok(!!bool_cond, "bool_cond == NULL\n");
11842 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, NULL);
11843 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11845 tmp_b = FALSE;
11846 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
11847 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11848 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
11849 IUIAutomationBoolCondition_Release(bool_cond);
11851 hr = IUIAutomation_CreateFalseCondition(uia_iface, NULL);
11852 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11854 cond = NULL;
11855 hr = IUIAutomation_CreateFalseCondition(uia_iface, &cond);
11856 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11857 ok(!!cond, "cond == NULL\n");
11859 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
11860 IUIAutomationCondition_Release(cond);
11861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11862 ok(!!bool_cond, "bool_cond == NULL\n");
11864 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, NULL);
11865 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11867 tmp_b = TRUE;
11868 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
11869 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11870 ok(tmp_b == FALSE, "tmp_b != FALSE\n");
11871 IUIAutomationBoolCondition_Release(bool_cond);
11874 * IUIAutomationPropertyCondition tests.
11876 cond = (void *)0xdeadbeef;
11877 VariantInit(&v);
11878 /* Invalid property ID. */
11879 hr = IUIAutomation_CreatePropertyCondition(uia_iface, 0, v, &cond);
11880 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
11881 ok(!cond, "cond != NULL\n");
11883 /* Invalid variant type for property ID. */
11884 cond = (void *)0xdeadbeef;
11885 VariantInit(&v);
11886 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond);
11887 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
11888 ok(!cond, "cond != NULL\n");
11890 /* NULL Condition argument. */
11891 V_VT(&v) = VT_I4 | VT_ARRAY;
11892 V_ARRAY(&v) = create_i4_safearray();
11893 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, NULL);
11894 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11896 /* Finally, create property condition interface. */
11897 cond = NULL;
11898 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond);
11899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11900 ok(!!cond, "cond == NULL\n");
11902 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
11903 IUIAutomationCondition_Release(cond);
11904 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11905 ok(!!prop_cond, "prop_cond == NULL\n");
11907 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, NULL);
11908 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11910 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
11911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11912 ok(prop_id == UIA_RuntimeIdPropertyId, "Unexpected prop_id %d.\n", prop_id);
11914 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, NULL);
11915 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11917 VariantClear(&v);
11918 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
11919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11920 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d.\n", V_VT(&v));
11921 ok(!!V_ARRAY(&v), "V_ARRAY(&v) == NULL\n");
11922 VariantClear(&v);
11924 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, NULL);
11925 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11927 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
11928 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11929 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
11932 * IUIAutomationNotCondition tests.
11934 cond = (void *)0xdeadbeef;
11937 * Passing in an interface that isn't a valid IUIAutomationCondition
11938 * interface.
11940 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)&Object, &cond);
11941 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
11942 ok(!cond, "cond != NULL\n");
11944 /* NULL input argument tests. */
11945 cond = (void *)0xdeadbeef;
11946 hr = IUIAutomation_CreateNotCondition(uia_iface, NULL, &cond);
11947 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11948 ok(!cond, "cond != NULL\n");
11950 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)prop_cond, NULL);
11951 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11953 /* Create the IUIAutomationNotCondition with our property condition. */
11954 cond = NULL;
11955 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)prop_cond, &cond);
11956 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11957 ok(!!cond, "cond == NULL\n");
11959 /* IUIAutomationNotCondition holds a reference to the passed in condition. */
11960 ref = IUIAutomationPropertyCondition_Release(prop_cond);
11961 ok(ref == 1, "Unexpected ref %ld\n", ref);
11963 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
11964 IUIAutomationCondition_Release(cond);
11965 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11966 ok(!!not_cond, "not_cond == NULL\n");
11968 hr = IUIAutomationNotCondition_GetChild(not_cond, NULL);
11969 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
11971 cond = NULL;
11972 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
11973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11974 ok(iface_cmp((IUnknown *)cond, (IUnknown *)prop_cond), "cond != prop_cond\n");
11975 IUIAutomationCondition_Release(cond);
11977 IUIAutomationNotCondition_Release(not_cond);
11980 * IUIAutomationOrCondition tests.
11982 cond = NULL;
11983 VariantInit(&v);
11984 V_VT(&v) = VT_BOOL;
11985 V_BOOL(&v) = VARIANT_FALSE;
11986 /* Create two condition interfaces to use for our IUIAutomationOrCondition. */
11987 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsControlElementPropertyId, v, &cond);
11988 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11989 ok(!!cond, "cond == NULL\n");
11991 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
11992 IUIAutomationCondition_Release(cond);
11993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11994 ok(!!prop_cond, "prop_cond == NULL\n");
11996 cond = NULL;
11997 VariantInit(&v);
11998 V_VT(&v) = VT_BOOL;
11999 V_BOOL(&v) = VARIANT_TRUE;
12000 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &cond);
12001 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12002 ok(!!cond, "cond == NULL\n");
12004 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond2);
12005 IUIAutomationCondition_Release(cond);
12006 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12007 ok(!!prop_cond2, "prop_cond2 == NULL\n");
12009 /* NULL input argument tests. */
12010 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
12011 (IUIAutomationCondition *)prop_cond2, NULL);
12012 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12014 cond = (void *)0xdeadbeef;
12015 hr = IUIAutomation_CreateOrCondition(uia_iface, NULL, (IUIAutomationCondition *)prop_cond2, &cond);
12016 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12017 ok(!cond, "cond != NULL\n");
12019 cond = (void *)0xdeadbeef;
12020 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond, NULL, &cond);
12021 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12022 ok(!cond, "cond != NULL\n");
12024 /* One of the IUIAutomationCondition interfaces are invalid. */
12025 cond = (void *)0xdeadbeef;
12026 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
12027 (IUIAutomationCondition *)&Object, &cond);
12028 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
12029 ok(!cond, "cond != NULL\n");
12031 cond = NULL;
12032 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
12033 (IUIAutomationCondition *)prop_cond2, &cond);
12034 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12035 ok(!!cond, "cond == NULL\n");
12037 or_cond = NULL;
12038 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationOrCondition, (void **)&or_cond);
12039 IUIAutomationCondition_Release(cond);
12040 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12041 ok(!!or_cond, "or_cond == NULL\n");
12043 /* References held to both passed in interfaces. */
12044 ref = IUIAutomationPropertyCondition_Release(prop_cond);
12045 ok(ref == 1, "Unexpected ref %ld\n", ref);
12047 ref = IUIAutomationPropertyCondition_Release(prop_cond2);
12048 ok(ref == 1, "Unexpected ref %ld\n", ref);
12050 hr = IUIAutomationOrCondition_get_ChildCount(or_cond, NULL);
12051 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12053 child_count = 0;
12054 hr = IUIAutomationOrCondition_get_ChildCount(or_cond, &child_count);
12055 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12056 ok(child_count == 2, "Unexpected child_count %d.\n", child_count);
12058 child_count = 10;
12059 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, NULL, &child_count);
12060 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12061 ok(child_count == 10, "Unexpected child_count %d.\n", child_count);
12063 cond_arr = (void *)0xdeadbeef;
12064 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, &cond_arr, NULL);
12065 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12066 ok(!cond_arr, "cond_arr != NULL\n");
12068 child_count = 0;
12069 cond_arr = NULL;
12070 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, &cond_arr, &child_count);
12071 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12072 ok(child_count == 2, "Unexpected child_count %d.\n", child_count);
12073 ok(!!cond_arr, "cond_arr == NULL\n");
12075 ok(iface_cmp((IUnknown *)cond_arr[0], (IUnknown *)prop_cond), "cond_arr[0] != prop_cond\n");
12076 IUIAutomationCondition_Release(cond_arr[0]);
12078 ok(iface_cmp((IUnknown *)cond_arr[1], (IUnknown *)prop_cond2), "cond_arr[1] != prop_cond2\n");
12079 IUIAutomationCondition_Release(cond_arr[1]);
12081 CoTaskMemFree(cond_arr);
12082 IUIAutomationOrCondition_Release(or_cond);
12085 * Condition used to get the control TreeView. Equivalent to:
12086 * if (!(UIA_IsControlElementPropertyId == VARIANT_FALSE))
12088 hr = IUIAutomation_get_ControlViewCondition(uia_iface, NULL);
12089 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12091 cond = NULL;
12092 hr = IUIAutomation_get_ControlViewCondition(uia_iface, &cond);
12093 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12094 ok(!!cond, "cond == NULL\n");
12096 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
12097 IUIAutomationCondition_Release(cond);
12098 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12099 ok(!!not_cond, "not_cond == NULL\n");
12101 cond = NULL;
12102 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
12103 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12104 ok(!!cond, "cond == NULL\n");
12106 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
12107 IUIAutomationCondition_Release(cond);
12108 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12109 ok(!!prop_cond, "prop_cond == NULL\n");
12111 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
12112 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12113 ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
12115 VariantInit(&v);
12116 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
12117 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12118 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
12119 VariantClear(&v);
12121 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
12122 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12123 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
12125 IUIAutomationPropertyCondition_Release(prop_cond);
12126 IUIAutomationNotCondition_Release(not_cond);
12129 * Condition used to get the raw TreeView. Equivalent to:
12130 * if (1)
12132 hr = IUIAutomation_get_RawViewCondition(uia_iface, NULL);
12133 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12135 cond = NULL;
12136 hr = IUIAutomation_get_RawViewCondition(uia_iface, &cond);
12137 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12138 ok(!!cond, "cond == NULL\n");
12140 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
12141 IUIAutomationCondition_Release(cond);
12142 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12143 ok(!!bool_cond, "bool_cond == NULL\n");
12145 tmp_b = FALSE;
12146 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
12147 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12148 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
12149 IUIAutomationBoolCondition_Release(bool_cond);
12152 static void test_CUIAutomation_cache_request_iface(IUIAutomation *uia_iface)
12154 IUIAutomationPropertyCondition *prop_cond;
12155 enum PropertyConditionFlags prop_flags;
12156 IUIAutomationCacheRequest *cache_req;
12157 enum AutomationElementMode elem_mode;
12158 IUIAutomationCondition *cond, *cond2;
12159 IUIAutomationNotCondition *not_cond;
12160 enum TreeScope scope;
12161 PROPERTYID prop_id;
12162 HRESULT hr;
12163 VARIANT v;
12165 hr = IUIAutomation_CreateCacheRequest(uia_iface, NULL);
12166 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12169 * CreateCacheRequest returns an IUIAutomationCacheRequest with the
12170 * default cache request values set.
12172 cache_req = NULL;
12173 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
12174 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12175 ok(!!cache_req, "cache_req == NULL\n");
12178 * TreeScope tests.
12180 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, NULL);
12181 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12183 scope = 0;
12184 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
12185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12186 ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
12188 /* Set it to something invalid. */
12189 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, 0);
12190 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12192 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent);
12193 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12195 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors);
12196 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12198 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent | TreeScope_Element);
12199 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12201 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors | TreeScope_Element);
12202 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12204 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, ~(TreeScope_Subtree | TreeScope_Parent | TreeScope_Ancestors));
12205 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12207 /* Invalid values don't change anything. */
12208 scope = 0;
12209 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
12210 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12211 ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
12213 /* Now set it to TreeScope_Children. */
12214 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Children);
12215 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12217 scope = 0;
12218 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
12219 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12220 todo_wine ok(scope == TreeScope_Children, "Unexpected scope %#x\n", scope);
12223 * TreeFilter tests.
12225 cond = NULL;
12226 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, NULL);
12227 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12229 cond = NULL;
12230 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, NULL);
12231 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12233 cond = NULL;
12234 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, (IUIAutomationCondition *)&Object);
12235 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
12237 /* Default IUIAutomationCacheRequest has the ControlView condition. */
12238 cond = NULL;
12239 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond);
12240 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12241 ok(!!cond, "cond == NULL\n");
12243 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
12244 IUIAutomationCondition_Release(cond);
12245 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12246 ok(!!not_cond, "not_cond == NULL\n");
12248 cond = NULL;
12249 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
12250 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12251 ok(!!cond, "cond == NULL\n");
12253 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
12254 IUIAutomationCondition_Release(cond);
12255 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12256 ok(!!prop_cond, "prop_cond == NULL\n");
12258 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
12259 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12260 ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
12262 VariantInit(&v);
12263 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
12264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12265 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
12266 VariantClear(&v);
12268 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
12269 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12270 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
12272 IUIAutomationPropertyCondition_Release(prop_cond);
12273 IUIAutomationNotCondition_Release(not_cond);
12275 /* Set a new TreeFilter condition. */
12276 cond = NULL;
12277 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
12278 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12279 ok(!!cond, "cond == NULL\n");
12281 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, cond);
12282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12284 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond2);
12285 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12286 ok(!!cond2, "cond2 == NULL\n");
12287 ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
12288 IUIAutomationCondition_Release(cond);
12289 IUIAutomationCondition_Release(cond2);
12292 * AutomationElementMode tests.
12294 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, NULL);
12295 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12297 elem_mode = 0;
12298 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
12299 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12300 ok(elem_mode == AutomationElementMode_Full, "Unexpected element mode %#x\n", elem_mode);
12302 /* Invalid value - maximum is AutomationElementMode_Full, 0x01. */
12303 hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, 0x02);
12304 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12306 hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, AutomationElementMode_None);
12307 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12309 elem_mode = 0;
12310 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
12311 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12312 todo_wine ok(elem_mode == AutomationElementMode_None, "Unexpected element mode %#x\n", elem_mode);
12315 * AddProperty tests.
12317 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_IsContentElementPropertyId);
12318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12320 /* Invalid property ID. */
12321 hr = IUIAutomationCacheRequest_AddProperty(cache_req, 1);
12322 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12324 IUIAutomationCacheRequest_Release(cache_req);
12327 static const struct prov_method_sequence get_elem_cache_seq[] = {
12328 { &Provider, PROV_GET_PROPERTY_VALUE },
12329 NODE_CREATE_SEQ(&Provider_child),
12330 { 0 },
12333 static const struct prov_method_sequence get_cached_prop_val_seq[] = {
12334 { &Provider_child, FRAG_GET_RUNTIME_ID },
12335 { 0 },
12338 static const struct prov_method_sequence get_cached_prop_val_seq2[] = {
12339 { &Provider_child, FRAG_GET_RUNTIME_ID },
12340 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12341 { 0 },
12344 static const struct prov_method_sequence get_cached_prop_val_seq3[] = {
12345 { &Provider, PROV_GET_PROPERTY_VALUE },
12346 NODE_CREATE_SEQ(&Provider_child),
12347 { &Provider, PROV_GET_PROPERTY_VALUE },
12348 NODE_CREATE_SEQ(&Provider_child),
12349 NODE_CREATE_SEQ(&Provider_child2),
12350 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12351 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
12352 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
12353 { 0 },
12356 static void test_Element_cache_methods(IUIAutomation *uia_iface)
12358 HWND hwnd = create_test_hwnd("test_Element_cache_methods class");
12359 IUIAutomationElement *element, *element2, *element3;
12360 IUIAutomationCacheRequest *cache_req;
12361 IUIAutomationElementArray *elem_arr;
12362 int tmp_rt_id[2], i, len;
12363 IUnknown *unk_ns;
12364 HRESULT hr;
12365 VARIANT v;
12367 element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
12368 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
12369 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
12370 provider_add_child(&Provider, &Provider_child);
12372 hr = UiaGetReservedNotSupportedValue(&unk_ns);
12373 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12375 cache_req = NULL;
12376 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
12377 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12378 ok(!!cache_req, "cache_req == NULL\n");
12381 * Run these tests on Provider_child, it doesn't have an HWND so it will
12382 * get UIA_RuntimeIdPropertyId from GetRuntimeId.
12384 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
12385 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12386 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12387 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
12388 ok_method_sequence(get_elem_cache_seq, "get_elem_cache_seq");
12390 IUIAutomationElement_Release(element);
12391 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12393 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element);
12394 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12395 ok(!!element, "element == NULL\n");
12396 VariantClear(&v);
12399 * Passing in an invalid COM interface for IUIAutomationCacheRequest will
12400 * cause an access violation on Windows.
12402 if (0)
12404 IUIAutomationElement_BuildUpdatedCache(element, (IUIAutomationCacheRequest *)&Object, &element2);
12407 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, NULL);
12408 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12410 element2 = (void *)0xdeadbeef;
12411 hr = IUIAutomationElement_BuildUpdatedCache(element, NULL, &element2);
12412 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12413 ok(!element2, "element2 != NULL\n");
12416 * Test cached property values. The default IUIAutomationCacheRequest
12417 * always caches UIA_RuntimeIdPropertyId.
12419 element2 = NULL;
12420 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
12421 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12422 ok(!!element2, "element2 == NULL\n");
12423 ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
12425 /* RuntimeId is currently unset, so we'll get the NotSupported value. */
12426 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
12427 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12428 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12429 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
12430 VariantClear(&v);
12432 /* Attempting to get a cached value for a non-cached property. */
12433 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
12434 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12435 ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
12436 VariantClear(&v);
12438 IUIAutomationElement_Release(element2);
12440 /* RuntimeId is now set. */
12441 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
12442 element2 = NULL;
12443 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
12444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12445 ok(!!element2, "element2 == NULL\n");
12446 ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
12448 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
12449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12450 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
12451 check_runtime_id(Provider_child.runtime_id, ARRAY_SIZE(Provider_child.runtime_id), V_ARRAY(&v));
12452 VariantClear(&v);
12453 IUIAutomationElement_Release(element2);
12456 * Add UIA_IsControlElementPropertyId to the list of cached property
12457 * values.
12459 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_IsControlElementPropertyId);
12460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12462 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadb33f;
12463 element2 = NULL;
12464 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
12465 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12466 ok(!!element2, "element2 == NULL\n");
12467 ok_method_sequence(get_cached_prop_val_seq2, "get_cached_prop_val_seq2");
12469 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
12470 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12471 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
12472 check_runtime_id(Provider_child.runtime_id, ARRAY_SIZE(Provider_child.runtime_id), V_ARRAY(&v));
12473 VariantClear(&v);
12475 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
12476 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12477 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
12478 VariantClear(&v);
12480 IUIAutomationElement_Release(element2);
12481 IUIAutomationCacheRequest_Release(cache_req);
12483 IUIAutomationElement_Release(element);
12484 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
12486 /* Test cached UIAutomationType_Element properties. */
12487 element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
12489 cache_req = NULL;
12490 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
12491 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12492 ok(!!cache_req, "cache_req == NULL\n");
12494 /* UIAutomationType_Element property. */
12495 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_LabeledByPropertyId);
12496 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12498 /* UIAutomationType_ElementArray property. */
12499 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_ControllerForPropertyId);
12500 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12502 element2 = NULL;
12503 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
12504 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12505 ok(!!element2, "element2 == NULL\n");
12506 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
12507 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12509 tmp_rt_id[0] = UIA_RUNTIME_ID_PREFIX;
12510 tmp_rt_id[1] = HandleToULong(hwnd);
12511 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
12512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12513 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
12514 check_runtime_id(tmp_rt_id, ARRAY_SIZE(tmp_rt_id), V_ARRAY(&v));
12515 VariantClear(&v);
12517 /* Cached IUIAutomationElement. */
12518 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_LabeledByPropertyId, TRUE, &v);
12519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12520 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12522 element3 = NULL;
12523 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element3);
12524 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12525 ok(!!element3, "element3 == NULL\n");
12526 VariantClear(&v);
12528 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_IsControlElementPropertyId, TRUE, &v);
12529 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12530 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
12531 IUIAutomationElement_Release(element3);
12532 VariantClear(&v);
12534 /* Cached IUIAutomationElementArray. */
12535 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_ControllerForPropertyId, TRUE, &v);
12536 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12537 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12539 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
12540 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12541 ok(!!elem_arr, "elem_arr == NULL\n");
12542 VariantClear(&v);
12544 hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
12545 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12546 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
12548 for (i = 0; i < ARRAY_SIZE(uia_unk_arr_prop_val); i++)
12550 hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element3);
12551 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12552 ok(!!element3, "element3 == NULL\n");
12554 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_ControlTypePropertyId, TRUE, &v);
12555 ok(hr == S_OK, "elem[%d] Unexpected hr %#lx\n", i, hr);
12556 ok(V_VT(&v) == VT_I4, "elem[%d] Unexpected VT %d\n", i, V_VT(&v));
12557 ok(V_I4(&v) == uia_i4_prop_val, "elem[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
12559 IUIAutomationElement_Release(element3);
12560 VariantClear(&v);
12563 IUIAutomationElementArray_Release(elem_arr);
12564 IUIAutomationCacheRequest_Release(cache_req);
12567 * Reference isn't released until the element holding the cache is
12568 * destroyed.
12570 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
12571 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12573 IUIAutomationElement_Release(element2);
12574 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
12575 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
12576 ok_method_sequence(get_cached_prop_val_seq3, "get_cached_prop_val_seq3");
12578 IUIAutomationElement_Release(element);
12579 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12580 IUnknown_Release(unk_ns);
12582 DestroyWindow(hwnd);
12583 UnregisterClassA("test_Element_cache_methods class", NULL);
12586 static const struct prov_method_sequence element_find_start_seq[] = {
12587 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
12588 NODE_CREATE_SEQ(&Provider),
12589 { 0 }
12593 * Identical to find_seq7, except default cache request used by FindAll
12594 * doesn't cache UIA_RuntimeIdPropertyId.
12596 static const struct prov_method_sequence element_find_seq1[] = {
12597 { &Provider, FRAG_GET_RUNTIME_ID },
12598 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12599 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12600 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
12601 NODE_CREATE_SEQ(&Provider_child),
12602 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12603 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
12604 NODE_CREATE_SEQ(&Provider_child_child),
12605 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12606 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12607 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12608 NODE_CREATE_SEQ(&Provider_child_child2),
12609 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12610 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12611 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12612 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
12613 NODE_CREATE_SEQ(&Provider_child),
12614 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12615 NODE_CREATE_SEQ(&Provider_child2),
12616 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12617 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12618 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12619 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
12620 NODE_CREATE_SEQ(&Provider),
12621 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12622 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
12623 /* Only done on Win10v1507 and below. */
12624 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
12625 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
12626 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
12627 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
12628 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
12629 { 0 },
12633 * Identical to find_seq11, except default cache request used by FindFirst
12634 * doesn't cache UIA_RuntimeIdPropertyId.
12636 static const struct prov_method_sequence element_find_seq2[] = {
12637 { &Provider, FRAG_GET_RUNTIME_ID },
12638 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12639 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
12640 NODE_CREATE_SEQ(&Provider_child),
12641 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12642 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
12643 NODE_CREATE_SEQ(&Provider_child_child),
12644 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12645 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
12646 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
12647 NODE_CREATE_SEQ(&Provider_child_child2),
12648 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
12649 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
12650 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
12651 { 0 },
12654 struct exp_elem_desc {
12655 struct Provider *elem_prov;
12656 struct node_provider_desc prov_desc;
12657 ULONG exp_refcnt;
12658 ULONG exp_release_refcnt;
12661 static void set_elem_desc(struct exp_elem_desc *desc, struct Provider *prov, HWND hwnd, DWORD pid, ULONG exp_refcnt,
12662 ULONG exp_release_refcnt)
12664 desc->elem_prov = prov;
12665 init_node_provider_desc(&desc->prov_desc, pid, hwnd);
12666 desc->exp_refcnt = exp_refcnt;
12667 desc->exp_release_refcnt = exp_release_refcnt;
12670 #define test_uia_element_arr( elem_arr, exp_elems, exp_elems_count ) \
12671 test_uia_element_arr_( (elem_arr), (exp_elems), (exp_elems_count), __FILE__, __LINE__)
12672 static void test_uia_element_arr_(IUIAutomationElementArray *elem_arr, struct exp_elem_desc *exp_elems, int exp_elems_count,
12673 const char *file, int line)
12675 int i, arr_length;
12676 HRESULT hr;
12678 hr = IUIAutomationElementArray_get_Length(elem_arr, &arr_length);
12679 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12680 ok_(file, line)(hr == S_OK, "IUIAutomationElementArray_get_Length: Unexpected hr %#lx\n", hr);
12681 ok_(file, line)(arr_length == exp_elems_count, "Unexpected arr_length %d.\n", arr_length);
12683 for (i = 0; i < arr_length; i++)
12685 struct exp_elem_desc *desc = &exp_elems[i];
12686 IUIAutomationElement *element;
12687 VARIANT v;
12689 ok_(file, line)(desc->elem_prov->ref == desc->exp_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
12691 VariantInit(&v);
12692 element = NULL;
12693 hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element);
12694 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12695 ok(!!element, "element == NULL\n");
12697 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
12698 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
12699 test_node_provider_desc_(&exp_elems[i].prov_desc, V_BSTR(&v), file, line);
12700 VariantClear(&v);
12701 IUIAutomationElement_Release(element);
12704 IUIAutomationElementArray_Release(elem_arr);
12706 for (i = 0; i < arr_length; i++)
12708 struct exp_elem_desc *desc = &exp_elems[i];
12710 ok_(file, line)(desc->elem_prov->ref == desc->exp_release_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
12714 static void test_Element_Find(IUIAutomation *uia_iface)
12716 HWND hwnd = create_test_hwnd("test_Element_Find class");
12717 IUIAutomationCondition *condition, *condition2;
12718 struct Provider_prop_override prop_override;
12719 struct exp_elem_desc exp_elems[7] = { 0 };
12720 IUIAutomationElement *element, *element2;
12721 IUIAutomationElementArray *element_arr;
12722 IUIAutomationCacheRequest *cache_req;
12723 HRESULT hr;
12724 VARIANT v;
12726 element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
12729 * The COM API has no equivalent to UiaNodeFromProvider, so the only way
12730 * we can get an initial element is with ElementFromHandle. This means our
12731 * element representing Provider will have an HWND associated, which
12732 * doesn't match our old UiaFind tests. To work around this, make Provider
12733 * return itself for the UIA_LabeledByPropertyId to get an element without
12734 * an HWND associated.
12736 VariantInit(&v);
12737 V_VT(&v) = VT_UNKNOWN;
12738 V_UNKNOWN(&v) = (IUnknown *)&Provider.IRawElementProviderSimple_iface;
12739 set_property_override(&prop_override, UIA_LabeledByPropertyId, &v);
12740 set_provider_prop_override(&Provider, &prop_override, 1);
12741 Provider.hwnd = NULL;
12743 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
12744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12745 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12746 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
12748 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
12749 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12750 ok(!!element2, "element2 == NULL\n");
12751 VariantClear(&v);
12752 ok_method_sequence(element_find_start_seq, "element_find_start_seq");
12753 set_provider_prop_override(&Provider, NULL, 0);
12755 IUIAutomationElement_Release(element);
12756 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
12758 element = element2;
12759 element2 = NULL;
12761 initialize_provider_tree(TRUE);
12762 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
12763 provider_add_child(&Provider, &Provider_child);
12764 provider_add_child(&Provider, &Provider_child2);
12765 provider_add_child(&Provider_child, &Provider_child_child);
12766 provider_add_child(&Provider_child, &Provider_child_child2);
12767 provider_add_child(&Provider_child2, &Provider_child2_child);
12768 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
12771 * In order to match the tests from test_UiaFind(), we need to create a
12772 * custom IUIAutomationCacheRequest with a ConditionType_True treeview.
12773 * The default cache request also caches the RuntimeId property.
12775 cache_req = NULL;
12776 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
12777 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12778 ok(!!cache_req, "cache_req == NULL\n");
12780 /* Set view condition to ConditionType_True. */
12781 condition = NULL;
12782 hr = IUIAutomation_CreateTrueCondition(uia_iface, &condition);
12783 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12784 ok(!!condition, "condition == NULL\n");
12786 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, condition);
12787 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12790 * Equivalent to: Maximum find depth of -1, find first is FALSE, exclude
12791 * root is FALSE.
12793 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Subtree, condition, cache_req, &element_arr);
12794 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12796 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
12797 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
12798 set_elem_desc(&exp_elems[1], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
12799 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child", TRUE);
12800 set_elem_desc(&exp_elems[2], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
12801 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child", TRUE);
12802 set_elem_desc(&exp_elems[3], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
12803 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child_child2", TRUE);
12804 set_elem_desc(&exp_elems[4], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
12805 add_provider_desc(&exp_elems[4].prov_desc, L"Main", L"Provider_child2", TRUE);
12806 set_elem_desc(&exp_elems[5], &Provider_child2_child, NULL, GetCurrentProcessId(), 2, 1);
12807 add_provider_desc(&exp_elems[5].prov_desc, L"Main", L"Provider_child2_child", TRUE);
12808 set_elem_desc(&exp_elems[6], &Provider_child2_child_child, NULL, GetCurrentProcessId(), 2, 1);
12809 add_provider_desc(&exp_elems[6].prov_desc, L"Main", L"Provider_child2_child_child", TRUE);
12811 test_uia_element_arr(element_arr, exp_elems, 7);
12812 ok_method_sequence(find_seq1, "find_seq1");
12815 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
12816 * is FALSE.
12818 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition, cache_req, &element_arr);
12819 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12821 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
12822 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
12823 set_elem_desc(&exp_elems[1], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
12824 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child", TRUE);
12825 set_elem_desc(&exp_elems[2], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
12826 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child2", TRUE);
12828 test_uia_element_arr(element_arr, exp_elems, 3);
12829 ok_method_sequence(find_seq2, "find_seq2");
12832 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
12833 * is TRUE.
12835 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Children, condition, cache_req, &element_arr);
12836 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12838 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
12839 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
12840 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
12841 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
12843 test_uia_element_arr(element_arr, exp_elems, 2);
12844 ok_method_sequence(find_seq3, "find_seq3");
12847 * Equivalent to: Maximum find depth of 1, find first is TRUE, exclude
12848 * root is TRUE. element2 now represents Provider_child.
12850 hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Children, condition, cache_req, &element2);
12851 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12852 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
12854 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
12855 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12856 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
12857 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
12858 VariantClear(&v);
12860 ok_method_sequence(find_seq4, "find_seq4");
12863 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
12864 * root is FALSE. Provider_child doesn't have a runtime id for UI
12865 * Automation to use as a way to check if it has navigated back to the
12866 * node that began the search, so it will get siblings.
12868 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
12869 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12871 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 2);
12872 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
12873 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
12874 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
12876 test_uia_element_arr(element_arr, exp_elems, 2);
12877 ok_method_sequence(find_seq5, "find_seq5");
12880 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
12881 * root is FALSE. Provider_child now has a runtime ID, so we don't get
12882 * its sibling.
12884 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
12885 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
12886 IUIAutomationElement_Release(element2);
12887 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12889 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
12890 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
12892 test_uia_element_arr(element_arr, exp_elems, 1);
12893 ok_method_sequence(find_seq6, "find_seq6");
12894 initialize_provider_tree(FALSE);
12896 IUIAutomationCondition_Release(condition);
12898 /* condition is now UIA_IsContentElementPropertyId == FALSE. */
12899 condition = NULL;
12900 variant_init_bool(&v, FALSE);
12901 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &condition);
12902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12903 ok(!!condition, "condition == NULL\n");
12905 /* Set view condition to this property condition. */
12906 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, condition);
12907 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12909 /* condition2 is UIA_IsControlElementPropertyId == TRUE. */
12910 condition2 = NULL;
12911 variant_init_bool(&v, TRUE);
12912 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsControlElementPropertyId, v, &condition2);
12913 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12914 ok(!!condition2, "condition2 == NULL\n");
12916 /* Override UIA_IsContentElementPropertyId, set it to FALSE. */
12917 variant_init_bool(&v, FALSE);
12918 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12919 set_provider_prop_override(&Provider, &prop_override, 1);
12920 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12921 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
12922 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12925 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
12926 * root is FALSE. The cache request view condition is used to determine
12927 * tree depth, if an element matches the cache request view condition,
12928 * depth is incremented. Since Provider_child does not, Provider_child_child,
12929 * Provider_child_child2, and Provider_child2 are all considered to be at
12930 * depth 1.
12932 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
12933 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12935 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
12936 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
12937 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
12938 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
12939 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
12940 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
12941 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
12942 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
12944 test_uia_element_arr(element_arr, exp_elems, 4);
12945 ok_method_sequence(find_seq7, "find_seq7");
12946 initialize_provider_tree(FALSE);
12949 * Same test as before, except now Provider has a runtime ID.
12951 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
12952 variant_init_bool(&v, FALSE);
12953 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12954 set_provider_prop_override(&Provider, &prop_override, 1);
12955 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12956 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
12957 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12959 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
12960 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12962 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
12963 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
12964 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
12965 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
12966 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 2);
12967 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
12968 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
12969 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
12971 /* element2 now represents Provider_child_child2. */
12972 hr = IUIAutomationElementArray_GetElement(element_arr, 2, &element2);
12973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12975 test_uia_element_arr(element_arr, exp_elems, 4);
12976 ok_method_sequence(find_seq8, "find_seq8");
12977 initialize_provider_tree(FALSE);
12979 variant_init_bool(&v, FALSE);
12980 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12981 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12982 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12983 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
12986 * Equivalent to: Maximum find depth of 1, find first is FALSE,
12987 * exclude root is FALSE. Starting at Provider_child_child2, find
12988 * will be able to traverse the tree in the same order as it would
12989 * if we had started at the tree root Provider, retrieving
12990 * Provider_child2 as a sibling and Provider_child2_child as a node
12991 * at depth 1.
12993 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
12994 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12995 IUIAutomationElement_Release(element2);
12997 set_elem_desc(&exp_elems[0], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
12998 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child_child2", TRUE);
12999 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13000 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
13001 set_elem_desc(&exp_elems[2], &Provider_child2_child, NULL, GetCurrentProcessId(), 2, 1);
13002 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child2_child", TRUE);
13004 test_uia_element_arr(element_arr, exp_elems, 3);
13005 ok_method_sequence(find_seq9, "find_seq9");
13006 initialize_provider_tree(FALSE);
13009 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
13010 * root is TRUE. Exclude root applies to the first node that matches the
13011 * view condition, and not the node that is passed into UiaFind(). Since
13012 * Provider doesn't match our view condition here, Provider_child will be
13013 * excluded.
13015 variant_init_bool(&v, FALSE);
13016 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
13017 set_provider_prop_override(&Provider_child, &prop_override, 1);
13018 set_provider_prop_override(&Provider_child2, &prop_override, 1);
13019 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Children, condition2, cache_req, &element_arr);
13020 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13022 set_elem_desc(&exp_elems[0], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13023 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child2", TRUE);
13025 test_uia_element_arr(element_arr, exp_elems, 1);
13026 ok_method_sequence(find_seq10, "find_seq10");
13027 initialize_provider_tree(FALSE);
13029 variant_init_bool(&v, FALSE);
13030 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
13031 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
13034 * Equivalent to: Maximum find depth of -1, find first is TRUE, exclude
13035 * root is FALSE. Provider_child_child2 is the only element in the tree
13036 * to match our condition.
13038 hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Subtree, condition, cache_req, &element2);
13039 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13040 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
13042 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13043 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13044 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
13045 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
13046 VariantClear(&v);
13048 IUIAutomationElement_Release(element2);
13049 ok_method_sequence(find_seq11, "find_seq11");
13050 initialize_provider_tree(FALSE);
13052 IUIAutomationCondition_Release(condition);
13053 IUIAutomationCondition_Release(condition2);
13054 IUIAutomationCacheRequest_Release(cache_req);
13057 * Equivalent to: Maximum find depth of 1, find first is FALSE,
13058 * exclude root is FALSE. FindAll() uses the default
13059 * IUIAutomationCacheRequest, which uses the ControlView condition
13060 * as its view condition. Since Provider_child doesn't match this view
13061 * condition, it isn't a child of Provider in this treeview. No property
13062 * values are cached by the default internal cache request, so we need to
13063 * use a separate method sequence.
13065 variant_init_bool(&v, FALSE);
13066 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
13067 set_provider_prop_override(&Provider_child, &prop_override, 1);
13069 /* condition is now UIA_IsContentElementPropertyId == TRUE. */
13070 variant_init_bool(&v, TRUE);
13071 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &condition);
13072 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13073 ok(!!condition, "cond == NULL\n");
13075 hr = IUIAutomationElement_FindAll(element, TreeScope_Element | TreeScope_Children, condition, &element_arr);
13076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13078 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
13079 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
13080 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
13081 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
13082 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
13083 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
13084 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13085 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
13087 test_uia_element_arr(element_arr, exp_elems, 4);
13088 ok_method_sequence(element_find_seq1, "element_find_seq1");
13089 initialize_provider_tree(FALSE);
13092 * Equivalent to: Maximum find depth of -1, find first is TRUE,
13093 * exclude root is FALSE. FindFirst() also uses the default cache request.
13094 * Provider_child_child2 will be the first provider in the tree to match
13095 * this view condition, so it will be returned.
13097 variant_init_bool(&v, FALSE);
13098 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
13099 set_provider_prop_override(&Provider, &prop_override, 1);
13100 set_provider_prop_override(&Provider_child, &prop_override, 1);
13101 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
13103 hr = IUIAutomationElement_FindFirst(element, TreeScope_Subtree, condition, &element2);
13104 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13105 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
13107 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13108 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13109 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
13110 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
13111 VariantClear(&v);
13113 IUIAutomationElement_Release(element2);
13114 ok_method_sequence(element_find_seq2, "element_find_seq2");
13115 initialize_provider_tree(TRUE);
13117 IUIAutomationCondition_Release(condition);
13118 IUIAutomationElement_Release(element);
13119 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
13121 DestroyWindow(hwnd);
13122 UnregisterClassA("test_Element_Find class", NULL);
13125 static const struct prov_method_sequence treewalker_seq1[] = {
13126 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13127 NODE_CREATE_SEQ(&Provider_child),
13128 { 0 }
13131 static const struct prov_method_sequence treewalker_seq2[] = {
13132 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13133 NODE_CREATE_SEQ(&Provider_child),
13134 { &Provider_child, FRAG_GET_RUNTIME_ID },
13135 { 0 }
13138 static const struct prov_method_sequence treewalker_seq3[] = {
13139 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
13140 NODE_CREATE_SEQ(&Provider_child2),
13141 { 0 }
13144 static const struct prov_method_sequence treewalker_seq4[] = {
13145 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
13146 NODE_CREATE_SEQ(&Provider_child2),
13147 { &Provider_child2, FRAG_GET_RUNTIME_ID },
13148 { 0 }
13151 static const struct prov_method_sequence treewalker_seq5[] = {
13152 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13153 NODE_CREATE_SEQ(&Provider_child2),
13154 { 0 }
13157 static const struct prov_method_sequence treewalker_seq6[] = {
13158 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13159 NODE_CREATE_SEQ(&Provider_child2),
13160 { &Provider_child2, FRAG_GET_RUNTIME_ID },
13161 { 0 }
13164 static const struct prov_method_sequence treewalker_seq7[] = {
13165 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
13166 NODE_CREATE_SEQ(&Provider_child),
13167 { 0 }
13170 static const struct prov_method_sequence treewalker_seq8[] = {
13171 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
13172 NODE_CREATE_SEQ(&Provider_child),
13173 { &Provider_child, FRAG_GET_RUNTIME_ID },
13174 { 0 }
13177 static const struct prov_method_sequence treewalker_seq9[] = {
13178 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13179 NODE_CREATE_SEQ(&Provider),
13180 { 0 }
13183 static const struct prov_method_sequence treewalker_seq10[] = {
13184 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13185 NODE_CREATE_SEQ(&Provider),
13186 { &Provider, FRAG_GET_RUNTIME_ID },
13187 { 0 }
13190 static void test_CUIAutomation_TreeWalker_ifaces(IUIAutomation *uia_iface)
13192 HWND hwnd = create_test_hwnd("test_CUIAutomation_TreeWalker_ifaces class");
13193 IUIAutomationElement *element, *element2, *element3;
13194 IUIAutomationCacheRequest *cache_req;
13195 IUIAutomationCondition *cond, *cond2;
13196 IUIAutomationTreeWalker *walker;
13197 HRESULT hr;
13199 cond = NULL;
13200 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
13201 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13202 ok(!!cond, "cond == NULL\n");
13204 /* NULL input argument tests. */
13205 walker = (void *)0xdeadbeef;
13206 hr = IUIAutomation_CreateTreeWalker(uia_iface, NULL, &walker);
13207 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13208 ok(!walker, "walker != NULL\n");
13210 hr = IUIAutomation_CreateTreeWalker(uia_iface, cond, NULL);
13211 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13213 /* Actually create TreeWalker. */
13214 walker = NULL;
13215 hr = IUIAutomation_CreateTreeWalker(uia_iface, cond, &walker);
13216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13217 ok(!!walker, "walker == NULL\n");
13219 hr = IUIAutomationTreeWalker_get_Condition(walker, &cond2);
13220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13221 ok(!!cond2, "cond2 == NULL\n");
13223 ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
13224 IUIAutomationCondition_Release(cond);
13225 IUIAutomationCondition_Release(cond2);
13227 cache_req = NULL;
13228 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13229 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13230 ok(!!cache_req, "cache_req == NULL\n");
13232 element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
13233 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13234 initialize_provider(&Provider_child2, ProviderOptions_ServerSideProvider, NULL, TRUE);
13235 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
13236 provider_add_child(&Provider, &Provider_child);
13237 provider_add_child(&Provider, &Provider_child2);
13239 /* NULL input argument tests. */
13240 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, element, NULL);
13241 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13243 element2 = (void *)0xdeadbeef;
13244 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, NULL, &element2);
13245 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13246 ok(!element2, "element2 != NULL\n");
13248 /* NavigateDirection_FirstChild. */
13249 element2 = NULL;
13250 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, element, &element2);
13251 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13252 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13253 ok(!!element2, "element2 == NULL\n");
13254 ok_method_sequence(treewalker_seq1, "treewalker_seq1");
13256 IUIAutomationElement_Release(element2);
13257 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13259 element2 = NULL;
13260 hr = IUIAutomationTreeWalker_GetFirstChildElementBuildCache(walker, element, cache_req, &element2);
13261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13262 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13263 ok(!!element2, "element2 == NULL\n");
13264 ok_method_sequence(treewalker_seq2, "treewalker_seq2");
13266 /* NavigateDirection_NextSibling. */
13267 element3 = NULL;
13268 hr = IUIAutomationTreeWalker_GetNextSiblingElement(walker, element2, &element3);
13269 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13270 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13271 ok(!!element3, "element3 == NULL\n");
13272 ok_method_sequence(treewalker_seq5, "treewalker_seq5");
13273 IUIAutomationElement_Release(element3);
13274 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
13276 element3 = NULL;
13277 hr = IUIAutomationTreeWalker_GetNextSiblingElementBuildCache(walker, element2, cache_req, &element3);
13278 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13279 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13280 ok(!!element3, "element3 == NULL\n");
13281 ok_method_sequence(treewalker_seq6, "treewalker_seq6");
13282 IUIAutomationElement_Release(element3);
13283 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
13285 IUIAutomationElement_Release(element2);
13286 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13288 /* NavigateDirection_LastChild. */
13289 element2 = NULL;
13290 hr = IUIAutomationTreeWalker_GetLastChildElement(walker, element, &element2);
13291 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13292 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13293 ok(!!element2, "element2 == NULL\n");
13294 ok_method_sequence(treewalker_seq3, "treewalker_seq3");
13296 IUIAutomationElement_Release(element2);
13297 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
13299 element2 = NULL;
13300 hr = IUIAutomationTreeWalker_GetLastChildElementBuildCache(walker, element, cache_req, &element2);
13301 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13302 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13303 ok(!!element2, "element2 == NULL\n");
13304 ok_method_sequence(treewalker_seq4, "treewalker_seq4");
13306 /* NavigateDirection_PreviousSibling. */
13307 element3 = NULL;
13308 hr = IUIAutomationTreeWalker_GetPreviousSiblingElement(walker, element2, &element3);
13309 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13310 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13311 ok(!!element3, "element3 == NULL\n");
13312 ok_method_sequence(treewalker_seq7, "treewalker_seq7");
13313 IUIAutomationElement_Release(element3);
13314 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13316 element3 = NULL;
13317 hr = IUIAutomationTreeWalker_GetPreviousSiblingElementBuildCache(walker, element2, cache_req, &element3);
13318 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13319 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13320 ok(!!element3, "element3 == NULL\n");
13321 ok_method_sequence(treewalker_seq8, "treewalker_seq8");
13322 IUIAutomationElement_Release(element3);
13323 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13325 /* NavigateDirection_Parent. */
13326 element3 = NULL;
13327 Provider.hwnd = NULL;
13328 hr = IUIAutomationTreeWalker_GetParentElement(walker, element2, &element3);
13329 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13330 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
13331 ok(!!element3, "element3 == NULL\n");
13332 ok_method_sequence(treewalker_seq9, "treewalker_seq9");
13333 IUIAutomationElement_Release(element3);
13334 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
13336 element3 = NULL;
13337 hr = IUIAutomationTreeWalker_GetParentElementBuildCache(walker, element2, cache_req, &element3);
13338 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13339 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
13340 ok(!!element3, "element3 == NULL\n");
13341 ok_method_sequence(treewalker_seq10, "treewalker_seq10");
13342 IUIAutomationElement_Release(element3);
13343 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
13345 IUIAutomationElement_Release(element2);
13346 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
13348 IUIAutomationElement_Release(element);
13349 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
13351 IUIAutomationCacheRequest_Release(cache_req);
13352 IUIAutomationTreeWalker_Release(walker);
13354 DestroyWindow(hwnd);
13355 UnregisterClassA("test_CUIAutomation_TreeWalker_ifaces class", NULL);
13358 static void set_clientside_providers_for_hwnd(struct Provider *proxy_prov, struct Provider *nc_prov,
13359 struct Provider *hwnd_prov, HWND hwnd)
13361 if (proxy_prov)
13363 initialize_provider(proxy_prov, ProviderOptions_ClientSideProvider, hwnd, TRUE);
13364 proxy_prov->frag_root = &proxy_prov->IRawElementProviderFragmentRoot_iface;
13365 proxy_prov->ignore_hwnd_prop = TRUE;
13368 initialize_provider(hwnd_prov, ProviderOptions_ClientSideProvider, hwnd, TRUE);
13369 initialize_provider(nc_prov, ProviderOptions_NonClientAreaProvider | ProviderOptions_ClientSideProvider, hwnd, TRUE);
13370 hwnd_prov->frag_root = &hwnd_prov->IRawElementProviderFragmentRoot_iface;
13371 nc_prov->frag_root = &nc_prov->IRawElementProviderFragmentRoot_iface;
13372 nc_prov->ignore_hwnd_prop = TRUE;
13375 static void test_GetRootElement(IUIAutomation *uia_iface)
13377 IUIAutomationElement *element;
13378 HRESULT hr;
13379 VARIANT v;
13381 hr = IUIAutomation_GetRootElement(uia_iface, NULL);
13382 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13384 UiaRegisterProviderCallback(test_uia_provider_callback);
13386 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
13387 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
13388 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
13389 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
13391 /* Retrieve an element representing the desktop HWND. */
13392 method_sequences_enabled = FALSE;
13393 SET_EXPECT(prov_callback_base_hwnd);
13394 SET_EXPECT(prov_callback_nonclient);
13395 SET_EXPECT(prov_callback_proxy);
13396 hr = IUIAutomation_GetRootElement(uia_iface, &element);
13397 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13398 ok(!!element, "Node == NULL.\n");
13399 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
13400 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
13401 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
13402 CHECK_CALLED(prov_callback_base_hwnd);
13403 CHECK_CALLED(prov_callback_nonclient);
13404 CHECK_CALLED(prov_callback_proxy);
13406 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13407 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13408 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), GetDesktopWindow());
13409 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
13410 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
13411 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
13412 VariantClear(&v);
13414 IUIAutomationElement_Release(element);
13415 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
13416 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
13417 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
13419 initialize_provider(&Provider_hwnd, ProviderOptions_ClientSideProvider, NULL, TRUE);
13420 initialize_provider(&Provider_nc, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider, NULL,
13421 TRUE);
13422 initialize_provider(&Provider_proxy, ProviderOptions_ClientSideProvider, NULL, TRUE);
13423 base_hwnd_prov = proxy_prov = nc_prov = NULL;
13425 method_sequences_enabled = TRUE;
13426 UiaRegisterProviderCallback(NULL);
13429 #define test_get_focused_elem( uia_iface, cache_req, exp_hr, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, \
13430 nc_cback_count, win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, \
13431 base_hwnd_cback_todo, nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo ) \
13432 test_get_focused_elem_( (uia_iface), (cache_req), (exp_hr), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), \
13433 (nc_cback_count), (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), \
13434 (base_hwnd_cback_todo), (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
13435 static void test_get_focused_elem_(IUIAutomation *uia_iface, IUIAutomationCacheRequest *cache_req, HRESULT exp_hr,
13436 struct node_provider_desc *exp_node_desc, int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
13437 int win_get_obj_count, int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo,
13438 BOOL nc_cback_todo, BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
13440 IUIAutomationElement *element = NULL;
13441 HRESULT hr;
13442 VARIANT v;
13444 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
13445 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
13446 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
13447 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
13448 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
13449 if (cache_req)
13450 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, &element);
13451 else
13452 hr = IUIAutomation_GetFocusedElement(uia_iface, &element);
13453 ok_(file, line)(hr == exp_hr, "Unexpected hr %#lx.\n", hr);
13454 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
13455 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
13456 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
13457 todo_wine_if(win_get_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
13458 todo_wine_if(child_win_get_obj_todo) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
13460 if (exp_node_desc->prov_count)
13462 ok_(file, line)(!!element, "element == NULL\n");
13464 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13465 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
13466 test_node_provider_desc_(exp_node_desc, V_BSTR(&v), file, line);
13467 VariantClear(&v);
13469 IUIAutomationElement_Release(element);
13471 else
13472 ok_(file, line)(!element, "element != NULL\n");
13475 static void test_GetFocusedElement(IUIAutomation *uia_iface)
13477 struct Provider_prop_override prop_override;
13478 struct node_provider_desc exp_node_desc;
13479 IUIAutomationCacheRequest *cache_req;
13480 IUIAutomationElement *element;
13481 HWND hwnd, hwnd_child;
13482 HRESULT hr;
13483 VARIANT v;
13485 hwnd = create_test_hwnd("test_GetFocusedElement class");
13486 hwnd_child = create_child_test_hwnd("test_GetFocusedElement child class", hwnd);
13487 UiaRegisterProviderCallback(test_uia_provider_callback);
13489 cache_req = NULL;
13490 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13491 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13492 ok(!!cache_req, "cache_req == NULL\n");
13495 * Set clientside providers for our test windows and the desktop. Same
13496 * tests as UiaNodeFromFocus, just with COM methods.
13498 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
13499 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
13500 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
13501 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
13503 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
13504 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
13505 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
13506 prov_root = &Provider.IRawElementProviderSimple_iface;
13507 Provider.ignore_hwnd_prop = TRUE;
13509 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, hwnd_child);
13510 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, hwnd_child, TRUE);
13511 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
13512 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
13513 Provider2.ignore_hwnd_prop = TRUE;
13515 /* NULL input argument tests. */
13516 hr = IUIAutomation_GetFocusedElement(uia_iface, NULL);
13517 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13519 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, NULL);
13520 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13522 element = (void *)0xdeadbeef;
13523 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, NULL, &element);
13524 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13525 ok(!element, "element != NULL\n");
13528 * None of the providers for the desktop node return a provider from
13529 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
13530 * desktop node.
13532 method_sequences_enabled = FALSE;
13533 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), GetDesktopWindow());
13534 add_provider_desc(&exp_node_desc, L"Main", L"Provider_proxy", TRUE);
13535 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc", FALSE);
13536 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd", FALSE);
13538 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
13539 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
13541 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
13542 Provider_hwnd.focus_prov = &Provider_hwnd2.IRawElementProviderFragment_iface;
13544 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
13545 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
13546 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
13547 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
13549 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
13550 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
13553 * Provider_proxy returns Provider from GetFocus. The provider that
13554 * creates the node will not have GetFocus called on it to avoid returning
13555 * the same provider twice. Similarly, on nodes other than the desktop
13556 * node, the HWND provider will not have GetFocus called on it.
13558 Provider_hwnd.focus_prov = NULL;
13559 Provider_proxy.focus_prov = &Provider.IRawElementProviderFragment_iface;
13560 Provider.focus_prov = Provider_hwnd2.focus_prov = &Provider2.IRawElementProviderFragment_iface;
13562 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
13563 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
13564 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
13565 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
13567 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
13568 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
13571 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
13572 * Provider2, Provider_nc3 returns Provider_child.
13574 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13575 Provider_proxy.focus_prov = Provider_hwnd.focus_prov = NULL;
13576 Provider_nc.focus_prov = &Provider_nc2.IRawElementProviderFragment_iface;
13577 Provider.focus_prov = &Provider2.IRawElementProviderFragment_iface;
13578 Provider_nc3.focus_prov = &Provider_child.IRawElementProviderFragment_iface;
13580 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
13581 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
13583 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
13584 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
13587 * Provider_proxy returns Provider_child_child from GetFocus. The focus
13588 * provider is normalized against the cache request view condition.
13589 * Provider_child_child and its ancestors don't match the cache request
13590 * view condition, so we'll get no provider.
13592 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13593 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13594 provider_add_child(&Provider, &Provider_child);
13595 provider_add_child(&Provider_child, &Provider_child_child);
13596 Provider_proxy.focus_prov = &Provider_child_child.IRawElementProviderFragment_iface;
13597 Provider_nc.focus_prov = Provider_hwnd.focus_prov = NULL;
13599 variant_init_bool(&v, FALSE);
13600 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
13601 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
13602 set_provider_prop_override(&Provider_child, &prop_override, 1);
13603 set_provider_prop_override(&Provider, &prop_override, 1);
13606 * GetFocusedElement returns UIA_E_ELEMENTNOTAVAILABLE when no provider
13607 * matches our view condition, GetFocusedElementBuildCache returns E_FAIL.
13609 init_node_provider_desc(&exp_node_desc, 0, NULL);
13610 test_get_focused_elem(uia_iface, NULL, UIA_E_ELEMENTNOTAVAILABLE,
13611 &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
13612 test_get_focused_elem(uia_iface, cache_req, E_FAIL,
13613 &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
13615 /* This time, Provider_child matches our view condition. */
13616 set_provider_prop_override(&Provider_child, NULL, 0);
13618 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
13619 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
13621 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
13623 method_sequences_enabled = TRUE;
13624 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, TRUE);
13625 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13626 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13628 base_hwnd_prov = nc_prov = proxy_prov = prov_root = NULL;
13629 IUIAutomationCacheRequest_Release(cache_req);
13630 UiaRegisterProviderCallback(NULL);
13631 DestroyWindow(hwnd);
13632 UnregisterClassA("test_GetFocusedElement class", NULL);
13633 UnregisterClassA("test_GetFocusedElement child class", NULL);
13636 static void set_uia_hwnd_expects(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
13637 int win_get_uia_obj_count, int win_get_client_obj_count)
13639 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
13640 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
13641 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
13642 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
13643 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
13646 static void check_uia_hwnd_expects(int proxy_cback_count, BOOL proxy_cback_todo,
13647 int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo,
13648 int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
13650 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
13651 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
13652 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
13653 todo_wine_if(win_get_uia_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
13654 if (win_get_client_obj_count)
13655 todo_wine_if(win_get_client_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
13658 static void check_uia_hwnd_expects_at_most(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
13659 int win_get_uia_obj_count, int win_get_client_obj_count)
13661 CHECK_CALLED_AT_MOST(prov_callback_proxy, proxy_cback_count);
13662 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, base_hwnd_cback_count);
13663 CHECK_CALLED_AT_MOST(prov_callback_nonclient, nc_cback_count);
13664 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
13665 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
13668 static struct ComEventData {
13669 struct node_provider_desc exp_node_desc;
13670 struct node_provider_desc exp_nested_node_desc;
13672 HWND event_hwnd;
13673 DWORD last_call_tid;
13674 } ComEventData;
13676 static void set_com_event_data(struct node_provider_desc *exp_node_desc)
13678 if (exp_node_desc)
13680 int i;
13682 ComEventData.exp_node_desc = *exp_node_desc;
13683 for (i = 0; i < exp_node_desc->prov_count; i++)
13685 if (exp_node_desc->nested_desc[i])
13687 ComEventData.exp_nested_node_desc = *exp_node_desc->nested_desc[i];
13688 ComEventData.exp_node_desc.nested_desc[i] = &ComEventData.exp_nested_node_desc;
13689 break;
13693 else
13694 memset(&ComEventData.exp_node_desc, 0, sizeof(ComEventData.exp_node_desc));
13695 ComEventData.last_call_tid = 0;
13696 SET_EXPECT(uia_com_event_callback);
13699 #define test_com_event_data( sender ) \
13700 test_com_event_data_( (sender), __FILE__, __LINE__)
13701 static void test_com_event_data_(IUIAutomationElement *sender, const char *file, int line)
13703 HRESULT hr;
13704 VARIANT v;
13706 CHECK_EXPECT(uia_com_event_callback);
13708 VariantInit(&v);
13709 hr = IUIAutomationElement_GetCurrentPropertyValueEx(sender, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13710 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
13711 test_node_provider_desc_(&ComEventData.exp_node_desc, V_BSTR(&v), file, line);
13712 VariantClear(&v);
13714 ComEventData.last_call_tid = GetCurrentThreadId();
13718 * IUIAutomationEventHandler.
13720 static struct AutomationEventHandler
13722 IUIAutomationEventHandler IUIAutomationEventHandler_iface;
13723 LONG ref;
13724 } AutomationEventHandler;
13726 static inline struct AutomationEventHandler *impl_from_AutomationEventHandler(IUIAutomationEventHandler *iface)
13728 return CONTAINING_RECORD(iface, struct AutomationEventHandler, IUIAutomationEventHandler_iface);
13731 static HRESULT WINAPI AutomationEventHandler_QueryInterface(IUIAutomationEventHandler *iface, REFIID riid, void **ppv)
13733 *ppv = NULL;
13734 if (IsEqualIID(riid, &IID_IUIAutomationEventHandler) || IsEqualIID(riid, &IID_IUnknown))
13735 *ppv = iface;
13736 else
13737 return E_NOINTERFACE;
13739 IUIAutomationEventHandler_AddRef(iface);
13740 return S_OK;
13743 static ULONG WINAPI AutomationEventHandler_AddRef(IUIAutomationEventHandler* iface)
13745 struct AutomationEventHandler *handler = impl_from_AutomationEventHandler(iface);
13746 return InterlockedIncrement(&handler->ref);
13749 static ULONG WINAPI AutomationEventHandler_Release(IUIAutomationEventHandler* iface)
13751 struct AutomationEventHandler *handler = impl_from_AutomationEventHandler(iface);
13752 return InterlockedDecrement(&handler->ref);
13755 static HRESULT WINAPI AutomationEventHandler_HandleAutomationEvent(IUIAutomationEventHandler *iface,
13756 IUIAutomationElement *sender, EVENTID event_id)
13758 test_com_event_data(sender);
13760 return S_OK;
13763 static const IUIAutomationEventHandlerVtbl AutomationEventHandlerVtbl = {
13764 AutomationEventHandler_QueryInterface,
13765 AutomationEventHandler_AddRef,
13766 AutomationEventHandler_Release,
13767 AutomationEventHandler_HandleAutomationEvent,
13770 static struct AutomationEventHandler AutomationEventHandler =
13772 { &AutomationEventHandlerVtbl },
13777 * IUIAutomationFocusChangedEventHandler.
13779 static struct FocusChangedHandler
13781 IUIAutomationFocusChangedEventHandler IUIAutomationFocusChangedEventHandler_iface;
13782 LONG ref;
13784 BOOL event_handler_added;
13785 } FocusChangedHandler;
13787 static inline struct FocusChangedHandler *impl_from_FocusChangedHandler(IUIAutomationFocusChangedEventHandler *iface)
13789 return CONTAINING_RECORD(iface, struct FocusChangedHandler, IUIAutomationFocusChangedEventHandler_iface);
13792 static HRESULT WINAPI FocusChangedHandler_QueryInterface(IUIAutomationFocusChangedEventHandler *iface,
13793 REFIID riid, void **ppv)
13795 *ppv = NULL;
13796 if (IsEqualIID(riid, &IID_IUIAutomationFocusChangedEventHandler) || IsEqualIID(riid, &IID_IUnknown))
13797 *ppv = iface;
13798 else
13799 return E_NOINTERFACE;
13801 IUIAutomationFocusChangedEventHandler_AddRef(iface);
13802 return S_OK;
13805 static ULONG WINAPI FocusChangedHandler_AddRef(IUIAutomationFocusChangedEventHandler* iface)
13807 struct FocusChangedHandler *handler = impl_from_FocusChangedHandler(iface);
13808 return InterlockedIncrement(&handler->ref);
13811 static ULONG WINAPI FocusChangedHandler_Release(IUIAutomationFocusChangedEventHandler* iface)
13813 struct FocusChangedHandler *handler = impl_from_FocusChangedHandler(iface);
13814 return InterlockedDecrement(&handler->ref);
13817 static HRESULT WINAPI FocusChangedHandler_HandleFocusChangedEvent(IUIAutomationFocusChangedEventHandler *iface,
13818 IUIAutomationElement *sender)
13820 struct FocusChangedHandler *handler = impl_from_FocusChangedHandler(iface);
13822 if (handler->event_handler_added)
13823 test_com_event_data(sender);
13825 return S_OK;
13828 static const IUIAutomationFocusChangedEventHandlerVtbl FocusChangedHandlerVtbl = {
13829 FocusChangedHandler_QueryInterface,
13830 FocusChangedHandler_AddRef,
13831 FocusChangedHandler_Release,
13832 FocusChangedHandler_HandleFocusChangedEvent,
13835 static struct FocusChangedHandler FocusChangedHandler =
13837 { &FocusChangedHandlerVtbl },
13841 static DWORD WINAPI uia_com_event_handler_test_thread(LPVOID param)
13843 struct node_provider_desc exp_node_desc;
13844 HRESULT hr;
13847 * Raise an event from inside of an MTA - the event handler proxy will be
13848 * called from the current thread because it was registered in an MTA.
13850 CoInitializeEx(NULL, COINIT_MULTITHREADED);
13852 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
13853 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
13854 set_com_event_data(&exp_node_desc);
13855 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
13856 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13857 CHECK_CALLED(uia_com_event_callback);
13858 ok(ComEventData.last_call_tid == GetCurrentThreadId(), "Event handler called on unexpected thread %ld\n",
13859 ComEventData.last_call_tid);
13860 CoUninitialize();
13863 * Raise an event from inside of an STA - an event handler proxy will be
13864 * created, and our handler will be invoked from another thread.
13866 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
13868 set_com_event_data(&exp_node_desc);
13869 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
13870 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13871 CHECK_CALLED(uia_com_event_callback);
13872 ok(ComEventData.last_call_tid != GetCurrentThreadId(), "Event handler called on unexpected thread %ld\n",
13873 ComEventData.last_call_tid);
13874 CoUninitialize();
13876 return 0;
13879 static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomationElement *elem)
13881 struct Provider_prop_override prop_override;
13882 struct node_provider_desc exp_node_desc;
13883 IUIAutomationElement *elem2;
13884 HANDLE thread;
13885 HRESULT hr;
13886 VARIANT v;
13889 * Invalid input argument tests.
13891 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, NULL, TreeScope_Subtree, NULL,
13892 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13893 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13895 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
13896 NULL);
13897 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13900 * Passing in a NULL element to this method results in an access violation
13901 * on Windows.
13903 if (0)
13905 IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, NULL, &AutomationEventHandler.IUIAutomationEventHandler_iface);
13908 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, elem, NULL);
13909 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13911 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem,
13912 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13913 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13916 * UIA_AutomationFocusChangedEventId can only be listened for with
13917 * AddFocusChangedEventHandler. Trying to register it on a regular event
13918 * handler returns E_INVALIDARG.
13920 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem, TreeScope_Subtree, NULL,
13921 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13922 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13924 /* Windows 11 queries the HWND for the element when adding a new handler. */
13925 set_uia_hwnd_expects(3, 2, 2, 3, 0);
13926 /* All other event IDs are fine, only focus events are blocked. */
13927 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, 1, elem, TreeScope_Subtree, NULL,
13928 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13929 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13930 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
13931 check_uia_hwnd_expects_at_most(3, 2, 2, 3, 0);
13933 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, elem,
13934 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13935 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13936 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
13939 * Test event raising behavior.
13941 set_uia_hwnd_expects(3, 2, 2, 3, 0);
13942 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
13943 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13944 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13945 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
13946 check_uia_hwnd_expects_at_most(3, 2, 2, 3, 0);
13948 /* Same behavior as HUIAEVENTs, events are matched by runtime ID. */
13949 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, NULL, TRUE);
13950 Provider2.runtime_id[0] = 0x2a;
13951 Provider2.runtime_id[1] = HandleToUlong(ComEventData.event_hwnd);
13953 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
13954 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
13955 set_com_event_data(&exp_node_desc);
13956 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
13957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13958 CHECK_CALLED(uia_com_event_callback);
13961 * If no cache request is provided by the user in
13962 * AddAutomationEventHandler, the default cache request is used. If no
13963 * elements match the view condition, the event handler isn't invoked.
13965 variant_init_bool(&v, FALSE);
13966 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
13967 set_provider_prop_override(&Provider2, &prop_override, 1);
13968 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
13969 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13971 set_provider_prop_override(&Provider2, NULL, 0);
13972 thread = CreateThread(NULL, 0, uia_com_event_handler_test_thread, NULL, 0, NULL);
13973 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
13975 MSG msg;
13977 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
13979 TranslateMessage(&msg);
13980 DispatchMessageW(&msg);
13983 CloseHandle(thread);
13985 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
13986 &AutomationEventHandler.IUIAutomationEventHandler_iface);
13987 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13988 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
13990 VariantInit(&v);
13991 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
13992 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_LabeledByPropertyId, TRUE, &v);
13993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13994 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13995 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13997 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&elem2);
13998 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13999 ok(!!elem2, "elem2 == NULL\n");
14000 VariantClear(&v);
14003 * Register an event on an element that has no runtime ID. The only way to
14004 * remove an individual event handler is by matching a combination of
14005 * runtime-id, property ID, and event handler interface pointer. Without a
14006 * runtime-id, the only way to unregister the event handler is to call
14007 * RemoveAllEventHandlers().
14009 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem2, TreeScope_Subtree, NULL,
14010 &AutomationEventHandler.IUIAutomationEventHandler_iface);
14011 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14012 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
14014 /* No removal will occur due to a lack of a runtime ID to match. */
14015 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem2,
14016 &AutomationEventHandler.IUIAutomationEventHandler_iface);
14017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14018 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
14020 hr = IUIAutomation_RemoveAllEventHandlers(uia_iface);
14021 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14022 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
14024 IUIAutomationElement_Release(elem2);
14027 static void test_IUIAutomationFocusChangedEventHandler(IUIAutomation *uia_iface)
14029 struct node_provider_desc exp_node_desc;
14030 IUIAutomationElement *elem;
14031 HRESULT hr;
14033 SetFocus(ComEventData.event_hwnd);
14036 * FocusChangedEventHandlers are always registered on the desktop node
14037 * with a scope of the entire desktop.
14039 * All versions of Windows query the currently focused HWND when adding a
14040 * new focus changed event handler, but behavior differs between versions:
14042 * Win7-Win10v1507 queries for the focused provider and raises an event
14043 * while also advising of events.
14045 * Win10v1809+ will query the focused HWND, but doesn't advise of events
14046 * or raise a focus event. Windows 11 will advise the provider of the
14047 * focused HWND of events, but not any clientside providers.
14049 set_uia_hwnd_expects(6, 6, 6, 3, 0);
14050 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
14051 &FocusChangedHandler.IUIAutomationFocusChangedEventHandler_iface);
14052 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14053 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
14054 check_uia_hwnd_expects_at_most(6, 6, 6, 3, 0);
14055 FocusChangedHandler.event_handler_added = TRUE;
14058 * Focus changed event handlers are registered on the desktop with a scope
14059 * of all elements, so all elements match regardless of runtime ID.
14061 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, NULL, TRUE);
14062 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
14063 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
14064 set_com_event_data(&exp_node_desc);
14065 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
14066 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14067 CHECK_CALLED(uia_com_event_callback);
14070 * Removing the focus changed event handler creates a desktop node -
14071 * presumably to use to get a runtime ID for removal.
14073 set_uia_hwnd_expects(1, 1, 1, 0, 0);
14074 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
14075 &FocusChangedHandler.IUIAutomationFocusChangedEventHandler_iface);
14076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14077 ok(FocusChangedHandler.ref == 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
14078 FocusChangedHandler.event_handler_added = FALSE;
14079 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
14082 * The focus changed event handler can also be removed by called
14083 * RemoveAutomationEventHandler, which isn't documented.
14085 set_uia_hwnd_expects(6, 6, 6, 3, 0);
14086 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
14087 &FocusChangedHandler.IUIAutomationFocusChangedEventHandler_iface);
14088 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14089 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
14090 check_uia_hwnd_expects_at_most(6, 6, 6, 3, 0);
14091 FocusChangedHandler.event_handler_added = TRUE;
14093 set_uia_hwnd_expects(1, 1, 1, 0, 0);
14094 hr = IUIAutomation_GetRootElement(uia_iface, &elem);
14095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14096 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
14098 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem,
14099 (IUIAutomationEventHandler *)&FocusChangedHandler.IUIAutomationFocusChangedEventHandler_iface);
14100 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14101 ok(FocusChangedHandler.ref == 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
14103 IUIAutomationElement_Release(elem);
14106 static void test_CUIAutomation_event_handlers(IUIAutomation *uia_iface)
14108 IUIAutomationElement *elem;
14109 HRESULT hr;
14110 HWND hwnd;
14112 ComEventData.event_hwnd = hwnd = create_test_hwnd("test_CUIAutomation_event_handlers class");
14114 /* Set up providers for the desktop window and our test HWND. */
14115 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
14116 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14117 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14118 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14120 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
14121 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
14122 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
14123 Provider.ignore_hwnd_prop = TRUE;
14124 prov_root = &Provider.IRawElementProviderSimple_iface;
14126 method_sequences_enabled = FALSE;
14127 set_uia_hwnd_expects(1, 1, 1, 1, 1);
14128 UiaRegisterProviderCallback(test_uia_provider_callback);
14129 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &elem);
14130 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14131 ok(!!elem, "elem == NULL\n");
14132 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14133 ok(Provider_hwnd2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd2.ref);
14134 ok(Provider_nc2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc2.ref);
14135 check_uia_hwnd_expects(1, TRUE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
14137 test_IUIAutomationEventHandler(uia_iface, elem);
14138 test_IUIAutomationFocusChangedEventHandler(uia_iface);
14140 IUIAutomationElement_Release(elem);
14141 UiaRegisterProviderCallback(NULL);
14142 DestroyWindow(hwnd);
14143 UnregisterClassA("test_CUIAutomation_event_handlers class", NULL);
14144 method_sequences_enabled = TRUE;
14147 struct uia_com_classes {
14148 const GUID *clsid;
14149 const GUID *iid;
14152 static const struct uia_com_classes com_classes[] = {
14153 { &CLSID_CUIAutomation, &IID_IUnknown },
14154 { &CLSID_CUIAutomation, &IID_IUIAutomation },
14155 { &CLSID_CUIAutomation8, &IID_IUnknown },
14156 { &CLSID_CUIAutomation8, &IID_IUIAutomation },
14157 { &CLSID_CUIAutomation8, &IID_IUIAutomation2 },
14158 { &CLSID_CUIAutomation8, &IID_IUIAutomation3 },
14159 { &CLSID_CUIAutomation8, &IID_IUIAutomation4 },
14160 { &CLSID_CUIAutomation8, &IID_IUIAutomation5 },
14161 { &CLSID_CUIAutomation8, &IID_IUIAutomation6 },
14164 static void test_CUIAutomation(void)
14166 BOOL has_cui8 = TRUE, tmp_b;
14167 IUIAutomation *uia_iface;
14168 IUnknown *unk1, *unk2;
14169 HRESULT hr;
14170 VARIANT v;
14171 int i;
14173 CoInitializeEx(NULL, COINIT_MULTITHREADED);
14175 for (i = 0; i < ARRAY_SIZE(com_classes); i++)
14177 IUnknown *iface = NULL;
14179 hr = CoCreateInstance(com_classes[i].clsid, NULL, CLSCTX_INPROC_SERVER, com_classes[i].iid,
14180 (void **)&iface);
14182 if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG))
14184 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
14185 has_cui8 = FALSE;
14186 break;
14188 else if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == E_NOINTERFACE) &&
14189 (com_classes[i].iid != &IID_IUIAutomation2) && (com_classes[i].iid != &IID_IUIAutomation) &&
14190 (com_classes[i].iid != &IID_IUnknown))
14192 win_skip("No object for clsid %s, iid %s, skipping further tests.\n", debugstr_guid(com_classes[i].clsid),
14193 debugstr_guid(com_classes[i].iid));
14194 break;
14197 ok(hr == S_OK, "Failed to create interface for clsid %s, iid %s, hr %#lx\n",
14198 debugstr_guid(com_classes[i].clsid), debugstr_guid(com_classes[i].iid), hr);
14199 ok(!!iface, "iface == NULL\n");
14200 IUnknown_Release(iface);
14203 if (has_cui8)
14204 hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
14205 (void **)&uia_iface);
14206 else
14207 hr = CoCreateInstance(&CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
14208 (void **)&uia_iface);
14209 ok(hr == S_OK, "Failed to create IUIAutomation interface, hr %#lx\n", hr);
14210 ok(!!uia_iface, "uia_iface == NULL\n");
14212 /* Reserved value retrieval methods. */
14213 hr = UiaGetReservedNotSupportedValue(&unk1);
14214 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14216 hr = IUIAutomation_get_ReservedNotSupportedValue(uia_iface, &unk2);
14217 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14218 ok(unk1 == unk2, "unk1 != unk2\n");
14220 V_VT(&v) = VT_UNKNOWN;
14221 V_UNKNOWN(&v) = unk1;
14222 hr = IUIAutomation_CheckNotSupported(uia_iface, v, &tmp_b);
14223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14224 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
14226 IUnknown_Release(unk1);
14227 IUnknown_Release(unk2);
14229 hr = UiaGetReservedMixedAttributeValue(&unk1);
14230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14232 hr = IUIAutomation_get_ReservedMixedAttributeValue(uia_iface, &unk2);
14233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14234 ok(unk1 == unk2, "unk1 != unk2\n");
14236 V_VT(&v) = VT_UNKNOWN;
14237 V_UNKNOWN(&v) = unk1;
14238 hr = IUIAutomation_CheckNotSupported(uia_iface, v, &tmp_b);
14239 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14240 ok(tmp_b == FALSE, "tmp_b != FALSE\n");
14242 IUnknown_Release(unk1);
14243 IUnknown_Release(unk2);
14245 test_CUIAutomation_condition_ifaces(uia_iface);
14246 test_CUIAutomation_value_conversion(uia_iface);
14247 test_CUIAutomation_cache_request_iface(uia_iface);
14248 test_CUIAutomation_TreeWalker_ifaces(uia_iface);
14249 test_ElementFromHandle(uia_iface, has_cui8);
14250 test_Element_GetPropertyValue(uia_iface);
14251 test_Element_cache_methods(uia_iface);
14252 test_Element_Find(uia_iface);
14253 test_GetRootElement(uia_iface);
14254 test_GetFocusedElement(uia_iface);
14255 test_CUIAutomation_event_handlers(uia_iface);
14257 IUIAutomation_Release(uia_iface);
14258 CoUninitialize();
14261 static const struct prov_method_sequence default_hwnd_prov_props_seq[] = {
14262 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
14263 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
14264 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
14265 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
14266 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NamePropertyId */
14267 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
14268 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_NamePropertyId */
14269 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
14270 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ClassNamePropertyId */
14271 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
14272 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ClassNamePropertyId */
14273 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
14274 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProcessIdPropertyId */
14275 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
14276 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProcessIdPropertyId */
14277 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_TODO },
14278 { 0 }
14281 #define test_node_hwnd_provider( node, hwnd ) \
14282 test_node_hwnd_provider_( (node), (hwnd), __FILE__, __LINE__)
14283 static void test_node_hwnd_provider_(HUIANODE node, HWND hwnd, const char *file, int line)
14285 WCHAR buf[1024] = { 0 };
14286 HRESULT hr;
14287 VARIANT v;
14288 DWORD pid;
14290 winetest_push_context("UIA_NativeWindowHandlePropertyId");
14291 hr = UiaGetPropertyValue(node, UIA_NativeWindowHandlePropertyId, &v);
14292 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14293 ok_(file, line)(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
14294 ok_(file, line)(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
14295 VariantClear(&v);
14296 winetest_pop_context();
14298 winetest_push_context("UIA_NamePropertyId");
14299 SendMessageW(hwnd, WM_GETTEXT, ARRAY_SIZE(buf), (LPARAM)buf);
14300 hr = UiaGetPropertyValue(node, UIA_NamePropertyId, &v);
14301 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14302 ok_(file, line)(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
14303 ok(!lstrcmpW(V_BSTR(&v), buf), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
14304 VariantClear(&v);
14305 winetest_pop_context();
14307 winetest_push_context("UIA_ClassNamePropertyId");
14308 memset(buf, 0, sizeof(buf));
14309 GetClassNameW(hwnd, buf, ARRAY_SIZE(buf));
14310 hr = UiaGetPropertyValue(node, UIA_ClassNamePropertyId, &v);
14311 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14312 ok_(file, line)(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
14313 ok(!lstrcmpW(V_BSTR(&v), buf), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
14314 VariantClear(&v);
14315 winetest_pop_context();
14317 GetWindowThreadProcessId(hwnd, &pid);
14318 winetest_push_context("UIA_ProcessIdPropertyId");
14319 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
14320 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14321 ok_(file, line)(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
14322 ok_(file, line)(V_I4(&v) == pid, "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), pid);
14323 VariantClear(&v);
14324 winetest_pop_context();
14327 enum {
14328 PARENT_HWND_NULL,
14329 PARENT_HWND_HWND,
14330 PARENT_HWND_DESKTOP,
14333 struct uia_hwnd_control_type_test {
14334 DWORD style;
14335 DWORD style_ex;
14336 int exp_control_type;
14337 int parent_hwnd_type;
14340 static const struct uia_hwnd_control_type_test hwnd_control_type_test[] = {
14341 { WS_OVERLAPPEDWINDOW, 0, UIA_WindowControlTypeId, PARENT_HWND_NULL },
14342 /* Top-level window (parent is desktop window) is always a window control. */
14343 { WS_CHILD, 0, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
14344 /* Not a top-level window, considered a pane. */
14345 { WS_CHILD, 0, UIA_PaneControlTypeId, PARENT_HWND_HWND },
14346 /* Not a top-level window, but WS_EX_APPWINDOW is always considered a window. */
14347 { WS_CHILD, WS_EX_APPWINDOW, UIA_WindowControlTypeId, PARENT_HWND_HWND },
14349 * WS_POPUP is always a pane regardless of being a top level window,
14350 * unless WS_CAPTION is set.
14352 { WS_CAPTION | WS_POPUP, 0, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
14353 { WS_BORDER | WS_POPUP, 0, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
14354 { WS_POPUP, 0, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
14356 * Top level window with WS_EX_TOOLWINDOW and without WS_CAPTION is
14357 * considered a pane.
14359 { WS_CHILD, WS_EX_TOOLWINDOW, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
14360 { WS_CHILD | WS_CAPTION, WS_EX_TOOLWINDOW, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
14363 static void create_base_hwnd_test_node(HWND hwnd, BOOL child_hwnd, struct Provider *main, struct Provider *nc,
14364 HUIANODE *ret_node)
14366 ULONG main_ref, nc_ref;
14367 HRESULT hr;
14369 initialize_provider(nc, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider, hwnd, TRUE);
14370 initialize_provider(main, ProviderOptions_ClientSideProvider, hwnd, TRUE);
14371 nc->ignore_hwnd_prop = main->ignore_hwnd_prop = TRUE;
14372 main_ref = main->ref;
14373 nc_ref = nc->ref;
14375 if (!child_hwnd)
14377 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14378 SET_EXPECT(winproc_GETOBJECT_CLIENT);
14379 prov_root = &main->IRawElementProviderSimple_iface;
14381 else
14383 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14384 SET_EXPECT(winproc_GETOBJECT_CLIENT);
14385 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
14386 child_win_prov_root = &main->IRawElementProviderSimple_iface;
14389 hr = UiaNodeFromProvider(&nc->IRawElementProviderSimple_iface, ret_node);
14390 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14391 ok(main->ref == (main_ref + 1), "Unexpected refcnt %ld\n", main->ref);
14392 ok(nc->ref == (nc_ref + 1), "Unexpected refcnt %ld\n", nc->ref);
14393 if (child_hwnd)
14395 /* Called while trying to get override provider. */
14396 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14397 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
14399 else
14400 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14401 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
14402 Provider.ret_invalid_prop_type = Provider_nc.ret_invalid_prop_type = TRUE;
14405 #define test_node_hwnd_provider_navigation( node, dir, exp_dest_hwnd ) \
14406 test_node_hwnd_provider_navigation_( (node), (dir), (exp_dest_hwnd), __FILE__, __LINE__)
14407 static void test_node_hwnd_provider_navigation_(HUIANODE node, int nav_dir, HWND exp_dest_hwnd, const char *file,
14408 int line)
14410 struct UiaCacheRequest cache_req = { NULL, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full };
14411 const WCHAR *exp_tree_struct = exp_dest_hwnd ? L"P)" : L"";
14412 SAFEARRAY *out_req = NULL;
14413 BSTR tree_struct = NULL;
14414 LONG idx[2] = { 0 };
14415 HUIANODE tmp_node;
14416 HRESULT hr;
14417 VARIANT v;
14418 int i;
14420 hr = UiaNavigate(node, nav_dir, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
14421 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14422 ok_(file, line)(!!out_req, "out_req == NULL\n");
14423 ok_(file, line)(!!tree_struct, "tree_struct == NULL\n");
14424 if (!exp_dest_hwnd)
14425 goto exit;
14427 for (i = 0; i < 2; i++)
14429 hr = SafeArrayGetLBound(out_req, 1 + i, &idx[i]);
14430 ok_(file, line)(hr == S_OK, "SafeArrayGetLBound unexpected hr %#lx\n", hr);
14433 hr = SafeArrayGetElement(out_req, idx, &v);
14434 ok_(file, line)(hr == S_OK, "SafeArrayGetElement unexpected hr %#lx\n", hr);
14436 hr = UiaHUiaNodeFromVariant(&v, &tmp_node);
14437 ok_(file, line)(hr == S_OK, "UiaHUiaNodeFromVariant unexpected hr %#lx\n", hr);
14438 ok_(file, line)(!!tmp_node, "tmp_node == NULL\n");
14439 VariantClear(&v);
14441 hr = UiaGetPropertyValue(tmp_node, UIA_NativeWindowHandlePropertyId, &v);
14442 ok_(file, line)(hr == S_OK, "UiaGetPropertyValue unexpected hr %#lx\n", hr);
14443 ok_(file, line)(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
14444 ok_(file, line)(V_I4(&v) == HandleToUlong(exp_dest_hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v),
14445 HandleToUlong(exp_dest_hwnd));
14446 VariantClear(&v);
14447 UiaNodeRelease(tmp_node);
14449 exit:
14450 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct), "unexpected tree structure %s\n", debugstr_w(tree_struct));
14451 SafeArrayDestroy(out_req);
14452 SysFreeString(tree_struct);
14455 static void test_default_clientside_providers(void)
14457 struct UiaRect uia_rect = { 0 };
14458 HWND hwnd, hwnd_child, hwnd2;
14459 RECT rect = { 0 };
14460 IUnknown *unk_ns;
14461 HUIANODE node;
14462 HRESULT hr;
14463 VARIANT v;
14464 int i;
14466 CoInitializeEx(NULL, COINIT_MULTITHREADED);
14467 hwnd = create_test_hwnd("test_default_clientside_providers class");
14468 hwnd_child = create_child_test_hwnd("test_default_clientside_providers child class", hwnd);
14469 method_sequences_enabled = FALSE;
14471 hr = UiaGetReservedNotSupportedValue(&unk_ns);
14472 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14475 * Test default BaseHwnd provider. Unlike the other default providers, the
14476 * default BaseHwnd IRawElementProviderSimple is not available to test
14477 * directly. To isolate the BaseHwnd provider, we set the node's nonclient
14478 * provider to Provider_nc, and its Main provider to Provider. These
14479 * providers will return nothing so that we can isolate properties coming
14480 * from the BaseHwnd provider.
14482 create_base_hwnd_test_node(hwnd, FALSE, &Provider, &Provider_nc, &node);
14484 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
14485 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14486 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
14487 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
14488 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
14489 check_node_provider_desc_todo(V_BSTR(&v), L"Hwnd", NULL, TRUE);
14490 VariantClear(&v);
14492 method_sequences_enabled = TRUE;
14493 Provider.ret_invalid_prop_type = Provider_nc.ret_invalid_prop_type = TRUE;
14494 test_node_hwnd_provider(node, hwnd);
14495 ok_method_sequence(default_hwnd_prov_props_seq, "default_hwnd_prov_props_seq");
14496 method_sequences_enabled = FALSE;
14498 /* Get the bounding rectangle from the default BaseHwnd provider. */
14499 GetWindowRect(hwnd, &rect);
14500 set_uia_rect(&uia_rect, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
14501 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
14502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14503 check_uia_rect_val(&v, &uia_rect);
14504 VariantClear(&v);
14506 /* Minimized top-level HWNDs don't return a bounding rectangle. */
14507 ShowWindow(hwnd, SW_MINIMIZE);
14508 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
14509 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14510 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
14511 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
14512 VariantClear(&v);
14514 UiaNodeRelease(node);
14515 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14516 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
14518 /* Create a child window node. */
14519 create_base_hwnd_test_node(hwnd_child, TRUE, &Provider, &Provider_nc, &node);
14520 test_node_hwnd_provider(node, hwnd_child);
14522 /* Get the bounding rectangle from the default BaseHwnd provider. */
14523 GetWindowRect(hwnd_child, &rect);
14524 set_uia_rect(&uia_rect, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
14525 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
14526 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14527 check_uia_rect_val(&v, &uia_rect);
14528 VariantClear(&v);
14530 /* Minimized non top-level HWNDs return a bounding rectangle. */
14531 ShowWindow(hwnd_child, SW_MINIMIZE);
14532 GetWindowRect(hwnd_child, &rect);
14533 set_uia_rect(&uia_rect, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
14534 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
14535 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14536 check_uia_rect_val(&v, &uia_rect);
14537 VariantClear(&v);
14539 UiaNodeRelease(node);
14540 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14541 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
14543 VariantInit(&v);
14544 for (i = 0; i < ARRAY_SIZE(hwnd_control_type_test); i++)
14546 const struct uia_hwnd_control_type_test *test = &hwnd_control_type_test[i];
14547 HWND parent;
14549 if (test->parent_hwnd_type == PARENT_HWND_HWND)
14550 parent = hwnd;
14551 else if (test->parent_hwnd_type == PARENT_HWND_DESKTOP)
14552 parent = GetDesktopWindow();
14553 else
14554 parent = NULL;
14556 hwnd2 = CreateWindowExA(test->style_ex, "test_default_clientside_providers class", "Test window", test->style,
14557 0, 0, 100, 100, parent, NULL, NULL, NULL);
14558 initialize_provider(&Provider_nc, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider, hwnd2, TRUE);
14559 initialize_provider(&Provider, ProviderOptions_ClientSideProvider, hwnd2, TRUE);
14560 Provider_nc.ignore_hwnd_prop = Provider.ignore_hwnd_prop = TRUE;
14561 Provider.ret_invalid_prop_type = Provider_nc.ret_invalid_prop_type = TRUE;
14563 /* If parent is hwnd, it will be queried for an override provider. */
14564 if (test->style == WS_CHILD && (parent == hwnd))
14565 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
14566 else
14567 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14568 /* Only sent on Win7. */
14569 SET_EXPECT(winproc_GETOBJECT_CLIENT);
14570 hr = UiaNodeFromProvider(&Provider_nc.IRawElementProviderSimple_iface, &node);
14571 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14572 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14573 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
14574 if (hwnd_control_type_test[i].style == WS_CHILD && (parent == hwnd))
14575 todo_wine CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, 2);
14576 else
14577 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14578 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
14580 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
14581 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14582 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
14583 ok(V_I4(&v) == test->exp_control_type, "Unexpected control type %ld\n", V_I4(&v));
14584 VariantClear(&v);
14586 UiaNodeRelease(node);
14587 DestroyWindow(hwnd2);
14591 * Default ProviderType_BaseHwnd provider navigation tests.
14593 create_base_hwnd_test_node(hwnd, FALSE, &Provider, &Provider_nc, &node);
14594 test_node_hwnd_provider(node, hwnd);
14597 * Navigate to the parent of our top-level HWND, will get a node
14598 * representing the desktop HWND.
14600 test_node_hwnd_provider_navigation(node, NavigateDirection_Parent, GetDesktopWindow());
14601 UiaNodeRelease(node);
14604 * Create a node representing an HWND that is a top-level window, but is
14605 * owned by another window. For top-level HWNDs, parent navigation will go
14606 * to the owner instead of the parent.
14608 hwnd2 = CreateWindowA("test_default_clientside_providers class", "Test window", WS_POPUP, 0, 0, 50, 50, hwnd, NULL,
14609 NULL, NULL);
14610 ok(GetAncestor(hwnd2, GA_PARENT) == GetDesktopWindow(), "unexpected parent hwnd");
14611 ok(GetWindow(hwnd2, GW_OWNER) == hwnd, "unexpected owner hwnd");
14612 create_base_hwnd_test_node(hwnd2, FALSE, &Provider, &Provider_nc, &node);
14613 test_node_hwnd_provider(node, hwnd2);
14615 /* Navigate to the parent. */
14616 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14617 /* Only sent on Win7. */
14618 SET_EXPECT(winproc_GETOBJECT_CLIENT);
14619 test_node_hwnd_provider_navigation(node, NavigateDirection_Parent, hwnd);
14620 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14621 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
14623 UiaNodeRelease(node);
14624 DestroyWindow(hwnd2);
14627 * Create a node for our child window.
14629 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, hwnd, TRUE);
14630 Provider2.ignore_hwnd_prop = TRUE;
14631 prov_root = &Provider2.IRawElementProviderSimple_iface;
14632 create_base_hwnd_test_node(hwnd_child, TRUE, &Provider, &Provider_nc, &node);
14633 test_node_hwnd_provider(node, hwnd_child);
14635 /* Navigate to parent. */
14636 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14637 /* Only sent on Win7. */
14638 SET_EXPECT(winproc_GETOBJECT_CLIENT);
14639 test_node_hwnd_provider_navigation(node, NavigateDirection_Parent, hwnd);
14640 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14641 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
14643 UiaNodeRelease(node);
14644 prov_root = NULL;
14647 * Test default ProviderType_Proxy clientside provider. Provider will be
14648 * the HWND provider for this node, and Accessible will be the main
14649 * provider.
14651 initialize_provider(&Provider, ProviderOptions_ClientSideProvider, hwnd, FALSE);
14652 set_accessible_props(&Accessible, ROLE_SYSTEM_TEXT, STATE_SYSTEM_FOCUSABLE, 0, L"Accessible", 0, 0, 20, 20);
14653 set_accessible_ia2_props(&Accessible, FALSE, 0);
14654 acc_client = &Accessible.IAccessible_iface;
14655 prov_root = child_win_prov_root = NULL;
14657 SET_ACC_METHOD_EXPECT(&Accessible, QI_IAccIdentity);
14658 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent);
14659 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14660 /* Only sent twice on Win7. */
14661 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
14662 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
14663 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14664 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14665 ok(Accessible.ref >= 2, "Unexpected refcnt %ld\n", Accessible.ref);
14666 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, QI_IAccIdentity);
14667 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, get_accParent);
14668 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14669 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
14671 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
14672 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14673 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd);
14674 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
14675 check_node_provider_desc_todo(V_BSTR(&v), L"Nonclient", NULL, FALSE);
14676 check_node_provider_desc(V_BSTR(&v), L"Main", NULL, TRUE);
14677 VariantClear(&v);
14679 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
14680 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
14681 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14682 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
14683 ok(V_I4(&v) == UIA_EditControlTypeId, "Unexpected I4 %#lx\n", V_I4(&v));
14684 VariantClear(&v);
14685 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
14687 UiaNodeRelease(node);
14688 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14689 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
14692 * Unlike UiaProviderFromIAccessible which won't create a provider for an
14693 * MSAA proxy, the default clientside proxy provider will.
14695 hwnd2 = CreateWindowA("EDIT", "", WS_VISIBLE | WS_CHILD | ES_PASSWORD,
14696 0, 0, 100, 100, hwnd, NULL, NULL, NULL);
14697 initialize_provider(&Provider, ProviderOptions_ClientSideProvider, hwnd2, FALSE);
14699 /* Tries to get override provider from parent HWND. */
14700 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
14701 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
14702 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14703 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14704 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
14706 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
14707 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14708 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), hwnd2);
14709 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
14710 check_node_provider_desc_todo(V_BSTR(&v), L"Main", NULL, FALSE);
14711 check_node_provider_desc_todo(V_BSTR(&v), L"Annotation", NULL, TRUE);
14712 VariantClear(&v);
14714 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
14715 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14716 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
14717 ok(V_I4(&v) == UIA_EditControlTypeId, "Unexpected I4 %#lx\n", V_I4(&v));
14718 VariantClear(&v);
14720 hr = UiaGetPropertyValue(node, UIA_IsPasswordPropertyId, &v);
14721 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14722 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
14723 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
14724 VariantClear(&v);
14726 UiaNodeRelease(node);
14727 DestroyWindow(hwnd2);
14729 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
14730 acc_client = NULL;
14731 prov_root = child_win_prov_root = NULL;
14733 method_sequences_enabled = TRUE;
14734 DestroyWindow(hwnd);
14735 DestroyWindow(hwnd_child);
14736 UnregisterClassA("test_default_clientside_providers class", NULL);
14737 UnregisterClassA("test_default_clientside_providers child class", NULL);
14739 IUnknown_Release(unk_ns);
14740 CoUninitialize();
14743 static void test_UiaGetRootNode(void)
14745 HUIANODE node;
14746 HRESULT hr;
14747 VARIANT v;
14749 CoInitializeEx(NULL, COINIT_MULTITHREADED);
14750 UiaRegisterProviderCallback(test_uia_provider_callback);
14753 * UiaGetRootNode is the same as calling UiaNodeFromHandle with the
14754 * desktop window handle.
14756 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
14757 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14758 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14759 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14761 method_sequences_enabled = FALSE;
14762 SET_EXPECT(prov_callback_base_hwnd);
14763 SET_EXPECT(prov_callback_nonclient);
14764 SET_EXPECT(prov_callback_proxy);
14765 hr = UiaGetRootNode(&node);
14766 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14767 ok(!!node, "Node == NULL.\n");
14768 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
14769 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
14770 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
14771 CHECK_CALLED(prov_callback_base_hwnd);
14772 CHECK_CALLED(prov_callback_nonclient);
14773 CHECK_CALLED(prov_callback_proxy);
14775 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
14776 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14777 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), GetDesktopWindow());
14778 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
14779 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
14780 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
14781 VariantClear(&v);
14783 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
14784 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
14785 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
14786 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
14788 initialize_provider(&Provider_hwnd, ProviderOptions_ClientSideProvider, NULL, TRUE);
14789 initialize_provider(&Provider_nc, ProviderOptions_ClientSideProvider | ProviderOptions_NonClientAreaProvider, NULL,
14790 TRUE);
14791 initialize_provider(&Provider_proxy, ProviderOptions_ClientSideProvider, NULL, TRUE);
14792 base_hwnd_prov = proxy_prov = nc_prov = NULL;
14794 method_sequences_enabled = TRUE;
14795 UiaRegisterProviderCallback(NULL);
14796 CoUninitialize();
14799 #define test_node_from_focus( cache_req, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, nc_cback_count, \
14800 win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, base_hwnd_cback_todo, \
14801 nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo) \
14802 test_node_from_focus_( (cache_req), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), (nc_cback_count), \
14803 (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), (base_hwnd_cback_todo), \
14804 (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
14805 static void test_node_from_focus_(struct UiaCacheRequest *cache_req, struct node_provider_desc *exp_node_desc,
14806 int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count, int win_get_obj_count,
14807 int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo, BOOL nc_cback_todo,
14808 BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
14810 const WCHAR *exp_tree_struct = exp_node_desc->prov_count ? L"P)" : L"";
14811 LONG exp_lbound[2], exp_elems[2];
14812 SAFEARRAY *out_req = NULL;
14813 BSTR tree_struct = NULL;
14814 HRESULT hr;
14816 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14817 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
14818 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
14819 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
14820 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
14821 hr = UiaNodeFromFocus(cache_req, &out_req, &tree_struct);
14822 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14823 if (exp_node_desc->prov_count)
14824 ok_(file, line)(!!out_req, "out_req == NULL\n");
14825 else
14826 ok_(file, line)(!out_req, "out_req != NULL\n");
14827 ok_(file, line)(!!tree_struct, "tree_struct == NULL\n");
14828 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14829 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
14830 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
14831 todo_wine_if(win_get_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
14832 todo_wine_if(child_win_get_obj_todo) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
14834 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct), "unexpected tree structure %s\n", debugstr_w(tree_struct));
14835 if (exp_node_desc->prov_count)
14837 exp_lbound[0] = exp_lbound[1] = 0;
14838 exp_elems[0] = 1;
14839 exp_elems[1] = 1 + cache_req->cProperties;
14840 test_cache_req_sa_(out_req, exp_lbound, exp_elems, exp_node_desc, file, line);
14843 SafeArrayDestroy(out_req);
14844 SysFreeString(tree_struct);
14847 static void test_UiaNodeFromFocus(void)
14849 struct Provider_prop_override prop_override;
14850 struct node_provider_desc exp_node_desc;
14851 struct UiaPropertyCondition prop_cond;
14852 struct UiaCacheRequest cache_req;
14853 struct UiaNotCondition not_cond;
14854 HWND hwnd, hwnd_child;
14855 int cache_prop;
14856 VARIANT v;
14858 CoInitializeEx(NULL, COINIT_MULTITHREADED);
14860 hwnd = create_test_hwnd("UiaNodeFromFocus class");
14861 hwnd_child = create_child_test_hwnd("UiaNodeFromFocus child class", hwnd);
14863 UiaRegisterProviderCallback(test_uia_provider_callback);
14865 /* Set clientside providers for our test windows and the desktop. */
14866 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
14867 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14868 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14869 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14871 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
14872 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
14873 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
14874 prov_root = &Provider.IRawElementProviderSimple_iface;
14875 Provider.ignore_hwnd_prop = TRUE;
14877 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, hwnd_child);
14878 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, hwnd_child, TRUE);
14879 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
14880 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
14881 Provider2.ignore_hwnd_prop = TRUE;
14884 * Nodes are normalized against the cache request view condition. Here,
14885 * we're setting it to the same as the default ControlView.
14887 variant_init_bool(&v, FALSE);
14888 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
14889 set_not_condition(&not_cond, (struct UiaCondition *)&prop_cond);
14890 cache_prop = UIA_RuntimeIdPropertyId;
14891 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, &cache_prop, 1, NULL, 0,
14892 AutomationElementMode_Full);
14895 * None of the providers for the desktop node return a provider from
14896 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
14897 * desktop node.
14899 method_sequences_enabled = FALSE;
14900 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), GetDesktopWindow());
14901 add_provider_desc(&exp_node_desc, L"Main", L"Provider_proxy", TRUE);
14902 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc", FALSE);
14903 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd", FALSE);
14905 test_node_from_focus(&cache_req, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14907 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
14908 Provider_hwnd.focus_prov = &Provider_hwnd2.IRawElementProviderFragment_iface;
14910 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
14911 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
14912 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
14913 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
14915 test_node_from_focus(&cache_req, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14918 * Provider_proxy returns Provider from GetFocus. The provider that
14919 * creates the node will not have GetFocus called on it to avoid returning
14920 * the same provider twice. Similarly, on nodes other than the desktop
14921 * node, the HWND provider will not have GetFocus called on it.
14923 Provider_hwnd.focus_prov = NULL;
14924 Provider_proxy.focus_prov = &Provider.IRawElementProviderFragment_iface;
14925 Provider.focus_prov = Provider_hwnd2.focus_prov = &Provider2.IRawElementProviderFragment_iface;
14927 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
14928 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
14929 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
14930 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
14932 test_node_from_focus(&cache_req, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14935 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
14936 * Provider2, Provider_nc3 returns Provider_child.
14938 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
14939 Provider_proxy.focus_prov = Provider_hwnd.focus_prov = Provider_hwnd2.focus_prov = NULL;
14940 Provider_nc.focus_prov = &Provider_nc2.IRawElementProviderFragment_iface;
14941 Provider.focus_prov = &Provider2.IRawElementProviderFragment_iface;
14942 Provider_nc3.focus_prov = &Provider_child.IRawElementProviderFragment_iface;
14944 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
14945 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
14947 test_node_from_focus(&cache_req, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
14950 * Provider_proxy returns Provider_child_child from GetFocus. The focus
14951 * provider is normalized against the cache request view condition.
14952 * Provider_child_child and its ancestors don't match the cache request
14953 * view condition, so we'll get no provider.
14955 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
14956 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
14957 provider_add_child(&Provider, &Provider_child);
14958 provider_add_child(&Provider_child, &Provider_child_child);
14959 Provider_proxy.focus_prov = &Provider_child_child.IRawElementProviderFragment_iface;
14960 Provider_nc.focus_prov = Provider_hwnd.focus_prov = NULL;
14962 variant_init_bool(&v, FALSE);
14963 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14964 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14965 set_provider_prop_override(&Provider_child, &prop_override, 1);
14966 set_provider_prop_override(&Provider, &prop_override, 1);
14968 init_node_provider_desc(&exp_node_desc, 0, NULL);
14969 test_node_from_focus(&cache_req, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14971 /* This time, Provider_child matches our view condition. */
14972 set_provider_prop_override(&Provider_child, NULL, 0);
14974 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
14975 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
14977 test_node_from_focus(&cache_req, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14979 method_sequences_enabled = TRUE;
14980 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, TRUE);
14981 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
14982 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
14984 CoUninitialize();
14985 UiaRegisterProviderCallback(NULL);
14986 DestroyWindow(hwnd);
14987 UnregisterClassA("UiaNodeFromFocus class", NULL);
14988 UnregisterClassA("UiaNodeFromFocus child class", NULL);
14991 static const struct prov_method_sequence event_seq1[] = {
14992 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win8+. */
14993 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Only called on Arabic version of Win10+. */
14994 { 0 },
14997 static const struct prov_method_sequence event_seq2[] = {
14998 { &Provider, FRAG_GET_RUNTIME_ID },
14999 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
15000 { &Provider, FRAG_GET_FRAGMENT_ROOT },
15001 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Called twice on Win11. */
15002 NODE_CREATE_SEQ_OPTIONAL(&Provider), /* Only done in Win11. */
15003 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win8+. */
15004 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
15005 { &Provider, ADVISE_EVENTS_EVENT_ADDED },
15006 { 0 },
15009 static const struct prov_method_sequence event_seq3[] = {
15010 { &Provider, PROV_GET_PROVIDER_OPTIONS },
15011 /* The following four methods are only called on Arabic versions of Win10+. */
15012 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
15013 { &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
15014 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
15015 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
15016 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win8+. */
15017 NODE_CREATE_SEQ3(&Provider),
15018 { &Provider, FRAG_GET_RUNTIME_ID },
15019 { 0 },
15022 static const struct prov_method_sequence event_seq4[] = {
15023 { &Provider, ADVISE_EVENTS_EVENT_REMOVED },
15024 { 0 },
15027 static const struct prov_method_sequence event_seq5[] = {
15028 { &Provider, FRAG_GET_RUNTIME_ID },
15029 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
15030 { &Provider, FRAG_GET_FRAGMENT_ROOT },
15031 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Called twice on Win11. */
15032 { &Provider, FRAG_GET_EMBEDDED_FRAGMENT_ROOTS },
15033 NODE_CREATE_SEQ_OPTIONAL(&Provider), /* Only done in Win11. */
15034 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win8+. */
15035 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
15036 { &Provider, ADVISE_EVENTS_EVENT_ADDED },
15037 { 0 },
15040 static const struct prov_method_sequence event_seq6[] = {
15041 { &Provider, ADVISE_EVENTS_EVENT_REMOVED },
15042 { &Provider_child, ADVISE_EVENTS_EVENT_REMOVED },
15043 { &Provider_child2, ADVISE_EVENTS_EVENT_REMOVED },
15044 { 0 },
15047 static struct EventData {
15048 LONG exp_lbound[2];
15049 LONG exp_elems[2];
15050 struct node_provider_desc exp_node_desc;
15051 const WCHAR *exp_tree_struct;
15053 struct node_provider_desc exp_nested_node_desc;
15054 HANDLE event_handle;
15055 } EventData;
15057 static void set_event_data(LONG exp_lbound0, LONG exp_lbound1, LONG exp_elems0, LONG exp_elems1,
15058 struct node_provider_desc *exp_node_desc, const WCHAR *exp_tree_struct)
15060 EventData.exp_lbound[0] = exp_lbound0;
15061 EventData.exp_lbound[1] = exp_lbound1;
15062 EventData.exp_elems[0] = exp_elems0;
15063 EventData.exp_elems[1] = exp_elems1;
15064 if (exp_node_desc)
15066 int i;
15068 EventData.exp_node_desc = *exp_node_desc;
15069 for (i = 0; i < exp_node_desc->prov_count; i++)
15071 if (exp_node_desc->nested_desc[i])
15073 EventData.exp_nested_node_desc = *exp_node_desc->nested_desc[i];
15074 EventData.exp_node_desc.nested_desc[i] = &EventData.exp_nested_node_desc;
15075 break;
15079 else
15080 memset(&EventData.exp_node_desc, 0, sizeof(EventData.exp_node_desc));
15081 EventData.exp_tree_struct = exp_tree_struct;
15084 static void WINAPI uia_event_callback(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
15086 CHECK_EXPECT(uia_event_callback);
15088 if (!EventData.exp_elems[0] && !EventData.exp_elems[1])
15089 ok(!req_data, "req_data != NULL\n");
15090 else
15091 test_cache_req_sa(req_data, EventData.exp_lbound, EventData.exp_elems, &EventData.exp_node_desc);
15093 ok(!wcscmp(tree_struct, EventData.exp_tree_struct), "tree structure %s\n", debugstr_w(tree_struct));
15094 if (EventData.event_handle)
15095 SetEvent(EventData.event_handle);
15098 enum {
15099 WM_UIA_TEST_RESET_EVENT_PROVIDERS = WM_APP,
15100 WM_UIA_TEST_SET_EVENT_PROVIDER_DATA,
15101 WM_UIA_TEST_RAISE_EVENT,
15102 WM_UIA_TEST_RAISE_EVENT_RT_ID,
15103 WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED,
15104 WM_UIA_TEST_CHECK_EVENT_ADVISE_REMOVED,
15107 enum {
15108 PROVIDER_ID,
15109 PROVIDER2_ID,
15110 PROVIDER_CHILD_ID,
15113 static struct Provider *event_test_provs[] = { &Provider, &Provider2, &Provider_child };
15114 static struct Provider *get_event_test_prov(int idx)
15116 if (idx >= ARRAY_SIZE(event_test_provs))
15117 return NULL;
15118 else
15119 return event_test_provs[idx];
15122 static void post_event_message(HWND hwnd, int msg, WPARAM wparam, int prov_id, int lparam_lower)
15124 PostMessageW(hwnd, msg, wparam, MAKELONG(lparam_lower, prov_id));
15127 static void test_UiaAddEvent_client_proc(void)
15129 IRawElementProviderFragmentRoot *embedded_root = &Provider_hwnd2.IRawElementProviderFragmentRoot_iface;
15130 struct node_provider_desc exp_node_desc, exp_nested_node_desc;
15131 struct UiaCacheRequest cache_req;
15132 HUIAEVENT event;
15133 HUIANODE node;
15134 BOOL is_win11;
15135 HRESULT hr;
15136 DWORD pid;
15137 HWND hwnd;
15139 CoInitializeEx(NULL, COINIT_MULTITHREADED);
15140 hwnd = FindWindowA("UiaAddEvent test class", "Test window");
15141 UiaRegisterProviderCallback(test_uia_provider_callback);
15142 EventData.event_handle = CreateEventW(NULL, FALSE, FALSE, NULL);
15144 /* Provider_proxy/hwnd/nc are desktop providers. */
15145 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
15146 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
15147 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
15148 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
15151 * Provider_nc2/Provider_hwnd2 are clientside providers for our test
15152 * window.
15154 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
15155 provider_add_child(&Provider_hwnd, &Provider_hwnd2);
15157 method_sequences_enabled = FALSE;
15158 SET_EXPECT(prov_callback_base_hwnd);
15159 SET_EXPECT(prov_callback_nonclient);
15160 SET_EXPECT(prov_callback_proxy);
15161 hr = UiaGetRootNode(&node);
15162 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15163 ok(!!node, "Node == NULL.\n");
15164 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
15165 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
15166 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
15167 CHECK_CALLED(prov_callback_base_hwnd);
15168 CHECK_CALLED(prov_callback_nonclient);
15169 CHECK_CALLED(prov_callback_proxy);
15171 PostMessageW(hwnd, WM_UIA_TEST_RESET_EVENT_PROVIDERS, 0, 0);
15173 /* Register an event on the desktop HWND with a scope of all elements. */
15174 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15175 AutomationElementMode_Full);
15176 event = NULL;
15177 /* Only done on Win11. */
15178 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
15179 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
15180 SET_EXPECT_MULTI(prov_callback_proxy, 2);
15181 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants,
15182 NULL, 0, &cache_req, &event);
15183 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15184 ok(!!event, "event == NULL\n");
15185 is_win11 = !!CALLED_COUNT(prov_callback_base_hwnd);
15186 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, 2);
15187 CHECK_CALLED_AT_MOST(prov_callback_nonclient, 2);
15188 CHECK_CALLED_AT_MOST(prov_callback_proxy, 2);
15189 method_sequences_enabled = TRUE;
15192 * Raise event in another process, prior to calling UiaEventAddWindow.
15193 * Event handler will not get triggered.
15195 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT, HandleToUlong(hwnd), PROVIDER_ID, ProviderOptions_ServerSideProvider);
15196 ok(WaitForSingleObject(EventData.event_handle, 300) == WAIT_TIMEOUT, "Wait for event_handle didn't timeout.\n");
15197 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED, 0, PROVIDER_ID, FALSE);
15199 /* Call UiaEventAddWindow, the event will now be connected. */
15200 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
15201 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
15202 SET_EXPECT_MULTI(prov_callback_proxy, 3);
15203 hr = UiaEventAddWindow(event, hwnd);
15204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15205 CHECK_CALLED(prov_callback_base_hwnd);
15206 CHECK_CALLED(prov_callback_nonclient);
15207 todo_wine CHECK_CALLED(prov_callback_proxy);
15208 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED, UIA_AutomationFocusChangedEventId, PROVIDER_ID, FALSE);
15210 /* Successfully raise event. */
15211 GetWindowThreadProcessId(hwnd, &pid);
15212 init_node_provider_desc(&exp_nested_node_desc, pid, hwnd);
15213 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider", TRUE);
15215 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
15216 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", TRUE);
15217 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
15218 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, FALSE, &exp_nested_node_desc);
15219 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15221 SET_EXPECT(prov_callback_base_hwnd);
15222 SET_EXPECT(prov_callback_nonclient);
15223 SET_EXPECT(prov_callback_proxy);
15224 SET_EXPECT(uia_event_callback);
15225 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT, HandleToUlong(hwnd), PROVIDER_ID, ProviderOptions_ServerSideProvider);
15226 ok(!WaitForSingleObject(EventData.event_handle, 2000), "Wait for event_handle failed.\n");
15227 CHECK_CALLED(uia_event_callback);
15228 CHECK_CALLED(prov_callback_base_hwnd);
15229 CHECK_CALLED(prov_callback_nonclient);
15230 todo_wine CHECK_CALLED(prov_callback_proxy);
15233 * If a clientside provider raises an event, it stays within its own
15234 * process.
15236 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT, 0, PROVIDER2_ID, ProviderOptions_ClientSideProvider);
15237 ok(WaitForSingleObject(EventData.event_handle, 300) == WAIT_TIMEOUT, "Wait for event_handle didn't timeout.\n");
15239 /* Raise serverside event. */
15240 GetWindowThreadProcessId(hwnd, &pid);
15241 init_node_provider_desc(&exp_node_desc, pid, NULL);
15242 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15243 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15245 SET_EXPECT(uia_event_callback);
15246 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT, 0, PROVIDER2_ID, ProviderOptions_ServerSideProvider);
15247 ok(!WaitForSingleObject(EventData.event_handle, 2000), "Wait for event_handle failed.\n");
15248 CHECK_CALLED(uia_event_callback);
15250 hr = UiaRemoveEvent(event);
15251 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15252 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_REMOVED, UIA_AutomationFocusChangedEventId, PROVIDER_ID, FALSE);
15254 PostMessageW(hwnd, WM_UIA_TEST_RESET_EVENT_PROVIDERS, 0, 0);
15255 post_event_message(hwnd, WM_UIA_TEST_SET_EVENT_PROVIDER_DATA, HandleToUlong(hwnd), PROVIDER_ID,
15256 ProviderOptions_ServerSideProvider);
15259 * Register an event on the desktop node, except this time the scope
15260 * doesn't include the desktop node itself. In this case, navigation will
15261 * have to be done to confirm a provider that raised an event is a
15262 * descendant of the desktop, but not the desktop itself.
15264 * No need for UiaEventAddWindow this time, because Provider_hwnd2 is an
15265 * embedded root. This method no longer works on Windows 11, which breaks
15266 * the managed UI Automation API. We match the old behavior instead.
15268 Provider_hwnd.embedded_frag_roots = &embedded_root;
15269 Provider_hwnd.embedded_frag_roots_count = 1;
15270 Provider_hwnd2.frag_root = &Provider_hwnd2.IRawElementProviderFragmentRoot_iface;
15272 event = NULL;
15273 /* Only done on Win11. */
15274 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
15275 SET_EXPECT_MULTI(prov_callback_nonclient, 3);
15276 SET_EXPECT_MULTI(prov_callback_proxy, 3);
15277 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Descendants,
15278 NULL, 0, &cache_req, &event);
15279 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15280 ok(!!event, "event == NULL\n");
15281 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
15282 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, 2);
15283 CHECK_CALLED_AT_MOST(prov_callback_nonclient, 3);
15284 CHECK_CALLED_AT_MOST(prov_callback_proxy, 3);
15286 if (is_win11)
15288 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED, 0, PROVIDER_ID, FALSE);
15289 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
15290 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
15291 SET_EXPECT_MULTI(prov_callback_proxy, 3);
15292 hr = UiaEventAddWindow(event, hwnd);
15293 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15294 CHECK_CALLED_MULTI(prov_callback_base_hwnd, 2);
15295 CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
15296 CHECK_CALLED_MULTI(prov_callback_proxy, 3);
15299 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED, UIA_AutomationFocusChangedEventId, PROVIDER_ID, FALSE);
15302 * Starts navigation in server process, then completes navigation in the
15303 * client process.
15305 GetWindowThreadProcessId(hwnd, &pid);
15306 init_node_provider_desc(&exp_node_desc, pid, NULL);
15307 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
15308 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15309 SET_EXPECT(prov_callback_base_hwnd);
15310 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
15311 SET_EXPECT_MULTI(prov_callback_proxy, 2);
15312 SET_EXPECT(uia_event_callback);
15314 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT, 0, PROVIDER_CHILD_ID, ProviderOptions_ServerSideProvider);
15315 ok(!WaitForSingleObject(EventData.event_handle, 5000), "Wait for event_handle failed.\n");
15316 CHECK_CALLED(prov_callback_base_hwnd);
15317 CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
15318 todo_wine CHECK_CALLED_MULTI(prov_callback_proxy, 2);
15319 CHECK_CALLED(uia_event_callback);
15321 hr = UiaRemoveEvent(event);
15322 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15323 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_REMOVED, UIA_AutomationFocusChangedEventId, PROVIDER_ID, FALSE);
15326 * Register an event on a node that won't require any navigation to reach.
15328 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, TRUE);
15329 Provider.runtime_id[0] = 0x1337;
15330 Provider.runtime_id[1] = 0xbeef;
15331 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
15332 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15333 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15335 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element,
15336 NULL, 0, &cache_req, &event);
15337 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15338 ok(!!event, "event == NULL\n");
15339 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
15341 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
15342 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
15343 SET_EXPECT_MULTI(prov_callback_proxy, 3);
15344 hr = UiaEventAddWindow(event, hwnd);
15345 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15346 CHECK_CALLED(prov_callback_base_hwnd);
15347 CHECK_CALLED(prov_callback_nonclient);
15348 todo_wine CHECK_CALLED(prov_callback_proxy);
15350 /* Wrong runtime ID, no match. */
15351 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT_RT_ID, 0xb33f, PROVIDER2_ID, 0x1337);
15352 ok(WaitForSingleObject(EventData.event_handle, 500) == WAIT_TIMEOUT, "Wait for event_handle didn't timeout.\n");
15354 /* Successfully raise event. */
15355 GetWindowThreadProcessId(hwnd, &pid);
15356 init_node_provider_desc(&exp_node_desc, pid, NULL);
15357 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15358 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15359 SET_EXPECT(uia_event_callback);
15360 post_event_message(hwnd, WM_UIA_TEST_RAISE_EVENT_RT_ID, 0xbeef, PROVIDER2_ID, 0x1337);
15361 ok(!WaitForSingleObject(EventData.event_handle, 2000), "Wait for event_handle failed.\n");
15362 CHECK_CALLED(uia_event_callback);
15364 hr = UiaRemoveEvent(event);
15365 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15366 CloseHandle(EventData.event_handle);
15367 CoUninitialize();
15370 struct event_test_thread_data {
15371 HUIAEVENT event;
15372 DWORD exp_thread_id;
15375 static DWORD WINAPI uia_add_event_test_thread(LPVOID param)
15377 struct event_test_thread_data *data = (struct event_test_thread_data *)param;
15378 HRESULT hr;
15380 CoInitializeEx(NULL, COINIT_MULTITHREADED);
15382 hr = UiaRemoveEvent(data->event);
15383 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15384 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15385 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
15386 ok(Provider2.last_call_tid == data->exp_thread_id ||
15387 broken(Provider2.last_call_tid == GetCurrentThreadId()), "Expected method call on separate thread\n");
15388 ok(Provider2.advise_events_removed_event_id == UIA_AutomationFocusChangedEventId,
15389 "Unexpected advise event removed, event ID %d\n", Provider.advise_events_removed_event_id);
15391 CoUninitialize();
15392 return 0;
15395 static void test_UiaAddEvent_args(HUIANODE node)
15397 struct UiaCacheRequest cache_req;
15398 HUIAEVENT event;
15399 HRESULT hr;
15401 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15402 AutomationElementMode_Full);
15404 /* NULL node. */
15405 hr = UiaAddEvent(NULL, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
15406 &event);
15407 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15409 /* NULL event callback. */
15410 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, NULL, TreeScope_Element, NULL, 0, &cache_req,
15411 &event);
15412 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15414 /* NULL cache request. */
15415 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, NULL,
15416 &event);
15417 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15419 /* NULL event handle. */
15420 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
15421 NULL);
15422 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15424 /* Event IDs aren't checked for validity, 1 is not a valid UIA event ID. */
15425 event = NULL;
15426 hr = UiaAddEvent(node, 1, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req, &event);
15427 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15428 ok(!!event, "event == NULL\n");
15430 hr = UiaRemoveEvent(event);
15431 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15434 static void test_UiaRemoveEvent_args(HUIANODE node)
15436 HRESULT hr;
15438 hr = UiaRemoveEvent(NULL);
15439 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15441 hr = UiaRemoveEvent((HUIAEVENT)node);
15442 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15445 static void test_UiaRaiseAutomationEvent_args(void)
15447 HRESULT hr;
15449 hr = UiaRaiseAutomationEvent(NULL, UIA_AutomationFocusChangedEventId);
15450 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15452 /* Returns failure code from get_ProviderOptions. */
15453 initialize_provider(&Provider2, 0, NULL, TRUE);
15454 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15455 /* Windows 7 returns S_OK. */
15456 ok(hr == E_NOTIMPL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
15458 /* Invalid event ID - doesn't return failure code. */
15459 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, NULL, TRUE);
15460 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, 1);
15461 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15464 * UIA_StructureChangedEventId should use UiaRaiseStructureChangedEvent.
15465 * No failure code is returned, however.
15467 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_StructureChangedEventId);
15468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15471 static void test_UiaAddEvent(const char *name)
15473 IRawElementProviderFragmentRoot *embedded_roots[2] = { &Provider_child.IRawElementProviderFragmentRoot_iface,
15474 &Provider_child2.IRawElementProviderFragmentRoot_iface };
15475 struct event_test_thread_data thread_data = { 0 };
15476 struct Provider_prop_override prop_override;
15477 struct node_provider_desc exp_node_desc;
15478 struct UiaPropertyCondition prop_cond;
15479 struct UiaCacheRequest cache_req;
15480 PROCESS_INFORMATION proc;
15481 char cmdline[MAX_PATH];
15482 STARTUPINFOA startup;
15483 HUIAEVENT event;
15484 DWORD exit_code;
15485 HUIANODE node;
15486 HANDLE thread;
15487 HRESULT hr;
15488 HWND hwnd;
15489 VARIANT v;
15491 CoInitializeEx(NULL, COINIT_MULTITHREADED);
15493 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, TRUE);
15494 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
15495 provider_add_child(&Provider, &Provider_child);
15496 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
15497 provider_add_child(&Provider_child, &Provider_child_child);
15499 /* Create a node with Provider as its only provider. */
15500 method_sequences_enabled = FALSE;
15501 hr = UiaNodeFromProvider(&Provider.IRawElementProviderSimple_iface, &node);
15502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15503 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15505 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
15506 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
15507 check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
15508 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
15509 VariantClear(&v);
15511 /* Test valid function input arguments. */
15512 test_UiaAddEvent_args(node);
15513 test_UiaRemoveEvent_args(node);
15514 test_UiaRaiseAutomationEvent_args();
15517 * Raise event without any registered event handlers.
15519 method_sequences_enabled = TRUE;
15520 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15522 ok_method_sequence(event_seq1, "event_seq1");
15525 * Register an event on a node without an HWND/RuntimeId. The event will
15526 * be created successfully, but without any way to match a provider to
15527 * this node, we won't be able to trigger the event handler.
15529 event = NULL;
15530 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
15531 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15532 AutomationElementMode_Full);
15533 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
15534 &event);
15535 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15536 ok(!!event, "event == NULL\n");
15537 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
15538 ok_method_sequence(event_seq2, "event_seq2");
15541 * Even though we raise an event on the same provider as the one our node
15542 * currently represents, without an HWND/RuntimeId, we have no way to
15543 * match them. The event handler will not be called.
15545 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15546 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15547 ok_method_sequence(event_seq3, "event_seq3");
15549 hr = UiaRemoveEvent(event);
15550 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15551 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15552 ok_method_sequence(event_seq4, "event_seq4");
15555 * Register an event on the same node again, except this time we have a
15556 * runtimeID. Nodes returned to the event handler are normalized against
15557 * the cache request view condition.
15559 event = NULL;
15560 variant_init_bool(&v, TRUE);
15561 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
15562 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
15563 AutomationElementMode_Full);
15565 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
15566 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
15567 &event);
15568 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15569 ok(!!event, "event == NULL\n");
15570 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
15571 ok_method_sequence(event_seq2, "event_seq2");
15573 /* Event callback is now invoked since we can match by runtime ID. */
15574 method_sequences_enabled = FALSE;
15575 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
15576 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
15577 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15578 SET_EXPECT(uia_event_callback);
15579 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15580 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15581 CHECK_CALLED(uia_event_callback);
15584 * Runtime ID matches so event callback is invoked, but nothing matches
15585 * the cache request view condition, so the callback will be passed a
15586 * NULL cache request.
15588 variant_init_bool(&v, FALSE);
15589 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
15590 set_provider_prop_override(&Provider, &prop_override, 1);
15592 set_event_data(0, 0, 0, 0, &exp_node_desc, L"");
15593 SET_EXPECT(uia_event_callback);
15594 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15596 CHECK_CALLED(uia_event_callback);
15597 set_provider_prop_override(&Provider, NULL, 0);
15599 method_sequences_enabled = TRUE;
15600 hr = UiaRemoveEvent(event);
15601 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15602 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15603 ok_method_sequence(event_seq4, "event_seq4");
15605 /* Create an event with TreeScope_Children. */
15606 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Children, NULL, 0, &cache_req,
15607 &event);
15608 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15609 ok(!!event, "event == NULL\n");
15610 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
15611 ok_method_sequence(event_seq5, "event_seq5");
15614 * Only TreeScope_Children and not TreeScope_Element, handler won't be
15615 * called.
15617 method_sequences_enabled = FALSE;
15618 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15619 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15621 /* Provider_child_child is not a direct child, handler won't be called. */
15622 hr = UiaRaiseAutomationEvent(&Provider_child_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15623 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15625 /* Raised an event on Provider_child, handler will be called. */
15626 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
15627 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
15628 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15629 SET_EXPECT(uia_event_callback);
15630 hr = UiaRaiseAutomationEvent(&Provider_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15631 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15632 CHECK_CALLED(uia_event_callback);
15634 /* Provider_child doesn't match the view condition, but Provider does. */
15635 variant_init_bool(&v, FALSE);
15636 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
15637 set_provider_prop_override(&Provider_child, &prop_override, 1);
15639 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
15640 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
15641 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15642 SET_EXPECT(uia_event_callback);
15643 hr = UiaRaiseAutomationEvent(&Provider_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15644 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15645 CHECK_CALLED(uia_event_callback);
15646 set_provider_prop_override(&Provider_child, NULL, 0);
15648 hr = UiaRemoveEvent(event);
15649 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15650 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15652 /* Create an event with TreeScope_Descendants. */
15653 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
15654 &cache_req, &event);
15655 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15656 ok(!!event, "event == NULL\n");
15657 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
15659 /* Raised an event on Provider_child_child. */
15660 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
15661 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child_child", TRUE);
15662 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15663 SET_EXPECT(uia_event_callback);
15664 hr = UiaRaiseAutomationEvent(&Provider_child_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15665 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15666 CHECK_CALLED(uia_event_callback);
15668 hr = UiaRemoveEvent(event);
15669 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15670 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15672 CoUninitialize();
15675 * When adding an event, each node provider's fragment root is queried
15676 * for, and if one is retrieved, it's IRawElementProviderAdviseEvents
15677 * interface is used. On Win10v1809+, ProviderOptions_UseComThreading is
15678 * respected for these interfaces. Set Provider2 as the fragment root here
15679 * to test this.
15681 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
15683 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
15684 initialize_provider(&Provider2, ProviderOptions_UseComThreading | ProviderOptions_ServerSideProvider, NULL, TRUE);
15685 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
15686 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
15687 &cache_req, &event);
15688 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15689 ok(!!event, "event == NULL\n");
15690 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15691 ok(Provider2.ref > 1, "Unexpected refcnt %ld\n", Provider2.ref);
15692 ok(!Provider.advise_events_added_event_id, "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
15693 ok(Provider2.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
15694 "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
15696 thread_data.exp_thread_id = GetCurrentThreadId();
15697 thread_data.event = event;
15698 thread = CreateThread(NULL, 0, uia_add_event_test_thread, (void *)&thread_data, 0, NULL);
15699 while (MsgWaitForMultipleObjects(1, &thread, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
15701 MSG msg;
15703 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
15705 TranslateMessage(&msg);
15706 DispatchMessageW(&msg);
15709 CloseHandle(thread);
15711 /* Test retrieving AdviseEvents on embedded fragment roots. */
15712 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
15713 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
15714 initialize_provider(&Provider_child2, ProviderOptions_ServerSideProvider, NULL, FALSE);
15715 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
15716 Provider.embedded_frag_roots = embedded_roots;
15717 Provider.embedded_frag_roots_count = ARRAY_SIZE(embedded_roots);
15718 Provider_child.frag_root = &Provider_child.IRawElementProviderFragmentRoot_iface;
15719 Provider_child2.frag_root = &Provider_child2.IRawElementProviderFragmentRoot_iface;
15721 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
15722 &cache_req, &event);
15723 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15724 ok(!!event, "event == NULL\n");
15725 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
15726 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
15727 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
15728 ok(Provider.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
15729 "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
15730 ok(Provider_child.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
15731 "Unexpected advise event added, event ID %d\n", Provider_child.advise_events_added_event_id);
15732 ok(Provider_child2.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
15733 "Unexpected advise event added, event ID %d\n", Provider_child2.advise_events_added_event_id);
15735 method_sequences_enabled = TRUE;
15736 hr = UiaRemoveEvent(event);
15737 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15738 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
15739 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
15740 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
15741 ok_method_sequence(event_seq6, "event_seq6");
15743 UiaNodeRelease(node);
15744 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
15745 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, TRUE);
15746 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
15747 initialize_provider(&Provider_child2, ProviderOptions_ServerSideProvider, NULL, TRUE);
15749 hwnd = create_test_hwnd("UiaAddEvent test class");
15750 UiaRegisterProviderCallback(test_uia_provider_callback);
15752 /* Set clientside providers for our test window and the desktop. */
15753 set_clientside_providers_for_hwnd(&Provider_proxy, &Provider_nc, &Provider_hwnd, GetDesktopWindow());
15754 Provider_proxy.frag_root = Provider_hwnd.frag_root = Provider_nc.frag_root = NULL;
15755 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
15756 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
15757 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
15759 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
15760 provider_add_child(&Provider_nc, &Provider_nc2);
15761 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
15762 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
15763 prov_root = &Provider.IRawElementProviderSimple_iface;
15764 Provider.ignore_hwnd_prop = TRUE;
15766 method_sequences_enabled = FALSE;
15767 SET_EXPECT(prov_callback_base_hwnd);
15768 SET_EXPECT(prov_callback_nonclient);
15769 SET_EXPECT(prov_callback_proxy);
15770 hr = UiaGetRootNode(&node);
15771 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15772 ok(!!node, "Node == NULL.\n");
15773 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
15774 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
15775 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
15776 CHECK_CALLED(prov_callback_base_hwnd);
15777 CHECK_CALLED(prov_callback_nonclient);
15778 CHECK_CALLED(prov_callback_proxy);
15780 /* Register an event on the desktop HWND. */
15781 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15782 AutomationElementMode_Full);
15783 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Children, NULL, 0,
15784 &cache_req, &event);
15785 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15786 ok(!!event, "event == NULL\n");
15789 * Raising an event on a serverside provider results in no clientside
15790 * providers being added for the HWND, which means we won't match this
15791 * event.
15793 Provider_hwnd2.prov_opts = ProviderOptions_ServerSideProvider;
15794 hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15795 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15797 /* Now that Provider has clientside providers, the event will be matched. */
15798 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
15799 SET_EXPECT(prov_callback_base_hwnd);
15800 SET_EXPECT(prov_callback_nonclient);
15801 SET_EXPECT_MULTI(prov_callback_proxy, 2);
15802 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
15803 add_provider_desc(&exp_node_desc, L"Main", L"Provider", FALSE);
15804 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", TRUE);
15805 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
15806 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15807 SET_EXPECT(uia_event_callback);
15808 Provider_hwnd2.prov_opts = ProviderOptions_ClientSideProvider;
15809 hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15810 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15811 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
15812 CHECK_CALLED(prov_callback_base_hwnd);
15813 CHECK_CALLED(prov_callback_nonclient);
15814 todo_wine CHECK_CALLED_MULTI(prov_callback_proxy, 2);
15815 CHECK_CALLED(uia_event_callback);
15817 hr = UiaRemoveEvent(event);
15818 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15821 * Register an event on the desktop HWND with a scope of TreeScope_Element
15822 * and TreeScope_Descendants. This is a special case where all providers
15823 * will match, regardless of whether or not they can navigate to the
15824 * desktop node.
15826 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15827 AutomationElementMode_Full);
15828 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
15829 &cache_req, &event);
15830 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15831 ok(!!event, "event == NULL\n");
15834 * Raise an event on Provider2 - completely disconnected from all other
15835 * providers, will still trigger the event callback.
15837 initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, NULL, TRUE);
15838 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
15839 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15840 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15841 SET_EXPECT(uia_event_callback);
15842 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15843 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15844 CHECK_CALLED(uia_event_callback);
15847 * No clientside providers to match us to the desktop node through
15848 * navigation, but event will still be triggered.
15850 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
15851 add_provider_desc(&exp_node_desc, L"Main", L"Provider_hwnd2", TRUE);
15852 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
15853 SET_EXPECT(uia_event_callback);
15854 Provider_hwnd2.prov_opts = ProviderOptions_ServerSideProvider;
15855 Provider_hwnd2.ignore_hwnd_prop = TRUE;
15856 hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15858 CHECK_CALLED(uia_event_callback);
15860 hr = UiaRemoveEvent(event);
15861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15862 UiaNodeRelease(node);
15863 CoUninitialize();
15865 /* Cross process event tests. */
15866 UiaRegisterProviderCallback(NULL);
15867 CoInitializeEx(NULL, COINIT_MULTITHREADED);
15868 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
15869 Provider.frag_root = &Provider.IRawElementProviderFragmentRoot_iface;
15870 initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, TRUE);
15871 provider_add_child(&Provider, &Provider_child);
15873 prov_root = &Provider.IRawElementProviderSimple_iface;
15874 sprintf(cmdline, "\"%s\" uiautomation UiaAddEvent_client_proc", name);
15875 memset(&startup, 0, sizeof(startup));
15876 startup.cb = sizeof(startup);
15877 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 22);
15878 /* Only sent on Win7. */
15879 SET_EXPECT(winproc_GETOBJECT_CLIENT);
15881 CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
15882 while (MsgWaitForMultipleObjects(1, &proc.hProcess, FALSE, INFINITE, QS_ALLINPUT) != WAIT_OBJECT_0)
15884 struct Provider *prov;
15885 MSG msg = { 0 };
15887 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
15889 switch (msg.message)
15891 case WM_UIA_TEST_RESET_EVENT_PROVIDERS:
15893 int i;
15895 for (i = 0; i < ARRAY_SIZE(event_test_provs); i++)
15896 initialize_provider(event_test_provs[i], ProviderOptions_ServerSideProvider, NULL, FALSE);
15897 break;
15900 case WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED:
15901 case WM_UIA_TEST_CHECK_EVENT_ADVISE_REMOVED:
15902 if (!(prov = get_event_test_prov(HIWORD(msg.lParam))))
15903 break;
15905 if (msg.message == WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED)
15906 todo_wine_if(LOWORD(msg.lParam)) ok(prov->advise_events_added_event_id == msg.wParam,
15907 "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
15908 else
15909 todo_wine_if(LOWORD(msg.lParam)) ok(prov->advise_events_removed_event_id == msg.wParam,
15910 "Unexpected advise event removed, event ID %d\n", Provider.advise_events_removed_event_id);
15911 break;
15913 case WM_UIA_TEST_RAISE_EVENT:
15914 case WM_UIA_TEST_RAISE_EVENT_RT_ID:
15915 case WM_UIA_TEST_SET_EVENT_PROVIDER_DATA:
15916 if (!(prov = get_event_test_prov(HIWORD(msg.lParam))))
15917 break;
15919 if ((msg.message == WM_UIA_TEST_RAISE_EVENT) || (msg.message == WM_UIA_TEST_SET_EVENT_PROVIDER_DATA))
15921 prov->prov_opts = LOWORD(msg.lParam);
15922 prov->hwnd = UlongToHandle(msg.wParam);
15923 prov->ignore_hwnd_prop = !!prov->hwnd;
15925 else if (msg.message == WM_UIA_TEST_RAISE_EVENT_RT_ID)
15927 prov->runtime_id[0] = LOWORD(msg.lParam);
15928 prov->runtime_id[1] = msg.wParam;
15931 if (msg.message != WM_UIA_TEST_SET_EVENT_PROVIDER_DATA)
15933 hr = UiaRaiseAutomationEvent(&prov->IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15934 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15936 break;
15938 default:
15939 prov = NULL;
15940 break;
15943 TranslateMessage(&msg);
15944 DispatchMessageW(&msg);
15948 CHECK_CALLED_AT_LEAST(winproc_GETOBJECT_UiaRoot, 5);
15949 GetExitCodeProcess(proc.hProcess, &exit_code);
15950 if (exit_code > 255)
15951 ok(0, "unhandled exception %08x in child process %04x\n", (UINT)exit_code, (UINT)GetProcessId(proc.hProcess));
15952 else if (exit_code)
15953 ok(0, "%u failures in child process\n", (UINT)exit_code);
15954 CloseHandle(proc.hProcess);
15956 method_sequences_enabled = TRUE;
15957 CoUninitialize();
15958 DestroyWindow(hwnd);
15959 UnregisterClassA("UiaAddEvent test class", NULL);
15962 static const struct prov_method_sequence serverside_prov_seq[] = {
15963 NODE_CREATE_SEQ2(&Provider),
15964 /* Windows 10+ calls this. */
15965 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
15966 { 0 }
15969 static void test_UiaHasServerSideProvider(void)
15971 BOOL ret_val;
15972 HWND hwnd;
15974 CoInitializeEx(NULL, COINIT_MULTITHREADED);
15975 hwnd = create_test_hwnd("UiaHasServerSideProvider test class");
15977 /* NULL hwnd. */
15978 ret_val = UiaHasServerSideProvider(NULL);
15979 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
15981 /* Desktop window has no serverside providers. */
15982 UiaRegisterProviderCallback(test_uia_provider_callback);
15983 ret_val = UiaHasServerSideProvider(GetDesktopWindow());
15984 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
15986 /* No provider to pass to UiaReturnRawElementProvider, returns FALSE. */
15987 prov_root = NULL;
15988 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
15989 ret_val = UiaHasServerSideProvider(hwnd);
15990 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
15991 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
15994 * Provider passed to UiaReturnRawElementProvider returns a failure from
15995 * get_ProviderOptions. Returns FALSE.
15997 initialize_provider(&Provider, 0, hwnd, TRUE);
15998 prov_root = &Provider.IRawElementProviderSimple_iface;
15999 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16000 ret_val = UiaHasServerSideProvider(hwnd);
16001 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
16002 ok_method_sequence(node_from_hwnd1, NULL);
16003 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16005 /* Successfully return a provider from UiaReturnRawElementProvider. */
16006 initialize_provider(&Provider, ProviderOptions_ServerSideProvider, hwnd, TRUE);
16007 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16008 ret_val = UiaHasServerSideProvider(hwnd);
16009 ok(ret_val, "UiaHasServerSideProvider returned FALSE\n");
16010 ok_method_sequence(serverside_prov_seq, "serverside_prov_seq");
16011 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16013 UiaRegisterProviderCallback(NULL);
16014 prov_root = NULL;
16015 CoUninitialize();
16016 DestroyWindow(hwnd);
16017 UnregisterClassA("UiaHasServerSideProvider test class", NULL);
16021 * Once a process returns a UI Automation provider with
16022 * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This
16023 * messes with tests around COM initialization, so we run these tests in
16024 * separate processes.
16026 static void launch_test_process(const char *name, const char *test_name)
16028 PROCESS_INFORMATION proc;
16029 STARTUPINFOA startup;
16030 char cmdline[MAX_PATH];
16032 sprintf(cmdline, "\"%s\" uiautomation %s", name, test_name);
16033 memset(&startup, 0, sizeof(startup));
16034 startup.cb = sizeof(startup);
16035 CreateProcessA(NULL, cmdline, NULL, NULL, FALSE, 0, NULL, NULL, &startup, &proc);
16036 wait_child_process(proc.hProcess);
16039 START_TEST(uiautomation)
16041 HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll");
16042 BOOL (WINAPI *pImmDisableIME)(DWORD);
16043 HMODULE hModuleImm32;
16044 char **argv;
16045 int argc;
16047 /* Make sure COM isn't initialized by imm32. */
16048 hModuleImm32 = LoadLibraryA("imm32.dll");
16049 if (hModuleImm32) {
16050 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME");
16051 if (pImmDisableIME)
16052 pImmDisableIME(0);
16054 pImmDisableIME = NULL;
16055 FreeLibrary(hModuleImm32);
16057 if (uia_dll)
16058 pUiaDisconnectProvider = (void *)GetProcAddress(uia_dll, "UiaDisconnectProvider");
16060 argc = winetest_get_mainargs(&argv);
16061 if (argc == 3)
16063 if (!strcmp(argv[2], "UiaNodeFromHandle"))
16064 test_UiaNodeFromHandle(argv[0]);
16065 else if (!strcmp(argv[2], "UiaNodeFromHandle_client_proc"))
16066 test_UiaNodeFromHandle_client_proc();
16067 else if (!strcmp(argv[2], "UiaRegisterProviderCallback"))
16068 test_UiaRegisterProviderCallback();
16069 else if (!strcmp(argv[2], "UiaAddEvent_client_proc"))
16070 test_UiaAddEvent_client_proc();
16072 FreeLibrary(uia_dll);
16073 return;
16076 test_UiaHostProviderFromHwnd();
16077 test_uia_reserved_value_ifaces();
16078 test_UiaLookupId();
16079 test_UiaNodeFromProvider();
16080 test_UiaGetPropertyValue();
16081 test_UiaGetRuntimeId();
16082 test_UiaHUiaNodeFromVariant();
16083 launch_test_process(argv[0], "UiaNodeFromHandle");
16084 launch_test_process(argv[0], "UiaRegisterProviderCallback");
16085 test_UiaGetUpdatedCache();
16086 test_UiaNavigate();
16087 test_UiaFind();
16088 test_CUIAutomation();
16089 test_default_clientside_providers();
16090 test_UiaGetRootNode();
16091 test_UiaNodeFromFocus();
16092 test_UiaAddEvent(argv[0]);
16093 test_UiaHasServerSideProvider();
16094 if (uia_dll)
16096 pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible");
16097 if (pUiaProviderFromIAccessible)
16098 test_UiaProviderFromIAccessible();
16099 else
16100 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
16102 FreeLibrary(uia_dll);