4 * Copyright 2019 Nikolay Sivov for CodeWeavers
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 #include "uiautomation.h"
28 #include "wine/iaccessible2.h"
30 #include "wine/test.h"
32 static HRESULT (WINAPI
*pUiaProviderFromIAccessible
)(IAccessible
*, LONG
, DWORD
, IRawElementProviderSimple
**);
33 static HRESULT (WINAPI
*pUiaDisconnectProvider
)(IRawElementProviderSimple
*);
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
)
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
)))
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) \
348 ok(expect_ ##func, "unexpected call " #func "\n"); \
352 #define CHECK_EXPECT(func) \
354 CHECK_EXPECT2(func); \
358 #define CALLED_COUNT(func) \
361 #define CHECK_CALLED(func) \
363 ok(called_ ## func, "expected " #func "\n"); \
364 expect_ ## func = called_ ## func = 0; \
367 #define CHECK_CALLED_MULTI(func, num) \
369 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
370 expect_ ## func = called_ ## func = 0; \
373 #define CHECK_CALLED_AT_LEAST(func, num) \
375 ok(called_ ## func >= num, "expected " #func " at least %d time(s) (got %d)\n", num, called_ ## func); \
376 expect_ ## func = called_ ## func = 0; \
379 #define CHECK_CALLED_AT_MOST(func, num) \
381 ok(called_ ## func <= num, "expected " #func " at most %d time(s) (got %d)\n", num, called_ ## func); \
382 expect_ ## func = called_ ## func = 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
)
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
))
414 static void variant_init_bool(VARIANT
*v
, BOOL val
)
417 V_BOOL(v
) = val
? VARIANT_TRUE
: VARIANT_FALSE
;
420 static BOOL
iface_cmp(IUnknown
*iface1
, IUnknown
*iface2
)
422 IUnknown
*unk1
, *unk2
;
425 IUnknown_QueryInterface(iface1
, &IID_IUnknown
, (void**)&unk1
);
426 IUnknown_QueryInterface(iface2
, &IID_IUnknown
, (void**)&unk2
);
429 IUnknown_Release(unk1
);
430 IUnknown_Release(unk2
);
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
;
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
);
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
;
501 const char *interface_name
;
510 LONG left
, top
, width
, height
;
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) \
524 ok((acc)->expect_ ##method, "unexpected call %s_" #method "\n", (acc)->interface_name); \
525 (acc)->called_ ## method++; \
528 #define CHECK_ACC_METHOD_EXPECT(acc, method) \
530 CHECK_ACC_METHOD_EXPECT2(acc, method); \
531 (acc)->expect_ ## method--; \
534 #define CHECK_ACC_METHOD_CALLED(acc, method) \
536 ok((acc)->called_ ## method, "expected %s_" #method "\n", (acc)->interface_name); \
537 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
540 #define CHECK_ACC_METHOD_CALLED_MULTI(acc, method, num) \
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; \
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
);
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
))
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
;
573 return E_NOINTERFACE
;
575 IAccessible_AddRef(iface
);
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");
597 static HRESULT WINAPI
Accessible_GetTypeInfo(IAccessible
*iface
, UINT iTInfo
,
598 LCID lcid
, ITypeInfo
**out_tinfo
)
600 ok(0, "unexpected call\n");
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");
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");
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
);
626 return IAccessible_QueryInterface(This
->parent
, &IID_IDispatch
, (void **)out_parent
);
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
;
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
);
656 if (V_VT(&child_id
) != VT_I4
)
659 if (This
== &Accessible
)
661 switch (V_I4(&child_id
))
664 return IAccessible_QueryInterface(&This
->IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
666 /* Simple element children. */
672 return IAccessible_QueryInterface(&Accessible_child
.IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
675 return IAccessible_QueryInterface(&Accessible_child2
.IAccessible_iface
, &IID_IDispatch
, (void **)out_child
);
685 static HRESULT WINAPI
Accessible_get_accName(IAccessible
*iface
, VARIANT child_id
,
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
);
696 *out_name
= SysAllocString(This
->name
);
703 static HRESULT WINAPI
Accessible_get_accValue(IAccessible
*iface
, VARIANT child_id
,
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
);
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
);
721 static HRESULT WINAPI
Accessible_get_accRole(IAccessible
*iface
, VARIANT child_id
,
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
);
731 V_VT(out_role
) = VT_I4
;
732 V_I4(out_role
) = This
->role
;
739 static HRESULT WINAPI
Accessible_get_accState(IAccessible
*iface
, VARIANT child_id
,
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
)
750 if (This
== &Accessible
&& V_I4(&child_id
) != CHILDID_SELF
)
752 switch (V_I4(&child_id
))
755 V_VT(out_state
) = VT_I4
;
756 V_I4(out_state
) = STATE_SYSTEM_INVISIBLE
;
760 V_VT(out_state
) = VT_I4
;
761 V_I4(out_state
) = STATE_SYSTEM_FOCUSABLE
;
773 V_VT(out_state
) = VT_I4
;
774 V_I4(out_state
) = This
->state
;
781 static HRESULT WINAPI
Accessible_get_accHelp(IAccessible
*iface
, VARIANT child_id
,
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
);
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
);
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
);
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
);
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
);
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
);
833 static HRESULT WINAPI
Accessible_accSelect(IAccessible
*iface
, LONG select_flags
,
836 struct Accessible
*This
= impl_from_Accessible(iface
);
837 CHECK_ACC_METHOD_EXPECT(This
, accSelect
);
838 ACC_METHOD_TRACE2(This
, &child_id
, accSelect
);
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
;
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
) &&
879 V_VT(out_var
) = VT_I4
;
880 V_I4(out_var
) = HandleToUlong(This
->acc_hwnd
);
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
);
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
);
903 static HRESULT WINAPI
Accessible_put_accName(IAccessible
*iface
, VARIANT child_id
,
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
);
912 static HRESULT WINAPI
Accessible_put_accValue(IAccessible
*iface
, VARIANT child_id
,
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
);
921 static IAccessibleVtbl AccessibleVtbl
= {
922 Accessible_QueryInterface
,
925 Accessible_GetTypeInfoCount
,
926 Accessible_GetTypeInfo
,
927 Accessible_GetIDsOfNames
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
,
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
1271 if (This
->unique_id
)
1273 *out_unique_id
= This
->unique_id
;
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
);
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
);
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
);
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
);
1312 static const IAccessible2Vtbl Accessible2Vtbl
= {
1313 Accessible2_QueryInterface
,
1315 Accessible2_Release
,
1316 Accessible2_GetTypeInfoCount
,
1317 Accessible2_GetTypeInfo
,
1318 Accessible2_GetIDsOfNames
,
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
,
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
)
1397 static const IOleWindowVtbl OleWindowVtbl
= {
1398 OleWindow_QueryInterface
,
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
) &&
1435 return IAccessible_QueryInterface(&This
->IAccessible_iface
, riid
, obj
);
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
},
1452 { &ServiceProviderVtbl
},
1462 static struct Accessible Accessible2
=
1464 { &AccessibleVtbl
},
1465 { &Accessible2Vtbl
},
1467 { &ServiceProviderVtbl
},
1477 static struct Accessible Accessible_child
=
1479 { &AccessibleVtbl
},
1480 { &Accessible2Vtbl
},
1482 { &ServiceProviderVtbl
},
1485 &Accessible
.IAccessible_iface
,
1492 static struct Accessible Accessible_child2
=
1494 { &AccessibleVtbl
},
1495 { &Accessible2Vtbl
},
1497 { &ServiceProviderVtbl
},
1499 "Accessible_child2",
1500 &Accessible
.IAccessible_iface
,
1507 struct Provider_prop_override
1513 struct Provider_value_pattern_data
1519 struct Provider_legacy_accessible_pattern_data
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
;
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
;
1546 BOOL ret_invalid_prop_type
;
1549 DWORD last_call_tid
;
1550 BOOL ignore_hwnd_prop
;
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)
1582 if (!(sa
= SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(uia_i4_arr_prop_val
))))
1585 for (idx
= 0; idx
< ARRAY_SIZE(uia_i4_arr_prop_val
); idx
++)
1586 SafeArrayPutElement(sa
, &idx
, (void *)&uia_i4_arr_prop_val
[idx
]);
1591 static SAFEARRAY
*create_r8_safearray(void)
1596 if (!(sa
= SafeArrayCreateVector(VT_R8
, 0, ARRAY_SIZE(uia_r8_arr_prop_val
))))
1599 for (idx
= 0; idx
< ARRAY_SIZE(uia_r8_arr_prop_val
); idx
++)
1600 SafeArrayPutElement(sa
, &idx
, (void *)&uia_r8_arr_prop_val
[idx
]);
1605 static SAFEARRAY
*create_unk_safearray(void)
1610 if (!(sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, ARRAY_SIZE(uia_unk_arr_prop_val
))))
1613 for (idx
= 0; idx
< ARRAY_SIZE(uia_unk_arr_prop_val
); idx
++)
1614 SafeArrayPutElement(sa
, &idx
, (void *)uia_unk_arr_prop_val
[idx
]);
1620 PROV_GET_PROVIDER_OPTIONS
,
1621 PROV_GET_PATTERN_PROV
,
1622 PROV_GET_PROPERTY_VALUE
,
1623 PROV_GET_HOST_RAW_ELEMENT_PROVIDER
,
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",
1639 "get_HostRawElementProvider",
1643 "get_BoundingRectangle",
1644 "GetEmbeddedFragmentRoots",
1646 "GetOverrideProviderForHwnd",
1648 "AdviseEventRemoved",
1651 static const char *get_prov_method_str(int method
)
1653 if (method
>= ARRAY_SIZE(prov_method_str
))
1656 return prov_method_str
[method
];
1660 METHOD_OPTIONAL
= 0x01,
1664 struct prov_method_sequence
{
1665 struct Provider
*prov
;
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
);
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
)
1745 sequence
= HeapAlloc(GetProcessHeap(), 0, sequence_size
* sizeof(*sequence
));
1747 if (sequence_cnt
== sequence_size
)
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);
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
));
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
));
1791 else if (expected
->flags
& METHOD_OPTIONAL
)
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
));
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
));
1814 if (expected
->prov
|| actual
->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
));
1820 ok_( file
, line
)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual
->prov
->prov_name
,
1821 get_prov_method_str(actual
->method
));
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
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
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>"
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
);
1873 str
+= wcslen(prov_type
);
1874 str2
= wcschr(str
, L
'(');
1875 lstrcpynW(out_name
, str
, ((str2
- str
)));
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
)
1890 wsprintfW(buf
, L
"%s(parent link):", prov_type
);
1892 wsprintfW(buf
, L
"%s:", prov_type
);
1894 if (!get_provider_desc(prov_desc
, buf
, buf
))
1897 wsprintfW(buf
, L
"%s:", prov_type
);
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
));
1906 todo_wine_if(todo
) ok_(file
, line
)(0, "expected parent link provider %s\n", debugstr_w(prov_type
));
1908 todo_wine_if(todo
) ok_(file
, line
)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type
));
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
;
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:");
1937 str
+= wcslen(L
"providerId:");
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
;
1959 wsprintfW(buf
, L
"%s:Nested ", prov_type
);
1961 wsprintfW(buf
, L
"%s(parent link):Nested ", prov_type
);
1962 str
= wcsstr(prov_desc
, buf
);
1963 /* Check with and without parent-link. */
1971 str2
= wcschr(str
, L
']');
1972 /* We want to include the ']' character, so + 2. */
1973 lstrcpynW(out_desc
, str
, ((str2
- str
) + 2));
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
;
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
++)
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
);
2018 if (IsEqualIID(riid
, &IID_IRawElementProviderSimple
) || IsEqualIID(riid
, &IID_IUnknown
))
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
;
2033 return E_NOINTERFACE
;
2035 IRawElementProviderSimple_AddRef(iface
);
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
);
2063 if (This
->prov_opts
)
2065 *ret_val
= This
->prov_opts
;
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
);
2086 case UIA_ValuePatternId
:
2087 if (This
->value_pattern_data
.is_supported
)
2088 *ret_val
= (IUnknown
*)iface
;
2091 case UIA_LegacyIAccessiblePatternId
:
2092 if (This
->legacy_acc_pattern_data
.is_supported
)
2093 *ret_val
= (IUnknown
*)iface
;
2101 IUnknown_AddRef(*ret_val
);
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
)
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
));
2134 VariantInit(ret_val
);
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
);
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
;
2170 V_VT(ret_val
) = VT_I4
;
2171 V_I4(ret_val
) = uia_i4_prop_val
;
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
;
2183 V_VT(ret_val
) = VT_R8
;
2184 V_R8(ret_val
) = uia_r8_prop_val
;
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
;
2209 V_VT(ret_val
) = VT_BSTR
;
2210 V_BSTR(ret_val
) = SysAllocString(uia_bstr_prop_str
);
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
;
2233 V_VT(ret_val
) = VT_BOOL
;
2234 V_BOOL(ret_val
) = VARIANT_TRUE
;
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();
2247 V_VT(ret_val
) = VT_ARRAY
| VT_I4
;
2248 V_ARRAY(ret_val
) = create_i4_safearray();
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();
2261 V_VT(ret_val
) = VT_ARRAY
| VT_R8
;
2262 V_ARRAY(ret_val
) = create_r8_safearray();
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
;
2274 V_VT(ret_val
) = VT_UNKNOWN
;
2275 V_UNKNOWN(ret_val
) = (IUnknown
*)&Provider_child
.IRawElementProviderSimple_iface
;
2276 IUnknown_AddRef(V_UNKNOWN(ret_val
));
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();
2292 V_VT(ret_val
) = VT_UNKNOWN
| VT_ARRAY
;
2293 V_ARRAY(ret_val
) = create_unk_safearray();
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
);
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
);
2327 return UiaHostProviderFromHwnd(This
->hwnd
, ret_val
);
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
,
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
);
2380 case NavigateDirection_Parent
:
2381 *ret_val
= This
->parent
;
2384 case NavigateDirection_NextSibling
:
2385 *ret_val
= This
->next_sibling
;
2388 case NavigateDirection_PreviousSibling
:
2389 *ret_val
= This
->prev_sibling
;
2392 case NavigateDirection_FirstChild
:
2393 *ret_val
= This
->first_child
;
2396 case NavigateDirection_LastChild
:
2397 *ret_val
= This
->last_child
;
2401 trace("Invalid navigate direction %d\n", direction
);
2406 IRawElementProviderFragment_AddRef(*ret_val
);
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
);
2423 if (This
->runtime_id
[0] || This
->runtime_id
[1])
2428 if (!(sa
= SafeArrayCreateVector(VT_I4
, 0, ARRAY_SIZE(This
->runtime_id
))))
2431 for (idx
= 0; idx
< ARRAY_SIZE(This
->runtime_id
); idx
++)
2432 SafeArrayPutElement(sa
, &idx
, (void *)&This
->runtime_id
[idx
]);
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
;
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
);
2467 if (This
->embedded_frag_roots
&& This
->embedded_frag_roots_count
)
2472 if (!(sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, This
->embedded_frag_roots_count
)))
2475 for (idx
= 0; idx
< This
->embedded_frag_roots_count
; idx
++)
2476 SafeArrayPutElement(sa
, &idx
, (IUnknown
*)This
->embedded_frag_roots
[idx
]);
2484 static HRESULT WINAPI
ProviderFragment_SetFocus(IRawElementProviderFragment
*iface
)
2486 ok(0, "unexpected call\n");
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
);
2502 if (This
->frag_root
)
2504 *ret_val
= This
->frag_root
;
2505 IRawElementProviderFragmentRoot_AddRef(This
->frag_root
);
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
,
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");
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
);
2566 if (Provider
->focus_prov
)
2568 *ret_val
= Provider
->focus_prov
;
2569 IRawElementProviderFragment_AddRef(*ret_val
);
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
,
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
);
2616 if (This
->override_hwnd
== hwnd
)
2618 return IRawElementProviderSimple_QueryInterface(&Provider_override
.IRawElementProviderSimple_iface
,
2619 &IID_IRawElementProviderSimple
, (void **)ret_val
);
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
,
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
);
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
);
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
,
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");
2724 static HRESULT WINAPI
ProviderValuePattern_get_Value(IValueProvider
*iface
, BSTR
*ret_val
)
2726 ok(0, "unexpected call\n");
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
;
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
,
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");
2778 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider
*iface
)
2780 ok(0, "unexpected call\n");
2784 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider
*iface
, LPCWSTR val
)
2786 ok(0, "unexpected call\n");
2790 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider
*iface
,
2791 IAccessible
**out_acc
)
2793 ok(0, "unexpected call\n");
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
;
2805 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider
*iface
, BSTR
*out_name
)
2807 ok(0, "unexpected call\n");
2811 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider
*iface
, BSTR
*out_value
)
2813 ok(0, "unexpected call\n");
2817 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider
*iface
,
2818 BSTR
*out_description
)
2820 ok(0, "unexpected call\n");
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
;
2832 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider
*iface
, DWORD
*out_state
)
2834 ok(0, "unexpected call\n");
2838 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider
*iface
, BSTR
*out_help
)
2840 ok(0, "unexpected call\n");
2844 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_KeyboardShortcut(ILegacyIAccessibleProvider
*iface
,
2845 BSTR
*out_kbd_shortcut
)
2847 ok(0, "unexpected call\n");
2851 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider
*iface
,
2852 SAFEARRAY
**out_selected
)
2854 ok(0, "unexpected call\n");
2858 static HRESULT WINAPI
ProviderLegacyIAccessiblePattern_get_DefaultAction(ILegacyIAccessibleProvider
*iface
,
2859 BSTR
*out_default_action
)
2861 ok(0, "unexpected call\n");
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
},
2898 &Provider_child
.IRawElementProviderFragment_iface
, &Provider_child2
.IRawElementProviderFragment_iface
,
2902 static struct Provider Provider2
=
2904 { &ProviderSimpleVtbl
},
2905 { &ProviderFragmentVtbl
},
2906 { &ProviderFragmentRootVtbl
},
2907 { &ProviderHwndOverrideVtbl
},
2908 { &ProviderAdviseEventsVtbl
},
2909 { &ProviderValuePatternVtbl
},
2910 { &ProviderLegacyIAccessiblePatternVtbl
},
2919 static struct Provider Provider_child
=
2921 { &ProviderSimpleVtbl
},
2922 { &ProviderFragmentVtbl
},
2923 { &ProviderFragmentRootVtbl
},
2924 { &ProviderHwndOverrideVtbl
},
2925 { &ProviderAdviseEventsVtbl
},
2926 { &ProviderValuePatternVtbl
},
2927 { &ProviderLegacyIAccessiblePatternVtbl
},
2930 &Provider
.IRawElementProviderFragment_iface
, &Provider
.IRawElementProviderFragmentRoot_iface
,
2931 NULL
, &Provider_child2
.IRawElementProviderFragment_iface
,
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
},
2947 &Provider
.IRawElementProviderFragment_iface
, &Provider
.IRawElementProviderFragmentRoot_iface
,
2948 &Provider_child
.IRawElementProviderFragment_iface
, 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
},
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
},
2984 ProviderOptions_ClientSideProvider
| ProviderOptions_NonClientAreaProvider
,
2988 static struct Provider Provider_proxy
=
2990 { &ProviderSimpleVtbl
},
2991 { &ProviderFragmentVtbl
},
2992 { &ProviderFragmentRootVtbl
},
2993 { &ProviderHwndOverrideVtbl
},
2994 { &ProviderAdviseEventsVtbl
},
2995 { &ProviderValuePatternVtbl
},
2996 { &ProviderLegacyIAccessiblePatternVtbl
},
3002 ProviderOptions_ClientSideProvider
,
3006 static struct Provider Provider_proxy2
=
3008 { &ProviderSimpleVtbl
},
3009 { &ProviderFragmentVtbl
},
3010 { &ProviderFragmentRootVtbl
},
3011 { &ProviderHwndOverrideVtbl
},
3012 { &ProviderAdviseEventsVtbl
},
3013 { &ProviderValuePatternVtbl
},
3014 { &ProviderLegacyIAccessiblePatternVtbl
},
3020 ProviderOptions_ClientSideProvider
,
3024 static struct Provider Provider_override
=
3026 { &ProviderSimpleVtbl
},
3027 { &ProviderFragmentVtbl
},
3028 { &ProviderFragmentRootVtbl
},
3029 { &ProviderHwndOverrideVtbl
},
3030 { &ProviderAdviseEventsVtbl
},
3031 { &ProviderValuePatternVtbl
},
3032 { &ProviderLegacyIAccessiblePatternVtbl
},
3034 "Provider_override",
3038 ProviderOptions_ServerSideProvider
| ProviderOptions_OverrideProvider
,
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 }, \
3053 "Provider_" # name "", \
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
)
3080 if (lParam
== (DWORD
)OBJID_CLIENT
)
3082 CHECK_EXPECT(winproc_GETOBJECT_CLIENT
);
3084 return LresultFromObject(&IID_IAccessible
, wParam
, (IUnknown
*)acc_client
);
3088 else if (lParam
== UiaRootObjectId
)
3090 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot
);
3092 return UiaReturnRawElementProvider(hwnd
, wParam
, lParam
, prov_root
);
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
)
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
);
3127 return DefWindowProcA(hwnd
, message
, wParam
, lParam
);
3130 static void test_UiaHostProviderFromHwnd(void)
3132 IRawElementProviderSimple
*p
, *p2
;
3133 enum ProviderOptions prov_opt
;
3141 cls
.lpfnWndProc
= test_wnd_proc
;
3144 cls
.hInstance
= GetModuleHandleA(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
);
3167 hr
= UiaHostProviderFromHwnd(hwnd
, &p
);
3168 ok(hr
== S_OK
, "Failed to get host provider, hr %#lx.\n", hr
);
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
));
3190 /* No patterns are implemented on the HWND Host provider. */
3191 for (i
= UIA_InvokePatternId
; i
< (UIA_CustomNavigationPatternId
+ 1); i
++)
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
));
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
;
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
);
3259 static void test_uia_reserved_value_ifaces(void)
3261 IUnknown
*unk_ns
, *unk_ns2
, *unk_ma
, *unk_ma2
;
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
);
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
);
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
)
3352 while(PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
3354 TranslateMessage(&msg
);
3355 DispatchMessageW(&msg
);
3358 CloseHandle(thread
);
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
;
3369 hr
= IAccessible_QueryInterface(acc
, &IID_IServiceProvider
, (void**)&sp
);
3372 IAccessible
*acc2
= NULL
;
3374 hr
= IServiceProvider_QueryService(sp
, &SID_AccFromDAWrapper
, &IID_IAccessible
, (void**)&acc2
);
3375 IServiceProvider_Release(sp
);
3376 if (SUCCEEDED(hr
) && acc2
)
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
;
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");
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
3404 if (acc
&& acc2
&& (acc
!= acc2
) && (acc3
= msaa_acc_da_unwrap(acc2
)))
3406 IAccessible_Release(acc2
);
3409 ok_(__FILE__
, line
)(acc2
== acc
, "acc2 != acc\n");
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
;
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
);
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
;
3450 set_accessible_props(&Accessible
, ROLE_SYSTEM_DOCUMENT
, 0, 0, L
"acc_name", 0, 0, 0, 0);
3451 Accessible
.ow_hwnd
= hwnd
;
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.
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.
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
;
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. */
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
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);
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.
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
);
3616 struct msaa_role_uia_type
{
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
{
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
)
3706 acc
->child_count
= child_count
;
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
;
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");
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
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");
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;
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;
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;
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;
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
,
3905 ILegacyIAccessibleProvider
*accprov
;
3906 IAccessible
*accessible
;
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
;
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
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
);
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
);
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
);
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
);
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
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 };
4374 /* MSAA role to UIA control type test. */
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
;
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
);
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
));
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
);
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
));
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
);
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
);
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
,
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
);
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
)));
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
)));
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
;
4611 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
4613 cls
.lpfnWndProc
= test_wnd_proc
;
4616 cls
.hInstance
= GetModuleHandleA(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
);
4671 /* Skip tests on Win10v1507. */
4672 if (called_winproc_GETOBJECT_CLIENT
)
4674 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
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
));
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
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
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;
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;
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
);
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;
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;
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;
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;
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. */
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
);
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
);
5214 DestroyWindow(hwnd
);
5215 UnregisterClassA("pUiaProviderFromIAccessible class", NULL
);
5216 Accessible
.acc_hwnd
= NULL
;
5217 Accessible
.ow_hwnd
= NULL
;
5220 struct uia_lookup_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
;
5536 const struct uia_lookup_id
*ids
;
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
) },
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
);
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
));
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
},
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 */
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 */
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 */
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 */
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 */
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 */
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
},
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
;
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
);
5746 static void test_uia_node_from_prov_com_threading(void)
5752 /* Test ProviderOptions_UseComThreading. */
5753 Provider
.hwnd
= 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.
5765 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
5766 UiaNodeRelease(node
);
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
)
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;
5796 static void test_UiaNodeFromProvider(void)
5806 cls
.lpfnWndProc
= test_wnd_proc
;
5809 cls
.hInstance
= GetModuleHandleA(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
);
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
);
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
;
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
);
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
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
);
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
);
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
);
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
);
6021 DestroyWindow(hwnd
);
6022 UnregisterClassA("UiaNodeFromProvider class", 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
},
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
},
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
},
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
},
6077 static const struct prov_method_sequence get_pattern_prop_seq
[] = {
6078 { &Provider
, PROV_GET_PATTERN_PROV
},
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
},
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
},
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
},
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
},
6130 static const struct prov_method_sequence get_empty_bounding_rect_seq
[] = {
6131 { &Provider_child
, FRAG_GET_BOUNDING_RECT
},
6135 static void set_uia_rect(struct UiaRect
*rect
, double left
, double top
, double width
, double height
)
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
;
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
))
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
)
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
);
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
));
6222 ok(check_variant_bool(v
, TRUE
), "Unexpected BOOL %#x\n", V_BOOL(v
));
6223 ok_method_sequence(get_prop_seq
, NULL
);
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
));
6232 ok(V_I4(v
) == uia_i4_prop_val
, "Unexpected I4 %#lx\n", V_I4(v
));
6233 ok_method_sequence(get_prop_seq
, NULL
);
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
++)
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
);
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
);
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
++)
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
);
6267 case UIAutomationType_Element
:
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
);
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
);
6290 ok(V_VT(v
) == VT_I8
, "Unexpected VT %d\n", V_VT(v
));
6291 tmp_node
= (HUIANODE
)V_I8(v
);
6293 ok(V_VT(v
) == VT_I4
, "Unexpected VT %d\n", V_VT(v
));
6294 tmp_node
= (HUIANODE
)V_I4(v
);
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
);
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
);
6316 IUIAutomationElementArray
*elem_arr
= NULL
;
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");
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
;
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
);
6352 IUIAutomationElementArray_Release(elem_arr
);
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
))
6360 for (idx
= 0; idx
< ARRAY_SIZE(uia_unk_arr_prop_val
); idx
++)
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
);
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
);
6392 struct uia_element_property
{
6393 const GUID
*prop_guid
;
6394 enum UIAutomationType type
;
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
;
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
;
6486 prop_id
= UiaLookupId(AutomationIdentifierType_Property
, elem_prop
->prop_guid
);
6489 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop
->prop_guid
));
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
);
6508 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", 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
));
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
);
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
);
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
);
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
);
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
);
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");
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
);
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
));
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
);
6623 IUnknown_Release(unk_ns
);
6627 static const struct prov_method_sequence get_runtime_id1
[] = {
6628 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
6632 static const struct prov_method_sequence get_runtime_id2
[] = {
6633 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
6634 { &Provider_child
, FRAG_GET_FRAGMENT_ROOT
},
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
},
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
},
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
},
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
;
6688 cls
.lpfnWndProc
= test_wnd_proc
;
6691 cls
.hInstance
= GetModuleHandleA(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
);
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
));
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;
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
++)
6823 Provider
.prov_opts
= root_prov_opts
[i
];
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
);
6836 ok(rt_id
[2] != tmp
, "Expected different runtime id value from previous\n");
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;
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
);
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
);
6889 static const struct prov_method_sequence node_from_var_seq
[] = {
6890 NODE_CREATE_SEQ(&Provider
),
6894 static void test_UiaHUiaNodeFromVariant(void)
6896 HUIANODE node
, node2
;
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;
6909 hr
= UiaHUiaNodeFromVariant(&v
, &node
);
6910 ok(hr
== E_INVALIDARG
, "Unexpected hr %#lx.\n", hr
);
6911 ok(!node
, "node != NULL\n");
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
);
6931 IUnknown_Release((IUnknown
*)node
);
6934 node2
= (void *)0xdeadbeef;
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;
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");
6948 node2
= (void *)0xdeadbeef;
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;
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");
6963 UiaNodeRelease(node
);
6966 static const struct prov_method_sequence node_from_hwnd1
[] = {
6967 { &Provider
, PROV_GET_PROVIDER_OPTIONS
},
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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+. */
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
},
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
},
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
},
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
},
7168 static void test_UiaNodeFromHandle_client_proc(void)
7170 APTTYPEQUALIFIER apt_qualifier
;
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
);
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
);
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
);
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
;
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
);
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
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
);
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
);
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
7340 if (Provider_child
.ref
!= 1)
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
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
);
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)
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)
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)
7409 ok(Provider
.ref
== 1, "Unexpected refcnt %ld\n", Provider
.ref
);
7411 if (!pUiaDisconnectProvider
)
7413 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
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
);
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
);
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
);
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");
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
;
7572 cls
.lpfnWndProc
= test_wnd_proc
;
7575 cls
.hInstance
= GetModuleHandleA(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. */
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
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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
);
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"))
7798 hr
= CoGetApartmentType(&apt_type
, &apt_qualifier
);
7800 todo_wine
ok(hr
== S_OK
|| broken(hr
== CO_E_NOTINITIALIZED
), "Unexpected hr %#lx\n", 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
)
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
)
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
));
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");
7857 DestroyWindow(hwnd
);
7858 UnregisterClassA("UiaNodeFromHandle class", 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 */
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 */
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 */
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 */
7918 static const struct prov_method_sequence reg_prov_cb5
[] = {
7919 { &Provider_override
, PROV_GET_PROPERTY_VALUE
, METHOD_TODO
}, /* UIA_ControlTypePropertyId */
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 */
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 */
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 */
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. */
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
},
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 */
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 */
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 */
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
;
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
;
8093 elprov
= base_hwnd_prov
;
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
;
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
;
8128 sa
= SafeArrayCreateVector(VT_UNKNOWN
, 0, 1);
8130 SafeArrayPutElement(sa
, &idx
, (void *)elprov
);
8138 static void test_UiaRegisterProviderCallback(void)
8147 cls
.lpfnWndProc
= test_wnd_proc
;
8150 cls
.hInstance
= GetModuleHandleA(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
);
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
);
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
);
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
);
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.
8345 * Nonclient 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
);
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
);
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
);
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
;
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
;
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
{
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
];
8592 static void init_node_provider_desc(struct node_provider_desc
*desc
, DWORD pid
, HWND hwnd
)
8594 memset(desc
, 0, sizeof(*desc
));
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
;
8609 static void add_provider_desc(struct node_provider_desc
*desc
, const WCHAR
*prov_type
, const WCHAR
*prov_name
,
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
)
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
])
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
);
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
)
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
);
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
);
8695 UiaNodeRelease(node
);
8699 static const struct prov_method_sequence cache_req_seq1
[] = {
8700 { &Provider
, PROV_GET_PROPERTY_VALUE
}, /* UIA_ProviderDescriptionPropertyId. */
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 */
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. */
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. */
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 */
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 */
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. */
8757 static const struct prov_method_sequence cache_req_seq8
[] = {
8758 NODE_CREATE_SEQ(&Provider_child
),
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 */
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. */
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];
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
);
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
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
);
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(¬_cond
, (struct UiaCondition
*)&UiaFalseCondition
);
9054 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_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(¬_cond
, (struct UiaCondition
*)&UiaTrueCondition
);
9074 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_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
);
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
);
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;
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
);
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;
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
);
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. */
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;
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
));
9265 for (i
= 0; i
< ARRAY_SIZE(prop_ids
); 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.
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;
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
));
9310 for (i
= 0; i
< ARRAY_SIZE(prop_ids
); 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
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
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
);
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
);
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
;
9677 prov
->parent
= &parent
->IRawElementProviderFragment_iface
;
9679 prov
->frag_root
= &frag_root
->IRawElementProviderFragmentRoot_iface
;
9681 prov
->prev_sibling
= &prev_sibling
->IRawElementProviderFragment_iface
;
9683 prov
->next_sibling
= &next_sibling
->IRawElementProviderFragment_iface
;
9685 prov
->first_child
= &first_child
->IRawElementProviderFragment_iface
;
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
;
9705 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
9707 cls
.lpfnWndProc
= test_wnd_proc
;
9710 cls
.hInstance
= GetModuleHandleA(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
,
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
,
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
);
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
);
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
);
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
);
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
);
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
);
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
;
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
;
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
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
;
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
);
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
;
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
;
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
);
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
;
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
;
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
);
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
;
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
;
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
;
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
);
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
++)
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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 */
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
;
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
);
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;
10799 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10801 for (i
= 0; i
< exp_elems
[0]; 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;
10834 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10836 for (i
= 0; i
< exp_elems
[0]; 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;
10869 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10871 for (i
= 0; i
< exp_elems
[0]; 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;
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
++)
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;
10947 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10949 for (i
= 0; i
< exp_elems
[0]; 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;
10982 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
10984 for (i
= 0; i
< exp_elems
[0]; 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;
11041 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
11043 for (i
= 0; i
< exp_elems
[0]; 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;
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
++)
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;
11159 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
11161 for (i
= 0; i
< exp_elems
[0]; 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
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;
11211 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
11213 for (i
= 0; i
< exp_elems
[0]; 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
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;
11258 test_cache_req_sa(out_req
, exp_lbound
, exp_elems
, exp_node_desc
);
11260 for (i
= 0; i
< exp_elems
[0]; 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
);
11280 struct marshal_thread_data
{
11282 const GUID
*iface_iid
;
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
;
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");
11313 ok_(data
->file
, data
->line
)(unk
== unk2
, "unk != unk2\n");
11315 IUnknown_Release(proxy_iface
);
11316 IUnknown_Release(unk
);
11317 IUnknown_Release(unk2
);
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
,
11328 struct marshal_thread_data data
= { NULL
, iid
, expect_proxy
, file
, line
};
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
)
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
;
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
);
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
);
11423 check_node_provider_desc(V_BSTR(&v
), L
"Main", L
"Provider", TRUE
);
11426 ok_method_sequence(node_from_hwnd2
, "create_test_element");
11427 UiaRegisterProviderCallback(NULL
);
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
;
11439 element
= create_test_element_from_hwnd(uia_iface
, hwnd
, FALSE
);
11440 hr
= IUIAutomationElement_QueryInterface(element
, &IID_IUIAutomationElement2
, (void **)&element_2
);
11443 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
11444 ok(!!element_2
, "element_2 == NULL\n");
11445 IUIAutomationElement2_Release(element_2
);
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
);
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
;
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
);
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
;
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
));
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
);
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
));
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");
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
++)
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
);
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. */
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.
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
);
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");
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");
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
);
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
));
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
);
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
;
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.
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
;
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
)
11789 if (IsEqualIID(riid
, &IID_IUnknown
))
11792 return E_NOINTERFACE
;
11797 static ULONG WINAPI
Object_AddRef(IUnknown
*iface
)
11802 static ULONG WINAPI
Object_Release(IUnknown
*iface
)
11807 static IUnknownVtbl ObjectVtbl
= {
11808 Object_QueryInterface
,
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
;
11829 hr
= IUIAutomation_CreateTrueCondition(uia_iface
, NULL
);
11830 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
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
);
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
);
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
);
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;
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;
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. */
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
);
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");
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
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. */
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 **)¬_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
);
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.
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");
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");
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");
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
);
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
);
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");
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
);
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 **)¬_cond
);
12097 IUIAutomationCondition_Release(cond
);
12098 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12099 ok(!!not_cond
, "not_cond == NULL\n");
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
);
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
));
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:
12132 hr
= IUIAutomation_get_RawViewCondition(uia_iface
, NULL
);
12133 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
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");
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
;
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.
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");
12180 hr
= IUIAutomationCacheRequest_get_TreeScope(cache_req
, NULL
);
12181 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
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. */
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
);
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.
12226 hr
= IUIAutomationCacheRequest_get_TreeFilter(cache_req
, NULL
);
12227 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
12230 hr
= IUIAutomationCacheRequest_put_TreeFilter(cache_req
, NULL
);
12231 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
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. */
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 **)¬_cond
);
12244 IUIAutomationCondition_Release(cond
);
12245 ok(hr
== S_OK
, "Unexpected hr %#lx.\n", hr
);
12246 ok(!!not_cond
, "not_cond == NULL\n");
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
);
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
));
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. */
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
);
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
);
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
),
12333 static const struct prov_method_sequence get_cached_prop_val_seq
[] = {
12334 { &Provider_child
, FRAG_GET_RUNTIME_ID
},
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 */
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 */
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
;
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
);
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");
12399 * Passing in an invalid COM interface for IUIAutomationCacheRequest will
12400 * cause an access violation on Windows.
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.
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
));
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
));
12438 IUIAutomationElement_Release(element2
);
12440 /* RuntimeId is now set. */
12441 Provider_child
.runtime_id
[0] = Provider_child
.runtime_id
[1] = 0xdeadbeef;
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
));
12453 IUIAutomationElement_Release(element2
);
12456 * Add UIA_IsControlElementPropertyId to the list of cached property
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;
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
));
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
));
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
);
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
);
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
));
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
));
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");
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
);
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");
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
);
12563 IUIAutomationElementArray_Release(elem_arr
);
12564 IUIAutomationCacheRequest_Release(cache_req
);
12567 * Reference isn't released until the element holding the cache is
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
),
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 */
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 */
12654 struct exp_elem_desc
{
12655 struct Provider
*elem_prov
;
12656 struct node_provider_desc prov_desc
;
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
)
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
;
12689 ok_(file
, line
)(desc
->elem_prov
->ref
== desc
->exp_refcnt
, "elem[%d]: Unexpected refcnt %ld\n", i
, exp_elems
[i
].elem_prov
->ref
);
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
);
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
;
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.
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");
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
;
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.
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. */
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
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
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
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
);
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
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. */
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. */
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
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
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
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
);
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
);
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
),
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
},
13138 static const struct prov_method_sequence treewalker_seq3
[] = {
13139 { &Provider
, FRAG_NAVIGATE
}, /* NavigateDirection_LastChild */
13140 NODE_CREATE_SEQ(&Provider_child2
),
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
},
13151 static const struct prov_method_sequence treewalker_seq5
[] = {
13152 { &Provider_child
, FRAG_NAVIGATE
}, /* NavigateDirection_NextSibling */
13153 NODE_CREATE_SEQ(&Provider_child2
),
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
},
13164 static const struct prov_method_sequence treewalker_seq7
[] = {
13165 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_PreviousSibling */
13166 NODE_CREATE_SEQ(&Provider_child
),
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
},
13177 static const struct prov_method_sequence treewalker_seq9
[] = {
13178 { &Provider_child2
, FRAG_NAVIGATE
}, /* NavigateDirection_Parent */
13179 NODE_CREATE_SEQ(&Provider
),
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
},
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
;
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. */
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
);
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. */
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
);
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. */
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
);
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. */
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
);
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. */
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
);
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. */
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
);
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
)
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
;
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
);
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
,
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
;
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
);
13450 hr
= IUIAutomation_GetFocusedElementBuildCache(uia_iface
, cache_req
, &element
);
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
);
13469 IUIAutomationElement_Release(element
);
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
;
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
);
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
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
;
13673 DWORD last_call_tid
;
13676 static void set_com_event_data(struct node_provider_desc
*exp_node_desc
)
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
;
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
)
13706 CHECK_EXPECT(uia_com_event_callback
);
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
);
13714 ComEventData
.last_call_tid
= GetCurrentThreadId();
13718 * IUIAutomationEventHandler.
13720 static struct AutomationEventHandler
13722 IUIAutomationEventHandler IUIAutomationEventHandler_iface
;
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
)
13734 if (IsEqualIID(riid
, &IID_IUIAutomationEventHandler
) || IsEqualIID(riid
, &IID_IUnknown
))
13737 return E_NOINTERFACE
;
13739 IUIAutomationEventHandler_AddRef(iface
);
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
);
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
;
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
)
13796 if (IsEqualIID(riid
, &IID_IUIAutomationFocusChangedEventHandler
) || IsEqualIID(riid
, &IID_IUnknown
))
13799 return E_NOINTERFACE
;
13801 IUIAutomationFocusChangedEventHandler_AddRef(iface
);
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
);
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
;
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
);
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
);
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
;
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
,
13897 ok(hr
== E_POINTER
, "Unexpected hr %#lx.\n", hr
);
13900 * Passing in a NULL element to this method results in an access violation
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
)
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
);
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");
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
;
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
;
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
{
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
;
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
,
14182 if ((com_classes
[i
].clsid
== &CLSID_CUIAutomation8
) && (hr
== REGDB_E_CLASSNOTREG
))
14184 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
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
));
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
);
14204 hr
= CoCreateInstance(&CLSID_CUIAutomation8
, NULL
, CLSCTX_INPROC_SERVER
, &IID_IUIAutomation
,
14205 (void **)&uia_iface
);
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
);
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
},
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 };
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
));
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
)));
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
)));
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
);
14324 winetest_pop_context();
14330 PARENT_HWND_DESKTOP
,
14333 struct uia_hwnd_control_type_test
{
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
;
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
;
14377 SET_EXPECT(winproc_GETOBJECT_UiaRoot
);
14378 SET_EXPECT(winproc_GETOBJECT_CLIENT
);
14379 prov_root
= &main
->IRawElementProviderSimple_iface
;
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
);
14395 /* Called while trying to get override provider. */
14396 todo_wine
CHECK_CALLED(winproc_GETOBJECT_UiaRoot
);
14397 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot
);
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
,
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 };
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
)
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");
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
));
14447 UiaNodeRelease(tmp_node
);
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
;
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
);
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
);
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
));
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
);
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
);
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
);
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
];
14549 if (test
->parent_hwnd_type
== PARENT_HWND_HWND
)
14551 else if (test
->parent_hwnd_type
== PARENT_HWND_DESKTOP
)
14552 parent
= GetDesktopWindow();
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);
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);
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
));
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
,
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
);
14647 * Test default ProviderType_Proxy clientside provider. Provider will be
14648 * the HWND provider for this node, and Accessible will be the main
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
);
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
));
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
);
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
));
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
));
14726 UiaNodeRelease(node
);
14727 DestroyWindow(hwnd2
);
14729 set_accessible_props(&Accessible
, 0, 0, 0, NULL
, 0, 0, 0, 0);
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
);
14743 static void test_UiaGetRootNode(void)
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
);
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
,
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
);
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
;
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");
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;
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
;
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(¬_cond
, (struct UiaCondition
*)&prop_cond
);
14890 cache_prop
= UIA_RuntimeIdPropertyId
;
14891 set_cache_request(&cache_req
, (struct UiaCondition
*)¬_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
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
);
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+. */
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
},
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
},
15022 static const struct prov_method_sequence event_seq4
[] = {
15023 { &Provider
, ADVISE_EVENTS_EVENT_REMOVED
},
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
},
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
},
15047 static struct EventData
{
15048 LONG exp_lbound
[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
;
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
;
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
;
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");
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
);
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
,
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
))
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
;
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
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
);
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
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
;
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);
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
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
);
15370 struct event_test_thread_data
{
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
;
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
);
15395 static void test_UiaAddEvent_args(HUIANODE node
)
15397 struct UiaCacheRequest cache_req
;
15401 set_cache_request(&cache_req
, (struct UiaCondition
*)&UiaTrueCondition
, TreeScope_Element
, NULL
, 0, NULL
, 0,
15402 AutomationElementMode_Full
);
15405 hr
= UiaAddEvent(NULL
, UIA_AutomationFocusChangedEventId
, uia_event_callback
, TreeScope_Element
, NULL
, 0, &cache_req
,
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
,
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
,
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
,
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. */
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
)
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)
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
;
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
);
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.
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
,
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.
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
,
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
,
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
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
);
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
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
)
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
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
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
);
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
;
15887 while (PeekMessageW(&msg
, 0, 0, 0, PM_REMOVE
))
15889 switch (msg
.message
)
15891 case WM_UIA_TEST_RESET_EVENT_PROVIDERS
:
15895 for (i
= 0; i
< ARRAY_SIZE(event_test_provs
); i
++)
15896 initialize_provider(event_test_provs
[i
], ProviderOptions_ServerSideProvider
, NULL
, FALSE
);
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
))))
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
);
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
);
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
))))
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
);
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
;
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
},
15969 static void test_UiaHasServerSideProvider(void)
15974 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
15975 hwnd
= create_test_hwnd("UiaHasServerSideProvider test class");
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. */
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
);
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
;
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
)
16054 pImmDisableIME
= NULL
;
16055 FreeLibrary(hModuleImm32
);
16058 pUiaDisconnectProvider
= (void *)GetProcAddress(uia_dll
, "UiaDisconnectProvider");
16060 argc
= winetest_get_mainargs(&argv
);
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
);
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();
16088 test_CUIAutomation();
16089 test_default_clientside_providers();
16090 test_UiaGetRootNode();
16091 test_UiaNodeFromFocus();
16092 test_UiaAddEvent(argv
[0]);
16093 test_UiaHasServerSideProvider();
16096 pUiaProviderFromIAccessible
= (void *)GetProcAddress(uia_dll
, "UiaProviderFromIAccessible");
16097 if (pUiaProviderFromIAccessible
)
16098 test_UiaProviderFromIAccessible();
16100 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
16102 FreeLibrary(uia_dll
);