ReactOS 0.4.17-dev-116-ga4b6fe9
uiautomation.c
Go to the documentation of this file.
1/*
2 * UI Automation tests
3 *
4 * Copyright 2019 Nikolay Sivov for CodeWeavers
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20
21#define COBJMACROS
22
23#include <oleauto.h>
24#include <assert.h>
25#include "windows.h"
26#include "initguid.h"
27#include "uiautomation.h"
28#include "ocidl.h"
29#include "wine/iaccessible2.h"
30
31#include "wine/test.h"
32
33static HRESULT (WINAPI *pUiaProviderFromIAccessible)(IAccessible *, LONG, DWORD, IRawElementProviderSimple **);
34static HRESULT (WINAPI *pUiaDisconnectProvider)(IRawElementProviderSimple *);
35
37 int id;
38 const char *str;
39};
40
41static const struct str_id_pair uia_prop_id_strs[] = {
42 { UIA_RuntimeIdPropertyId, "UIA_RuntimeIdPropertyId", },
43 { UIA_BoundingRectanglePropertyId, "UIA_BoundingRectanglePropertyId", },
44 { UIA_ProcessIdPropertyId, "UIA_ProcessIdPropertyId", },
45 { UIA_ControlTypePropertyId, "UIA_ControlTypePropertyId", },
46 { UIA_LocalizedControlTypePropertyId, "UIA_LocalizedControlTypePropertyId", },
47 { UIA_NamePropertyId, "UIA_NamePropertyId", },
48 { UIA_AcceleratorKeyPropertyId, "UIA_AcceleratorKeyPropertyId", },
49 { UIA_AccessKeyPropertyId, "UIA_AccessKeyPropertyId", },
50 { UIA_HasKeyboardFocusPropertyId, "UIA_HasKeyboardFocusPropertyId", },
51 { UIA_IsKeyboardFocusablePropertyId, "UIA_IsKeyboardFocusablePropertyId", },
52 { UIA_IsEnabledPropertyId, "UIA_IsEnabledPropertyId", },
53 { UIA_AutomationIdPropertyId, "UIA_AutomationIdPropertyId", },
54 { UIA_ClassNamePropertyId, "UIA_ClassNamePropertyId", },
55 { UIA_HelpTextPropertyId, "UIA_HelpTextPropertyId", },
56 { UIA_ClickablePointPropertyId, "UIA_ClickablePointPropertyId", },
57 { UIA_CulturePropertyId, "UIA_CulturePropertyId", },
58 { UIA_IsControlElementPropertyId, "UIA_IsControlElementPropertyId", },
59 { UIA_IsContentElementPropertyId, "UIA_IsContentElementPropertyId", },
60 { UIA_LabeledByPropertyId, "UIA_LabeledByPropertyId", },
61 { UIA_IsPasswordPropertyId, "UIA_IsPasswordPropertyId", },
62 { UIA_NativeWindowHandlePropertyId, "UIA_NativeWindowHandlePropertyId", },
63 { UIA_ItemTypePropertyId, "UIA_ItemTypePropertyId", },
64 { UIA_IsOffscreenPropertyId, "UIA_IsOffscreenPropertyId", },
65 { UIA_OrientationPropertyId, "UIA_OrientationPropertyId", },
66 { UIA_FrameworkIdPropertyId, "UIA_FrameworkIdPropertyId", },
67 { UIA_IsRequiredForFormPropertyId, "UIA_IsRequiredForFormPropertyId", },
68 { UIA_ItemStatusPropertyId, "UIA_ItemStatusPropertyId", },
69 { UIA_IsDockPatternAvailablePropertyId, "UIA_IsDockPatternAvailablePropertyId", },
70 { UIA_IsExpandCollapsePatternAvailablePropertyId, "UIA_IsExpandCollapsePatternAvailablePropertyId", },
71 { UIA_IsGridItemPatternAvailablePropertyId, "UIA_IsGridItemPatternAvailablePropertyId", },
72 { UIA_IsGridPatternAvailablePropertyId, "UIA_IsGridPatternAvailablePropertyId", },
73 { UIA_IsInvokePatternAvailablePropertyId, "UIA_IsInvokePatternAvailablePropertyId", },
74 { UIA_IsMultipleViewPatternAvailablePropertyId, "UIA_IsMultipleViewPatternAvailablePropertyId", },
75 { UIA_IsRangeValuePatternAvailablePropertyId, "UIA_IsRangeValuePatternAvailablePropertyId", },
76 { UIA_IsScrollPatternAvailablePropertyId, "UIA_IsScrollPatternAvailablePropertyId", },
77 { UIA_IsScrollItemPatternAvailablePropertyId, "UIA_IsScrollItemPatternAvailablePropertyId", },
78 { UIA_IsSelectionItemPatternAvailablePropertyId, "UIA_IsSelectionItemPatternAvailablePropertyId", },
79 { UIA_IsSelectionPatternAvailablePropertyId, "UIA_IsSelectionPatternAvailablePropertyId", },
80 { UIA_IsTablePatternAvailablePropertyId, "UIA_IsTablePatternAvailablePropertyId", },
81 { UIA_IsTableItemPatternAvailablePropertyId, "UIA_IsTableItemPatternAvailablePropertyId", },
82 { UIA_IsTextPatternAvailablePropertyId, "UIA_IsTextPatternAvailablePropertyId", },
83 { UIA_IsTogglePatternAvailablePropertyId, "UIA_IsTogglePatternAvailablePropertyId", },
84 { UIA_IsTransformPatternAvailablePropertyId, "UIA_IsTransformPatternAvailablePropertyId", },
85 { UIA_IsValuePatternAvailablePropertyId, "UIA_IsValuePatternAvailablePropertyId", },
86 { UIA_IsWindowPatternAvailablePropertyId, "UIA_IsWindowPatternAvailablePropertyId", },
87 { UIA_ValueValuePropertyId, "UIA_ValueValuePropertyId", },
88 { UIA_ValueIsReadOnlyPropertyId, "UIA_ValueIsReadOnlyPropertyId", },
89 { UIA_RangeValueValuePropertyId, "UIA_RangeValueValuePropertyId", },
90 { UIA_RangeValueIsReadOnlyPropertyId, "UIA_RangeValueIsReadOnlyPropertyId", },
91 { UIA_RangeValueMinimumPropertyId, "UIA_RangeValueMinimumPropertyId", },
92 { UIA_RangeValueMaximumPropertyId, "UIA_RangeValueMaximumPropertyId", },
93 { UIA_RangeValueLargeChangePropertyId, "UIA_RangeValueLargeChangePropertyId", },
94 { UIA_RangeValueSmallChangePropertyId, "UIA_RangeValueSmallChangePropertyId", },
95 { UIA_ScrollHorizontalScrollPercentPropertyId, "UIA_ScrollHorizontalScrollPercentPropertyId", },
96 { UIA_ScrollHorizontalViewSizePropertyId, "UIA_ScrollHorizontalViewSizePropertyId", },
97 { UIA_ScrollVerticalScrollPercentPropertyId, "UIA_ScrollVerticalScrollPercentPropertyId", },
98 { UIA_ScrollVerticalViewSizePropertyId, "UIA_ScrollVerticalViewSizePropertyId", },
99 { UIA_ScrollHorizontallyScrollablePropertyId, "UIA_ScrollHorizontallyScrollablePropertyId", },
100 { UIA_ScrollVerticallyScrollablePropertyId, "UIA_ScrollVerticallyScrollablePropertyId", },
101 { UIA_SelectionSelectionPropertyId, "UIA_SelectionSelectionPropertyId", },
102 { UIA_SelectionCanSelectMultiplePropertyId, "UIA_SelectionCanSelectMultiplePropertyId", },
103 { UIA_SelectionIsSelectionRequiredPropertyId, "UIA_SelectionIsSelectionRequiredPropertyId", },
104 { UIA_GridRowCountPropertyId, "UIA_GridRowCountPropertyId", },
105 { UIA_GridColumnCountPropertyId, "UIA_GridColumnCountPropertyId", },
106 { UIA_GridItemRowPropertyId, "UIA_GridItemRowPropertyId", },
107 { UIA_GridItemColumnPropertyId, "UIA_GridItemColumnPropertyId", },
108 { UIA_GridItemRowSpanPropertyId, "UIA_GridItemRowSpanPropertyId", },
109 { UIA_GridItemColumnSpanPropertyId, "UIA_GridItemColumnSpanPropertyId", },
110 { UIA_GridItemContainingGridPropertyId, "UIA_GridItemContainingGridPropertyId", },
111 { UIA_DockDockPositionPropertyId, "UIA_DockDockPositionPropertyId", },
112 { UIA_ExpandCollapseExpandCollapseStatePropertyId, "UIA_ExpandCollapseExpandCollapseStatePropertyId", },
113 { UIA_MultipleViewCurrentViewPropertyId, "UIA_MultipleViewCurrentViewPropertyId", },
114 { UIA_MultipleViewSupportedViewsPropertyId, "UIA_MultipleViewSupportedViewsPropertyId", },
115 { UIA_WindowCanMaximizePropertyId, "UIA_WindowCanMaximizePropertyId", },
116 { UIA_WindowCanMinimizePropertyId, "UIA_WindowCanMinimizePropertyId", },
117 { UIA_WindowWindowVisualStatePropertyId, "UIA_WindowWindowVisualStatePropertyId", },
118 { UIA_WindowWindowInteractionStatePropertyId, "UIA_WindowWindowInteractionStatePropertyId", },
119 { UIA_WindowIsModalPropertyId, "UIA_WindowIsModalPropertyId", },
120 { UIA_WindowIsTopmostPropertyId, "UIA_WindowIsTopmostPropertyId", },
121 { UIA_SelectionItemIsSelectedPropertyId, "UIA_SelectionItemIsSelectedPropertyId", },
122 { UIA_SelectionItemSelectionContainerPropertyId, "UIA_SelectionItemSelectionContainerPropertyId", },
123 { UIA_TableRowHeadersPropertyId, "UIA_TableRowHeadersPropertyId", },
124 { UIA_TableColumnHeadersPropertyId, "UIA_TableColumnHeadersPropertyId", },
125 { UIA_TableRowOrColumnMajorPropertyId, "UIA_TableRowOrColumnMajorPropertyId", },
126 { UIA_TableItemRowHeaderItemsPropertyId, "UIA_TableItemRowHeaderItemsPropertyId", },
127 { UIA_TableItemColumnHeaderItemsPropertyId, "UIA_TableItemColumnHeaderItemsPropertyId", },
128 { UIA_ToggleToggleStatePropertyId, "UIA_ToggleToggleStatePropertyId", },
129 { UIA_TransformCanMovePropertyId, "UIA_TransformCanMovePropertyId", },
130 { UIA_TransformCanResizePropertyId, "UIA_TransformCanResizePropertyId", },
131 { UIA_TransformCanRotatePropertyId, "UIA_TransformCanRotatePropertyId", },
132 { UIA_IsLegacyIAccessiblePatternAvailablePropertyId, "UIA_IsLegacyIAccessiblePatternAvailablePropertyId", },
133 { UIA_LegacyIAccessibleChildIdPropertyId, "UIA_LegacyIAccessibleChildIdPropertyId", },
134 { UIA_LegacyIAccessibleNamePropertyId, "UIA_LegacyIAccessibleNamePropertyId", },
135 { UIA_LegacyIAccessibleValuePropertyId, "UIA_LegacyIAccessibleValuePropertyId", },
136 { UIA_LegacyIAccessibleDescriptionPropertyId, "UIA_LegacyIAccessibleDescriptionPropertyId", },
137 { UIA_LegacyIAccessibleRolePropertyId, "UIA_LegacyIAccessibleRolePropertyId", },
138 { UIA_LegacyIAccessibleStatePropertyId, "UIA_LegacyIAccessibleStatePropertyId", },
139 { UIA_LegacyIAccessibleHelpPropertyId, "UIA_LegacyIAccessibleHelpPropertyId", },
140 { UIA_LegacyIAccessibleKeyboardShortcutPropertyId, "UIA_LegacyIAccessibleKeyboardShortcutPropertyId", },
141 { UIA_LegacyIAccessibleSelectionPropertyId, "UIA_LegacyIAccessibleSelectionPropertyId", },
142 { UIA_LegacyIAccessibleDefaultActionPropertyId, "UIA_LegacyIAccessibleDefaultActionPropertyId", },
143 { UIA_AriaRolePropertyId, "UIA_AriaRolePropertyId", },
144 { UIA_AriaPropertiesPropertyId, "UIA_AriaPropertiesPropertyId", },
145 { UIA_IsDataValidForFormPropertyId, "UIA_IsDataValidForFormPropertyId", },
146 { UIA_ControllerForPropertyId, "UIA_ControllerForPropertyId", },
147 { UIA_DescribedByPropertyId, "UIA_DescribedByPropertyId", },
148 { UIA_FlowsToPropertyId, "UIA_FlowsToPropertyId", },
149 { UIA_ProviderDescriptionPropertyId, "UIA_ProviderDescriptionPropertyId", },
150 { UIA_IsItemContainerPatternAvailablePropertyId, "UIA_IsItemContainerPatternAvailablePropertyId", },
151 { UIA_IsVirtualizedItemPatternAvailablePropertyId, "UIA_IsVirtualizedItemPatternAvailablePropertyId", },
152 { UIA_IsSynchronizedInputPatternAvailablePropertyId, "UIA_IsSynchronizedInputPatternAvailablePropertyId", },
153 { UIA_OptimizeForVisualContentPropertyId, "UIA_OptimizeForVisualContentPropertyId", },
154 { UIA_IsObjectModelPatternAvailablePropertyId, "UIA_IsObjectModelPatternAvailablePropertyId", },
155 { UIA_AnnotationAnnotationTypeIdPropertyId, "UIA_AnnotationAnnotationTypeIdPropertyId", },
156 { UIA_AnnotationAnnotationTypeNamePropertyId, "UIA_AnnotationAnnotationTypeNamePropertyId", },
157 { UIA_AnnotationAuthorPropertyId, "UIA_AnnotationAuthorPropertyId", },
158 { UIA_AnnotationDateTimePropertyId, "UIA_AnnotationDateTimePropertyId", },
159 { UIA_AnnotationTargetPropertyId, "UIA_AnnotationTargetPropertyId", },
160 { UIA_IsAnnotationPatternAvailablePropertyId, "UIA_IsAnnotationPatternAvailablePropertyId", },
161 { UIA_IsTextPattern2AvailablePropertyId, "UIA_IsTextPattern2AvailablePropertyId", },
162 { UIA_StylesStyleIdPropertyId, "UIA_StylesStyleIdPropertyId", },
163 { UIA_StylesStyleNamePropertyId, "UIA_StylesStyleNamePropertyId", },
164 { UIA_StylesFillColorPropertyId, "UIA_StylesFillColorPropertyId", },
165 { UIA_StylesFillPatternStylePropertyId, "UIA_StylesFillPatternStylePropertyId", },
166 { UIA_StylesShapePropertyId, "UIA_StylesShapePropertyId", },
167 { UIA_StylesFillPatternColorPropertyId, "UIA_StylesFillPatternColorPropertyId", },
168 { UIA_StylesExtendedPropertiesPropertyId, "UIA_StylesExtendedPropertiesPropertyId", },
169 { UIA_IsStylesPatternAvailablePropertyId, "UIA_IsStylesPatternAvailablePropertyId", },
170 { UIA_IsSpreadsheetPatternAvailablePropertyId, "UIA_IsSpreadsheetPatternAvailablePropertyId", },
171 { UIA_SpreadsheetItemFormulaPropertyId, "UIA_SpreadsheetItemFormulaPropertyId", },
172 { UIA_SpreadsheetItemAnnotationObjectsPropertyId, "UIA_SpreadsheetItemAnnotationObjectsPropertyId", },
173 { UIA_SpreadsheetItemAnnotationTypesPropertyId, "UIA_SpreadsheetItemAnnotationTypesPropertyId", },
174 { UIA_IsSpreadsheetItemPatternAvailablePropertyId, "UIA_IsSpreadsheetItemPatternAvailablePropertyId", },
175 { UIA_Transform2CanZoomPropertyId, "UIA_Transform2CanZoomPropertyId", },
176 { UIA_IsTransformPattern2AvailablePropertyId, "UIA_IsTransformPattern2AvailablePropertyId", },
177 { UIA_LiveSettingPropertyId, "UIA_LiveSettingPropertyId", },
178 { UIA_IsTextChildPatternAvailablePropertyId, "UIA_IsTextChildPatternAvailablePropertyId", },
179 { UIA_IsDragPatternAvailablePropertyId, "UIA_IsDragPatternAvailablePropertyId", },
180 { UIA_DragIsGrabbedPropertyId, "UIA_DragIsGrabbedPropertyId", },
181 { UIA_DragDropEffectPropertyId, "UIA_DragDropEffectPropertyId", },
182 { UIA_DragDropEffectsPropertyId, "UIA_DragDropEffectsPropertyId", },
183 { UIA_IsDropTargetPatternAvailablePropertyId, "UIA_IsDropTargetPatternAvailablePropertyId", },
184 { UIA_DropTargetDropTargetEffectPropertyId, "UIA_DropTargetDropTargetEffectPropertyId", },
185 { UIA_DropTargetDropTargetEffectsPropertyId, "UIA_DropTargetDropTargetEffectsPropertyId", },
186 { UIA_DragGrabbedItemsPropertyId, "UIA_DragGrabbedItemsPropertyId", },
187 { UIA_Transform2ZoomLevelPropertyId, "UIA_Transform2ZoomLevelPropertyId", },
188 { UIA_Transform2ZoomMinimumPropertyId, "UIA_Transform2ZoomMinimumPropertyId", },
189 { UIA_Transform2ZoomMaximumPropertyId, "UIA_Transform2ZoomMaximumPropertyId", },
190 { UIA_FlowsFromPropertyId, "UIA_FlowsFromPropertyId", },
191 { UIA_IsTextEditPatternAvailablePropertyId, "UIA_IsTextEditPatternAvailablePropertyId", },
192 { UIA_IsPeripheralPropertyId, "UIA_IsPeripheralPropertyId", },
193 { UIA_IsCustomNavigationPatternAvailablePropertyId, "UIA_IsCustomNavigationPatternAvailablePropertyId", },
194 { UIA_PositionInSetPropertyId, "UIA_PositionInSetPropertyId", },
195 { UIA_SizeOfSetPropertyId, "UIA_SizeOfSetPropertyId", },
196 { UIA_LevelPropertyId, "UIA_LevelPropertyId", },
197 { UIA_AnnotationTypesPropertyId, "UIA_AnnotationTypesPropertyId", },
198 { UIA_AnnotationObjectsPropertyId, "UIA_AnnotationObjectsPropertyId", },
199 { UIA_LandmarkTypePropertyId, "UIA_LandmarkTypePropertyId", },
200 { UIA_LocalizedLandmarkTypePropertyId, "UIA_LocalizedLandmarkTypePropertyId", },
201 { UIA_FullDescriptionPropertyId, "UIA_FullDescriptionPropertyId", },
202 { UIA_FillColorPropertyId, "UIA_FillColorPropertyId", },
203 { UIA_OutlineColorPropertyId, "UIA_OutlineColorPropertyId", },
204 { UIA_FillTypePropertyId, "UIA_FillTypePropertyId", },
205 { UIA_VisualEffectsPropertyId, "UIA_VisualEffectsPropertyId", },
206 { UIA_OutlineThicknessPropertyId, "UIA_OutlineThicknessPropertyId", },
207 { UIA_CenterPointPropertyId, "UIA_CenterPointPropertyId", },
208 { UIA_RotationPropertyId, "UIA_RotationPropertyId", },
209 { UIA_SizePropertyId, "UIA_SizePropertyId", },
210 { UIA_IsSelectionPattern2AvailablePropertyId, "UIA_IsSelectionPattern2AvailablePropertyId", },
211 { UIA_Selection2FirstSelectedItemPropertyId, "UIA_Selection2FirstSelectedItemPropertyId", },
212 { UIA_Selection2LastSelectedItemPropertyId, "UIA_Selection2LastSelectedItemPropertyId", },
213 { UIA_Selection2CurrentSelectedItemPropertyId, "UIA_Selection2CurrentSelectedItemPropertyId", },
214 { UIA_Selection2ItemCountPropertyId, "UIA_Selection2ItemCountPropertyId", },
215 { UIA_HeadingLevelPropertyId, "UIA_HeadingLevelPropertyId", },
216 { UIA_IsDialogPropertyId, "UIA_IsDialogPropertyId", },
217};
218
219static const struct str_id_pair uia_pattern_id_strs[] = {
220 { UIA_InvokePatternId, "UIA_InvokePatternId", },
221 { UIA_SelectionPatternId, "UIA_SelectionPatternId", },
222 { UIA_ValuePatternId, "UIA_ValuePatternId", },
223 { UIA_RangeValuePatternId, "UIA_RangeValuePatternId", },
224 { UIA_ScrollPatternId, "UIA_ScrollPatternId", },
225 { UIA_ExpandCollapsePatternId, "UIA_ExpandCollapsePatternId", },
226 { UIA_GridPatternId, "UIA_GridPatternId", },
227 { UIA_GridItemPatternId, "UIA_GridItemPatternId", },
228 { UIA_MultipleViewPatternId, "UIA_MultipleViewPatternId", },
229 { UIA_WindowPatternId, "UIA_WindowPatternId", },
230 { UIA_SelectionItemPatternId, "UIA_SelectionItemPatternId", },
231 { UIA_DockPatternId, "UIA_DockPatternId", },
232 { UIA_TablePatternId, "UIA_TablePatternId", },
233 { UIA_TableItemPatternId, "UIA_TableItemPatternId", },
234 { UIA_TextPatternId, "UIA_TextPatternId", },
235 { UIA_TogglePatternId, "UIA_TogglePatternId", },
236 { UIA_TransformPatternId, "UIA_TransformPatternId", },
237 { UIA_ScrollItemPatternId, "UIA_ScrollItemPatternId", },
238 { UIA_LegacyIAccessiblePatternId, "UIA_LegacyIAccessiblePatternId", },
239 { UIA_ItemContainerPatternId, "UIA_ItemContainerPatternId", },
240 { UIA_VirtualizedItemPatternId, "UIA_VirtualizedItemPatternId", },
241 { UIA_SynchronizedInputPatternId, "UIA_SynchronizedInputPatternId", },
242 { UIA_ObjectModelPatternId, "UIA_ObjectModelPatternId", },
243 { UIA_AnnotationPatternId, "UIA_AnnotationPatternId", },
244 { UIA_TextPattern2Id, "UIA_TextPattern2Id", },
245 { UIA_StylesPatternId, "UIA_StylesPatternId", },
246 { UIA_SpreadsheetPatternId, "UIA_SpreadsheetPatternId", },
247 { UIA_SpreadsheetItemPatternId, "UIA_SpreadsheetItemPatternId", },
248 { UIA_TransformPattern2Id, "UIA_TransformPattern2Id", },
249 { UIA_TextChildPatternId, "UIA_TextChildPatternId", },
250 { UIA_DragPatternId, "UIA_DragPatternId", },
251 { UIA_DropTargetPatternId, "UIA_DropTargetPatternId", },
252 { UIA_TextEditPatternId, "UIA_TextEditPatternId", },
253 { UIA_CustomNavigationPatternId, "UIA_CustomNavigationPatternId", },
254};
255
256static const struct str_id_pair uia_nav_dir_strs[] = {
257 { NavigateDirection_Parent, "NavigateDirection_Parent" },
258 { NavigateDirection_NextSibling, "NavigateDirection_NextSibling" },
259 { NavigateDirection_PreviousSibling, "NavigateDirection_PreviousSibling" },
260 { NavigateDirection_FirstChild, "NavigateDirection_FirstChild" },
261 { NavigateDirection_LastChild, "NavigateDirection_LastChild" },
262};
263
264static const struct str_id_pair uia_event_id_strs[] = {
265 { UIA_ToolTipOpenedEventId, "UIA_ToolTipOpenedEventId" },
266 { UIA_ToolTipClosedEventId, "UIA_ToolTipClosedEventId", },
267 { UIA_StructureChangedEventId, "UIA_StructureChangedEventId", },
268 { UIA_MenuOpenedEventId, "UIA_MenuOpenedEventId", },
269 { UIA_AutomationPropertyChangedEventId, "UIA_AutomationPropertyChangedEventId", },
270 { UIA_AutomationFocusChangedEventId, "UIA_AutomationFocusChangedEventId", },
271 { UIA_AsyncContentLoadedEventId, "UIA_AsyncContentLoadedEventId", },
272 { UIA_MenuClosedEventId, "UIA_MenuClosedEventId", },
273 { UIA_LayoutInvalidatedEventId, "UIA_LayoutInvalidatedEventId", },
274 { UIA_Invoke_InvokedEventId, "UIA_Invoke_InvokedEventId", },
275 { UIA_SelectionItem_ElementAddedToSelectionEventId, "UIA_SelectionItem_ElementAddedToSelectionEventId", },
276 { UIA_SelectionItem_ElementRemovedFromSelectionEventId, "UIA_SelectionItem_ElementRemovedFromSelectionEventId", },
277 { UIA_SelectionItem_ElementSelectedEventId, "UIA_SelectionItem_ElementSelectedEventId", },
278 { UIA_Selection_InvalidatedEventId, "UIA_Selection_InvalidatedEventId", },
279 { UIA_Text_TextSelectionChangedEventId, "UIA_Text_TextSelectionChangedEventId", },
280 { UIA_Text_TextChangedEventId, "UIA_Text_TextChangedEventId", },
281 { UIA_Window_WindowOpenedEventId, "UIA_Window_WindowOpenedEventId", },
282 { UIA_Window_WindowClosedEventId, "UIA_Window_WindowClosedEventId", },
283 { UIA_MenuModeStartEventId, "UIA_MenuModeStartEventId", },
284 { UIA_MenuModeEndEventId, "UIA_MenuModeEndEventId", },
285 { UIA_InputReachedTargetEventId, "UIA_InputReachedTargetEventId", },
286 { UIA_InputReachedOtherElementEventId, "UIA_InputReachedOtherElementEventId", },
287 { UIA_InputDiscardedEventId, "UIA_InputDiscardedEventId", },
288 { UIA_SystemAlertEventId, "UIA_SystemAlertEventId", },
289 { UIA_LiveRegionChangedEventId, "UIA_LiveRegionChangedEventId", },
290 { UIA_HostedFragmentRootsInvalidatedEventId, "UIA_HostedFragmentRootsInvalidatedEventId", },
291 { UIA_Drag_DragStartEventId, "UIA_Drag_DragStartEventId", },
292 { UIA_Drag_DragCancelEventId, "UIA_Drag_DragCancelEventId", },
293 { UIA_Drag_DragCompleteEventId, "UIA_Drag_DragCompleteEventId", },
294 { UIA_DropTarget_DragEnterEventId, "UIA_DropTarget_DragEnterEventId", },
295 { UIA_DropTarget_DragLeaveEventId, "UIA_DropTarget_DragLeaveEventId", },
296 { UIA_DropTarget_DroppedEventId, "UIA_DropTarget_DroppedEventId", },
297 { UIA_TextEdit_TextChangedEventId, "UIA_TextEdit_TextChangedEventId", },
298 { UIA_TextEdit_ConversionTargetChangedEventId, "UIA_TextEdit_ConversionTargetChangedEventId", },
299 { UIA_ChangesEventId, "UIA_ChangesEventId", },
300 { UIA_NotificationEventId, "UIA_NotificationEventId", },
301};
302
303static int __cdecl str_id_pair_compare(const void *a, const void *b)
304{
305 const int *id = a;
306 const struct str_id_pair *pair = b;
307
308 return ((*id) > pair->id) - ((*id) < pair->id);
309}
310
311#define get_str_for_id(id, id_pair) \
312 get_str_from_id_pair( (id), (id_pair), (ARRAY_SIZE(id_pair)) )
313static const char *get_str_from_id_pair(int id, const struct str_id_pair *id_pair, int id_pair_size)
314{
315 const struct str_id_pair *pair;
316
317 if (!(pair = bsearch(&id, id_pair, id_pair_size, sizeof(*pair), str_id_pair_compare)))
318 return "";
319 else
320 return pair->str;
321}
322
323
324#define PROV_METHOD_TRACE(prov, method) \
325 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method "\n", GetCurrentProcessId(), GetCurrentThreadId(), (prov)->prov_name);
326
327#define PROV_METHOD_TRACE2(prov, method, arg, str_table) \
328 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method ": %d (%s)\n", GetCurrentProcessId(), GetCurrentThreadId(), (prov)->prov_name, \
329 arg, get_str_for_id(arg, str_table)); \
330
331#define ACC_METHOD_TRACE(acc, method) \
332 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method "\n", GetCurrentProcessId(), GetCurrentThreadId(), (acc)->interface_name);
333
334#define ACC_METHOD_TRACE2(acc, cid, method) \
335 if(winetest_debug > 1) printf("%#lx:%#lx: %s_" #method ": %s\n", GetCurrentProcessId(), GetCurrentThreadId(), \
336 (acc)->interface_name, debugstr_variant((cid)));
337
338#define DEFINE_EXPECT(func) \
339 static int expect_ ## func = 0, called_ ## func = 0
340
341#define SET_EXPECT(func) \
342 do { called_ ## func = 0; expect_ ## func = 1; } while(0)
343
344#define SET_EXPECT_MULTI(func, num) \
345 do { called_ ## func = 0; expect_ ## func = num; } while(0)
346
347#define CHECK_EXPECT2(func) \
348 do { \
349 ok(expect_ ##func, "unexpected call " #func "\n"); \
350 called_ ## func++; \
351 }while(0)
352
353#define CHECK_EXPECT(func) \
354 do { \
355 CHECK_EXPECT2(func); \
356 expect_ ## func--; \
357 }while(0)
358
359#define CALLED_COUNT(func) \
360 called_ ## func
361
362#define CHECK_CALLED(func) \
363 do { \
364 ok(called_ ## func, "expected " #func "\n"); \
365 expect_ ## func = called_ ## func = 0; \
366 }while(0)
367
368#define CHECK_CALLED_MULTI(func, num) \
369 do { \
370 ok(called_ ## func == num, "expected " #func " %d times (got %d)\n", num, called_ ## func); \
371 expect_ ## func = called_ ## func = 0; \
372 }while(0)
373
374#define CHECK_CALLED_AT_LEAST(func, num) \
375 do { \
376 ok(called_ ## func >= num, "expected " #func " at least %d time(s) (got %d)\n", num, called_ ## func); \
377 expect_ ## func = called_ ## func = 0; \
378 }while(0)
379
380#define CHECK_CALLED_AT_MOST(func, num) \
381 do { \
382 ok(called_ ## func <= num, "expected " #func " at most %d time(s) (got %d)\n", num, called_ ## func); \
383 expect_ ## func = called_ ## func = 0; \
384 }while(0)
385
386#define NAVDIR_INTERNAL_HWND 10
387#define UIA_RUNTIME_ID_PREFIX 42
388
389DEFINE_EXPECT(winproc_GETOBJECT_CLIENT);
390DEFINE_EXPECT(prov_callback_base_hwnd);
391DEFINE_EXPECT(prov_callback_nonclient);
392DEFINE_EXPECT(prov_callback_proxy);
393DEFINE_EXPECT(prov_callback_parent_proxy);
397DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot);
398DEFINE_EXPECT(child_winproc_GETOBJECT_UiaRoot);
402
404{
405 if (V_VT(v) == VT_I4 && V_I4(v) == val)
406 return TRUE;
407
408 return FALSE;
409}
410
412{
413 if (V_VT(v) == VT_BOOL && V_BOOL(v) == (val ? VARIANT_TRUE : VARIANT_FALSE))
414 return TRUE;
415
416 return FALSE;
417}
418
420{
421 V_VT(v) = VT_BOOL;
422 V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE;
423}
424
425static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
426{
427 IUnknown *unk1, *unk2;
428 BOOL cmp;
429
430 IUnknown_QueryInterface(iface1, &IID_IUnknown, (void**)&unk1);
431 IUnknown_QueryInterface(iface2, &IID_IUnknown, (void**)&unk2);
432 cmp = unk1 == unk2;
433
434 IUnknown_Release(unk1);
435 IUnknown_Release(unk2);
436 return cmp;
437}
438
439#define test_implements_interface( unk, iid, exp_implemented ) \
440 test_implements_interface_( ((IUnknown *)(unk)), (iid), (exp_implemented), __FILE__, __LINE__)
441static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_implemented, const char *file, int line)
442{
443 IUnknown *unk2 = NULL;
444 HRESULT hr;
445
446 hr = IUnknown_QueryInterface(unk, iid, (void **)&unk2);
447 ok_(file, line)(hr == (exp_implemented ? S_OK : E_NOINTERFACE), "Unexpected hr %#lx\n", hr);
448 ok_(file, line)(!!unk2 == exp_implemented, "Unexpected iface %p\n", unk2);
449 if (unk2)
450 IUnknown_Release(unk2);
451}
452
453#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
454 check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
455static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file,
456 int line);
457
458#define DEFINE_ACC_METHOD_EXPECT(method) \
459 int expect_ ## method , called_ ## method
460
461#define DEFINE_ACC_METHOD_EXPECTS \
462 DEFINE_ACC_METHOD_EXPECT(QI_IAccIdentity); \
463 DEFINE_ACC_METHOD_EXPECT(get_accParent); \
464 DEFINE_ACC_METHOD_EXPECT(get_accChildCount); \
465 DEFINE_ACC_METHOD_EXPECT(get_accChild); \
466 DEFINE_ACC_METHOD_EXPECT(get_accName); \
467 DEFINE_ACC_METHOD_EXPECT(get_accValue); \
468 DEFINE_ACC_METHOD_EXPECT(get_accDescription); \
469 DEFINE_ACC_METHOD_EXPECT(get_accRole); \
470 DEFINE_ACC_METHOD_EXPECT(get_accState); \
471 DEFINE_ACC_METHOD_EXPECT(get_accHelp); \
472 DEFINE_ACC_METHOD_EXPECT(get_accHelpTopic); \
473 DEFINE_ACC_METHOD_EXPECT(get_accKeyboardShortcut); \
474 DEFINE_ACC_METHOD_EXPECT(get_accFocus); \
475 DEFINE_ACC_METHOD_EXPECT(get_accSelection); \
476 DEFINE_ACC_METHOD_EXPECT(get_accDefaultAction); \
477 DEFINE_ACC_METHOD_EXPECT(accSelect); \
478 DEFINE_ACC_METHOD_EXPECT(accLocation); \
479 DEFINE_ACC_METHOD_EXPECT(accNavigate); \
480 DEFINE_ACC_METHOD_EXPECT(accHitTest); \
481 DEFINE_ACC_METHOD_EXPECT(accDoDefaultAction); \
482 DEFINE_ACC_METHOD_EXPECT(put_accName); \
483 DEFINE_ACC_METHOD_EXPECT(put_accValue); \
484 DEFINE_ACC_METHOD_EXPECT(get_nRelations); \
485 DEFINE_ACC_METHOD_EXPECT(get_relation); \
486 DEFINE_ACC_METHOD_EXPECT(get_relations); \
487 DEFINE_ACC_METHOD_EXPECT(role); \
488 DEFINE_ACC_METHOD_EXPECT(scrollTo); \
489 DEFINE_ACC_METHOD_EXPECT(scrollToPoint); \
490 DEFINE_ACC_METHOD_EXPECT(get_groupPosition); \
491 DEFINE_ACC_METHOD_EXPECT(get_states); \
492 DEFINE_ACC_METHOD_EXPECT(get_extendedRole); \
493 DEFINE_ACC_METHOD_EXPECT(get_localizedExtendedRole); \
494 DEFINE_ACC_METHOD_EXPECT(get_nExtendedStates); \
495 DEFINE_ACC_METHOD_EXPECT(get_extendedStates); \
496 DEFINE_ACC_METHOD_EXPECT(get_localizedExtendedStates); \
497 DEFINE_ACC_METHOD_EXPECT(get_uniqueID); \
498 DEFINE_ACC_METHOD_EXPECT(get_windowHandle); \
499 DEFINE_ACC_METHOD_EXPECT(get_indexInParent); \
500 DEFINE_ACC_METHOD_EXPECT(get_locale); \
501 DEFINE_ACC_METHOD_EXPECT(get_attributes) \
502
503static DWORD msg_wait_for_all_events(HANDLE *event_handles, int event_handle_count, DWORD timeout_val)
504{
505 int events_handled = 0;
506 DWORD wait_res;
507
508 while ((wait_res = MsgWaitForMultipleObjects(event_handle_count, (const HANDLE *)event_handles, FALSE, timeout_val,
509 QS_ALLINPUT)) <= (WAIT_OBJECT_0 + event_handle_count))
510 {
511 if (wait_res == (WAIT_OBJECT_0 + event_handle_count))
512 {
513 MSG msg;
514
515 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
516 {
519 }
520 }
521 else
522 events_handled++;
523
524 if (events_handled == event_handle_count)
525 break;
526 }
527
528 return wait_res;
529}
530
531static struct Accessible
532{
538
539 const char *interface_name;
540
555
556#define SET_ACC_METHOD_EXPECT(acc, method) \
557 do { (acc)->called_ ## method = 0; (acc)->expect_ ## method = 1; } while(0)
558
559#define SET_ACC_METHOD_EXPECT_MULTI(acc, method, num) \
560 do { (acc)->called_ ## method = 0; (acc)->expect_ ## method = num; } while(0)
561
562#define CHECK_ACC_METHOD_EXPECT2(acc, method) \
563 do { \
564 ok((acc)->expect_ ##method, "unexpected call %s_" #method "\n", (acc)->interface_name); \
565 (acc)->called_ ## method++; \
566 }while(0)
567
568#define CHECK_ACC_METHOD_EXPECT(acc, method) \
569 do { \
570 CHECK_ACC_METHOD_EXPECT2(acc, method); \
571 (acc)->expect_ ## method--; \
572 }while(0)
573
574#define CHECK_ACC_METHOD_CALLED(acc, method) \
575 do { \
576 ok((acc)->called_ ## method, "expected %s_" #method "\n", (acc)->interface_name); \
577 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
578 }while(0)
579
580#define CHECK_ACC_METHOD_CALLED_MULTI(acc, method, num) \
581 do { \
582 ok((acc)->called_ ## method == num, "expected %s_" #method " %d times (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
583 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
584 }while(0)
585
586#define CHECK_ACC_METHOD_CALLED_AT_LEAST(acc, method, num) \
587 do { \
588 ok((acc)->called_ ## method >= num, "expected %s_" #method " at least %d time(s) (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
589 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
590 }while(0)
591
592#define CHECK_ACC_METHOD_CALLED_AT_MOST(acc, method, num) \
593 do { \
594 ok((acc)->called_ ## method <= num, "expected %s_" #method " at most %d time(s) (got %d)\n", (acc)->interface_name, num, (acc)->called_ ## method); \
595 (acc)->expect_ ## method = (acc)->called_ ## method = 0; \
596 }while(0)
597
598static inline struct Accessible* impl_from_Accessible(IAccessible *iface)
599{
600 return CONTAINING_RECORD(iface, struct Accessible, IAccessible_iface);
601}
602
604{
605 struct Accessible *This = impl_from_Accessible(iface);
606
607 *obj = NULL;
608 if (IsEqualIID(riid, &IID_IAccIdentity))
609 {
610 CHECK_ACC_METHOD_EXPECT(This, QI_IAccIdentity);
611 ACC_METHOD_TRACE(This, QI_IAccIdentity);
612 return E_NOINTERFACE;
613 }
614
616 IsEqualIID(riid, &IID_IAccessible))
617 *obj = iface;
618 else if (IsEqualIID(riid, &IID_IOleWindow))
619 *obj = &This->IOleWindow_iface;
620 else if (IsEqualIID(riid, &IID_IServiceProvider))
621 *obj = &This->IServiceProvider_iface;
622 else if (IsEqualIID(riid, &IID_IAccessible2) && This->enable_ia2)
623 *obj = &This->IAccessible2_iface;
624 else
625 return E_NOINTERFACE;
626
627 IAccessible_AddRef(iface);
628 return S_OK;
629}
630
632{
633 struct Accessible *This = impl_from_Accessible(iface);
634 return InterlockedIncrement(&This->ref);
635}
636
638{
639 struct Accessible *This = impl_from_Accessible(iface);
640 return InterlockedDecrement(&This->ref);
641}
642
644{
645 ok(0, "unexpected call\n");
646 return E_NOTIMPL;
647}
648
650 LCID lcid, ITypeInfo **out_tinfo)
651{
652 ok(0, "unexpected call\n");
653 return E_NOTIMPL;
654}
655
657 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
658{
659 ok(0, "unexpected call\n");
660 return E_NOTIMPL;
661}
662
663static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID disp_id_member,
664 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
665 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
666{
667 ok(0, "unexpected call\n");
668 return E_NOTIMPL;
669}
670
672{
673 struct Accessible *This = impl_from_Accessible(iface);
674
675 CHECK_ACC_METHOD_EXPECT(This, get_accParent);
676 ACC_METHOD_TRACE(This, get_accParent);
677 if (This->parent)
678 return IAccessible_QueryInterface(This->parent, &IID_IDispatch, (void **)out_parent);
679
680 *out_parent = NULL;
681 return S_FALSE;
682}
683
685{
686 struct Accessible *This = impl_from_Accessible(iface);
687
688 CHECK_ACC_METHOD_EXPECT(This, get_accChildCount);
689 ACC_METHOD_TRACE(This, get_accChildCount);
690 if (This->child_count)
691 {
692 *out_count = This->child_count;
693 return S_OK;
694 }
695
696 return E_NOTIMPL;
697}
698
700 IDispatch **out_child)
701{
702 struct Accessible *This = impl_from_Accessible(iface);
703
704 CHECK_ACC_METHOD_EXPECT(This, get_accChild);
705 ACC_METHOD_TRACE2(This, &child_id, get_accChild);
706
707 *out_child = NULL;
708 if (V_VT(&child_id) != VT_I4)
709 return E_INVALIDARG;
710
711 if (This == &Accessible)
712 {
713 switch (V_I4(&child_id))
714 {
715 case CHILDID_SELF:
716 return IAccessible_QueryInterface(&This->IAccessible_iface, &IID_IDispatch, (void **)out_child);
717
718 /* Simple element children. */
719 case 1:
720 case 3:
721 return S_FALSE;
722
723 case 2:
724 return IAccessible_QueryInterface(&Accessible_child.IAccessible_iface, &IID_IDispatch, (void **)out_child);
725
726 case 4:
727 return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
728
729 case 7:
730 return IAccessible_QueryInterface(&Accessible.IAccessible_iface, &IID_IDispatch, (void **)out_child);
731
732 default:
733 break;
734
735 }
736 }
737 return E_NOTIMPL;
738}
739
741 BSTR *out_name)
742{
743 struct Accessible *This = impl_from_Accessible(iface);
744
745 CHECK_ACC_METHOD_EXPECT(This, get_accName);
746 ACC_METHOD_TRACE2(This, &child_id, get_accName);
747
748 *out_name = NULL;
749 if (This->name)
750 {
751 *out_name = SysAllocString(This->name);
752 return S_OK;
753 }
754
755 return E_NOTIMPL;
756}
757
759 BSTR *out_value)
760{
761 struct Accessible *This = impl_from_Accessible(iface);
762 CHECK_ACC_METHOD_EXPECT(This, get_accValue);
763 ACC_METHOD_TRACE2(This, &child_id, get_accValue);
764 return E_NOTIMPL;
765}
766
768 BSTR *out_description)
769{
770 struct Accessible *This = impl_from_Accessible(iface);
771 CHECK_ACC_METHOD_EXPECT(This, get_accDescription);
772 ACC_METHOD_TRACE2(This, &child_id, get_accDescription);
773 return E_NOTIMPL;
774}
775
777 VARIANT *out_role)
778{
779 struct Accessible *This = impl_from_Accessible(iface);
780
781 CHECK_ACC_METHOD_EXPECT(This, get_accRole);
782 ACC_METHOD_TRACE2(This, &child_id, get_accRole);
783
784 if (This->role)
785 {
786 V_VT(out_role) = VT_I4;
787 V_I4(out_role) = This->role;
788 return S_OK;
789 }
790
791 return E_NOTIMPL;
792}
793
795 VARIANT *out_state)
796{
797 struct Accessible *This = impl_from_Accessible(iface);
798
799 CHECK_ACC_METHOD_EXPECT(This, get_accState);
800 ACC_METHOD_TRACE2(This, &child_id, get_accState);
801
802 if (V_VT(&child_id) != VT_I4)
803 return E_INVALIDARG;
804
805 if (This == &Accessible && V_I4(&child_id) != CHILDID_SELF)
806 {
807 switch (V_I4(&child_id))
808 {
809 case 1:
810 V_VT(out_state) = VT_I4;
811 V_I4(out_state) = STATE_SYSTEM_INVISIBLE;
812 break;
813
814 case 3:
815 V_VT(out_state) = VT_I4;
816 V_I4(out_state) = STATE_SYSTEM_FOCUSABLE;
817 break;
818
819 default:
820 return E_INVALIDARG;
821 }
822
823 return S_OK;
824 }
825
826 if (This->state)
827 {
828 V_VT(out_state) = VT_I4;
829 V_I4(out_state) = This->state;
830 return S_OK;
831 }
832
833 return E_NOTIMPL;
834}
835
837 BSTR *out_help)
838{
839 struct Accessible *This = impl_from_Accessible(iface);
840 CHECK_ACC_METHOD_EXPECT(This, get_accHelp);
841 ACC_METHOD_TRACE2(This, &child_id, get_accHelp);
842 return E_NOTIMPL;
843}
844
846 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
847{
848 struct Accessible *This = impl_from_Accessible(iface);
849 CHECK_ACC_METHOD_EXPECT(This, get_accHelpTopic);
850 ACC_METHOD_TRACE2(This, &child_id, get_accHelpTopic);
851 return E_NOTIMPL;
852}
853
855 BSTR *out_kbd_shortcut)
856{
857 struct Accessible *This = impl_from_Accessible(iface);
858 CHECK_ACC_METHOD_EXPECT(This, get_accKeyboardShortcut);
859 ACC_METHOD_TRACE2(This, &child_id, get_accKeyboardShortcut);
860 return E_NOTIMPL;
861}
862
864{
865 struct Accessible *This = impl_from_Accessible(iface);
866
867 CHECK_ACC_METHOD_EXPECT(This, get_accFocus);
868 ACC_METHOD_TRACE(This, get_accFocus);
869
870 VariantInit(pchild_id);
871 if (This->focus_acc)
872 {
873 HRESULT hr;
874
875 hr = IAccessible_QueryInterface(This->focus_acc, &IID_IDispatch, (void **)&V_DISPATCH(pchild_id));
876 if (SUCCEEDED(hr))
877 V_VT(pchild_id) = VT_DISPATCH;
878
879 return hr;
880 }
881 else if (This->focus_child_id >= 0)
882 {
883 V_VT(pchild_id) = VT_I4;
884 V_I4(pchild_id) = This->focus_child_id;
885 return S_OK;
886 }
887
888 return E_NOTIMPL;
889}
890
892{
893 struct Accessible *This = impl_from_Accessible(iface);
894 CHECK_ACC_METHOD_EXPECT(This, get_accSelection);
895 ACC_METHOD_TRACE(This, get_accSelection);
896 return E_NOTIMPL;
897}
898
900 BSTR *out_default_action)
901{
902 struct Accessible *This = impl_from_Accessible(iface);
903 CHECK_ACC_METHOD_EXPECT(This, get_accDefaultAction);
904 ACC_METHOD_TRACE2(This, &child_id, get_accDefaultAction);
905 return E_NOTIMPL;
906}
907
909 VARIANT child_id)
910{
911 struct Accessible *This = impl_from_Accessible(iface);
912 CHECK_ACC_METHOD_EXPECT(This, accSelect);
913 ACC_METHOD_TRACE2(This, &child_id, accSelect);
914 return E_NOTIMPL;
915}
916
918 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
919{
920 struct Accessible *This = impl_from_Accessible(iface);
921
922 CHECK_ACC_METHOD_EXPECT(This, accLocation);
923 ACC_METHOD_TRACE2(This, &child_id, accLocation);
924
925 if (This->width && This->height)
926 {
927 *out_left = This->left;
928 *out_top = This->top;
929 *out_width = This->width;
930 *out_height = This->height;
931 return S_OK;
932 }
933
934 return E_NOTIMPL;
935}
936
938 VARIANT child_id_start, VARIANT *out_var)
939{
940 struct Accessible *This = impl_from_Accessible(iface);
941
942 CHECK_ACC_METHOD_EXPECT(This, accNavigate);
943 ACC_METHOD_TRACE2(This, &child_id_start, accNavigate);
944
945 VariantInit(out_var);
946
947 /*
948 * This is an undocumented way for UI Automation to get an HWND for
949 * IAccessible's contained in a Direct Annotation wrapper object.
950 */
951 if ((nav_direction == NAVDIR_INTERNAL_HWND) && check_variant_i4(&child_id_start, CHILDID_SELF) &&
952 This->acc_hwnd)
953 {
954 V_VT(out_var) = VT_I4;
955 V_I4(out_var) = HandleToUlong(This->acc_hwnd);
956 return S_OK;
957 }
958 return S_FALSE;
959}
960
962 VARIANT *out_child_id)
963{
964 struct Accessible *This = impl_from_Accessible(iface);
965 CHECK_ACC_METHOD_EXPECT(This, accHitTest);
966 ACC_METHOD_TRACE(This, accHitTest);
967 return E_NOTIMPL;
968}
969
971{
972 struct Accessible *This = impl_from_Accessible(iface);
973 CHECK_ACC_METHOD_EXPECT(This, accDoDefaultAction);
974 ACC_METHOD_TRACE2(This, &child_id, accDoDefaultAction);
975 return E_NOTIMPL;
976}
977
979 BSTR name)
980{
981 struct Accessible *This = impl_from_Accessible(iface);
982 CHECK_ACC_METHOD_EXPECT(This, put_accName);
983 ACC_METHOD_TRACE2(This, &child_id, put_accName);
984 return E_NOTIMPL;
985}
986
988 BSTR value)
989{
990 struct Accessible *This = impl_from_Accessible(iface);
991 CHECK_ACC_METHOD_EXPECT(This, put_accValue);
992 ACC_METHOD_TRACE2(This, &child_id, put_accValue);
993 return E_NOTIMPL;
994}
995
996static IAccessibleVtbl AccessibleVtbl = {
1025};
1026
1027static inline struct Accessible* impl_from_Accessible2(IAccessible2 *iface)
1028{
1029 return CONTAINING_RECORD(iface, struct Accessible, IAccessible2_iface);
1030}
1031
1033{
1034 struct Accessible *This = impl_from_Accessible2(iface);
1035 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1036}
1037
1039{
1040 struct Accessible *This = impl_from_Accessible2(iface);
1041 return IAccessible_AddRef(&This->IAccessible_iface);
1042}
1043
1045{
1046 struct Accessible *This = impl_from_Accessible2(iface);
1047 return IAccessible_Release(&This->IAccessible_iface);
1048}
1049
1051{
1052 struct Accessible *This = impl_from_Accessible2(iface);
1053 return IAccessible_GetTypeInfoCount(&This->IAccessible_iface, pctinfo);
1054}
1055
1057 LCID lcid, ITypeInfo **out_tinfo)
1058{
1059 struct Accessible *This = impl_from_Accessible2(iface);
1060 return IAccessible_GetTypeInfo(&This->IAccessible_iface, iTInfo, lcid, out_tinfo);
1061}
1062
1064 LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
1065{
1066 struct Accessible *This = impl_from_Accessible2(iface);
1067 return IAccessible_GetIDsOfNames(&This->IAccessible_iface, riid, rg_names, name_count,
1068 lcid, rg_disp_id);
1069}
1070
1072 REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params,
1073 VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
1074{
1075 struct Accessible *This = impl_from_Accessible2(iface);
1076 return IAccessible_Invoke(&This->IAccessible_iface, disp_id_member, riid, lcid, flags,
1077 disp_params, var_result, excep_info, arg_err);
1078}
1079
1081{
1082 struct Accessible *This = impl_from_Accessible2(iface);
1083 return IAccessible_get_accParent(&This->IAccessible_iface, out_parent);
1084}
1085
1087{
1088 struct Accessible *This = impl_from_Accessible2(iface);
1089 return IAccessible_get_accChildCount(&This->IAccessible_iface, out_count);
1090}
1091
1093 IDispatch **out_child)
1094{
1095 struct Accessible *This = impl_from_Accessible2(iface);
1096 return IAccessible_get_accChild(&This->IAccessible_iface, child_id, out_child);
1097}
1098
1100 BSTR *out_name)
1101{
1102 struct Accessible *This = impl_from_Accessible2(iface);
1103 return IAccessible_get_accName(&This->IAccessible_iface, child_id, out_name);
1104}
1105
1107 BSTR *out_value)
1108{
1109 struct Accessible *This = impl_from_Accessible2(iface);
1110 return IAccessible_get_accValue(&This->IAccessible_iface, child_id, out_value);
1111}
1112
1114 BSTR *out_description)
1115{
1116 struct Accessible *This = impl_from_Accessible2(iface);
1117 return IAccessible_get_accDescription(&This->IAccessible_iface, child_id, out_description);
1118}
1119
1121 VARIANT *out_role)
1122{
1123 struct Accessible *This = impl_from_Accessible2(iface);
1124 return IAccessible_get_accRole(&This->IAccessible_iface, child_id, out_role);
1125}
1126
1128 VARIANT *out_state)
1129{
1130 struct Accessible *This = impl_from_Accessible2(iface);
1131 return IAccessible_get_accState(&This->IAccessible_iface, child_id, out_state);
1132}
1133
1135 BSTR *out_help)
1136{
1137 struct Accessible *This = impl_from_Accessible2(iface);
1138 return IAccessible_get_accHelp(&This->IAccessible_iface, child_id, out_help);
1139}
1140
1142 BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
1143{
1144 struct Accessible *This = impl_from_Accessible2(iface);
1145 return IAccessible_get_accHelpTopic(&This->IAccessible_iface, out_help_file, child_id,
1146 out_topic_id);
1147}
1148
1150 BSTR *out_kbd_shortcut)
1151{
1152 struct Accessible *This = impl_from_Accessible2(iface);
1153 return IAccessible_get_accKeyboardShortcut(&This->IAccessible_iface, child_id,
1154 out_kbd_shortcut);
1155}
1156
1158{
1159 struct Accessible *This = impl_from_Accessible2(iface);
1160 return IAccessible_get_accFocus(&This->IAccessible_iface, pchild_id);
1161}
1162
1164{
1165 struct Accessible *This = impl_from_Accessible2(iface);
1166 return IAccessible_get_accSelection(&This->IAccessible_iface, out_selection);
1167}
1168
1170 BSTR *out_default_action)
1171{
1172 struct Accessible *This = impl_from_Accessible2(iface);
1173 return IAccessible_get_accDefaultAction(&This->IAccessible_iface, child_id,
1174 out_default_action);
1175}
1176
1178 VARIANT child_id)
1179{
1180 struct Accessible *This = impl_from_Accessible2(iface);
1181 return IAccessible_accSelect(&This->IAccessible_iface, select_flags, child_id);
1182}
1183
1185 LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
1186{
1187 struct Accessible *This = impl_from_Accessible2(iface);
1188 return IAccessible_accLocation(&This->IAccessible_iface, out_left, out_top, out_width,
1189 out_height, child_id);
1190}
1191
1193 VARIANT child_id_start, VARIANT *out_var)
1194{
1195 struct Accessible *This = impl_from_Accessible2(iface);
1196 return IAccessible_accNavigate(&This->IAccessible_iface, nav_direction, child_id_start,
1197 out_var);
1198}
1199
1201 VARIANT *out_child_id)
1202{
1203 struct Accessible *This = impl_from_Accessible2(iface);
1204 return IAccessible_accHitTest(&This->IAccessible_iface, left, top, out_child_id);
1205}
1206
1208{
1209 struct Accessible *This = impl_from_Accessible2(iface);
1210 return IAccessible_accDoDefaultAction(&This->IAccessible_iface, child_id);
1211}
1212
1214 BSTR name)
1215{
1216 struct Accessible *This = impl_from_Accessible2(iface);
1217 return IAccessible_put_accName(&This->IAccessible_iface, child_id, name);
1218}
1219
1221 BSTR value)
1222{
1223 struct Accessible *This = impl_from_Accessible2(iface);
1224 return IAccessible_put_accValue(&This->IAccessible_iface, child_id, value);
1225}
1226
1228{
1229 struct Accessible *This = impl_from_Accessible2(iface);
1230 CHECK_ACC_METHOD_EXPECT(This, get_nRelations);
1231 ACC_METHOD_TRACE(This, get_nRelations);
1232 return E_NOTIMPL;
1233}
1234
1236 IAccessibleRelation **out_relation)
1237{
1238 struct Accessible *This = impl_from_Accessible2(iface);
1239 CHECK_ACC_METHOD_EXPECT(This, get_relation);
1240 ACC_METHOD_TRACE(This, get_relation);
1241 return E_NOTIMPL;
1242}
1243
1245 IAccessibleRelation **out_relations, LONG *out_relation_count)
1246{
1247 struct Accessible *This = impl_from_Accessible2(iface);
1248 CHECK_ACC_METHOD_EXPECT(This, get_relations);
1249 ACC_METHOD_TRACE(This, get_relations);
1250 return E_NOTIMPL;
1251}
1252
1254{
1255 struct Accessible *This = impl_from_Accessible2(iface);
1258 return E_NOTIMPL;
1259}
1260
1262{
1263 struct Accessible *This = impl_from_Accessible2(iface);
1264 CHECK_ACC_METHOD_EXPECT(This, scrollTo);
1265 ACC_METHOD_TRACE(This, scrollTo);
1266 return E_NOTIMPL;
1267}
1268
1270 enum IA2CoordinateType coordinate_type, LONG x, LONG y)
1271{
1272 struct Accessible *This = impl_from_Accessible2(iface);
1273 CHECK_ACC_METHOD_EXPECT(This, scrollToPoint);
1274 ACC_METHOD_TRACE(This, scrollToPoint);
1275 return E_NOTIMPL;
1276}
1277
1279 LONG *out_similar_items_in_group, LONG *out_position_in_group)
1280{
1281 struct Accessible *This = impl_from_Accessible2(iface);
1282 CHECK_ACC_METHOD_EXPECT(This, get_groupPosition);
1283 ACC_METHOD_TRACE(This, get_groupPosition);
1284 return E_NOTIMPL;
1285}
1286
1288{
1289 struct Accessible *This = impl_from_Accessible2(iface);
1290 CHECK_ACC_METHOD_EXPECT(This, get_states);
1291 ACC_METHOD_TRACE(This, get_states);
1292 return E_NOTIMPL;
1293}
1294
1296{
1297 struct Accessible *This = impl_from_Accessible2(iface);
1298 CHECK_ACC_METHOD_EXPECT(This, get_extendedRole);
1299 ACC_METHOD_TRACE(This, get_extendedRole);
1300 return E_NOTIMPL;
1301}
1302
1304 BSTR *out_localized_extended_role)
1305{
1306 struct Accessible *This = impl_from_Accessible2(iface);
1307 CHECK_ACC_METHOD_EXPECT(This, get_localizedExtendedRole);
1308 ACC_METHOD_TRACE(This, get_localizedExtendedRole);
1309 return E_NOTIMPL;
1310}
1311
1313{
1314 struct Accessible *This = impl_from_Accessible2(iface);
1315 CHECK_ACC_METHOD_EXPECT(This, get_nExtendedStates);
1316 ACC_METHOD_TRACE(This, get_nExtendedStates);
1317 return E_NOTIMPL;
1318}
1319
1321 BSTR **out_extended_states, LONG *out_extended_states_count)
1322{
1323 struct Accessible *This = impl_from_Accessible2(iface);
1324 CHECK_ACC_METHOD_EXPECT(This, get_extendedStates);
1325 ACC_METHOD_TRACE(This, get_extendedStates);
1326 return E_NOTIMPL;
1327}
1328
1330 BSTR **out_localized_extended_states, LONG *out_localized_extended_states_count)
1331{
1332 struct Accessible *This = impl_from_Accessible2(iface);
1333 CHECK_ACC_METHOD_EXPECT(This, get_localizedExtendedStates);
1334 ACC_METHOD_TRACE(This, get_localizedExtendedStates);
1335 return E_NOTIMPL;
1336}
1337
1339{
1340 struct Accessible *This = impl_from_Accessible2(iface);
1341
1342 CHECK_ACC_METHOD_EXPECT(This, get_uniqueID);
1343 ACC_METHOD_TRACE(This, get_uniqueID);
1344
1345 *out_unique_id = 0;
1346 if (This->unique_id)
1347 {
1348 *out_unique_id = This->unique_id;
1349 return S_OK;
1350 }
1351
1352 return E_NOTIMPL;
1353}
1354
1356{
1357 struct Accessible *This = impl_from_Accessible2(iface);
1358 CHECK_ACC_METHOD_EXPECT(This, get_windowHandle);
1359 ACC_METHOD_TRACE(This, get_windowHandle);
1360 return E_NOTIMPL;
1361}
1362
1364{
1365 struct Accessible *This = impl_from_Accessible2(iface);
1366 CHECK_ACC_METHOD_EXPECT(This, get_indexInParent);
1367 ACC_METHOD_TRACE(This, get_indexInParent);
1368 return E_NOTIMPL;
1369}
1370
1372{
1373 struct Accessible *This = impl_from_Accessible2(iface);
1376 return E_NOTIMPL;
1377}
1378
1380{
1381 struct Accessible *This = impl_from_Accessible2(iface);
1384 return E_NOTIMPL;
1385}
1386
1387static const IAccessible2Vtbl Accessible2Vtbl = {
1434};
1435
1436static inline struct Accessible* impl_from_OleWindow(IOleWindow *iface)
1437{
1438 return CONTAINING_RECORD(iface, struct Accessible, IOleWindow_iface);
1439}
1440
1442{
1443 struct Accessible *This = impl_from_OleWindow(iface);
1444 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1445}
1446
1448{
1449 struct Accessible *This = impl_from_OleWindow(iface);
1450 return IAccessible_AddRef(&This->IAccessible_iface);
1451}
1452
1454{
1455 struct Accessible *This = impl_from_OleWindow(iface);
1456 return IAccessible_Release(&This->IAccessible_iface);
1457}
1458
1460{
1461 struct Accessible *This = impl_from_OleWindow(iface);
1462
1463 *hwnd = This->ow_hwnd;
1464 return *hwnd ? S_OK : E_FAIL;
1465}
1466
1468{
1469 return E_NOTIMPL;
1470}
1471
1472static const IOleWindowVtbl OleWindowVtbl = {
1478};
1479
1481{
1483}
1484
1486{
1487 struct Accessible *This = impl_from_ServiceProvider(iface);
1488 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1489}
1490
1492{
1493 struct Accessible *This = impl_from_ServiceProvider(iface);
1494 return IAccessible_AddRef(&This->IAccessible_iface);
1495}
1496
1498{
1499 struct Accessible *This = impl_from_ServiceProvider(iface);
1500 return IAccessible_Release(&This->IAccessible_iface);
1501}
1502
1504 REFIID riid, void **obj)
1505{
1506 struct Accessible *This = impl_from_ServiceProvider(iface);
1507
1508 if (IsEqualIID(riid, &IID_IAccessible2) && IsEqualIID(service_guid, &IID_IAccessible2) &&
1509 This->enable_ia2)
1510 return IAccessible_QueryInterface(&This->IAccessible_iface, riid, obj);
1511
1512 return E_NOTIMPL;
1513}
1514
1515static const IServiceProviderVtbl ServiceProviderVtbl = {
1520};
1521
1522static struct Accessible Accessible =
1523{
1524 { &AccessibleVtbl },
1525 { &Accessible2Vtbl },
1526 { &OleWindowVtbl },
1528 1,
1529 "Accessible",
1530 NULL,
1531 0, 0,
1532 0, 0, 0, NULL,
1533 0, 0, 0, 0,
1534 FALSE, 0,
1536};
1537
1539{
1540 { &AccessibleVtbl },
1541 { &Accessible2Vtbl },
1542 { &OleWindowVtbl },
1544 1,
1545 "Accessible2",
1546 NULL,
1547 0, 0,
1548 0, 0, 0, NULL,
1549 0, 0, 0, 0,
1550 FALSE, 0,
1552};
1553
1555{
1556 { &AccessibleVtbl },
1557 { &Accessible2Vtbl },
1558 { &OleWindowVtbl },
1560 1,
1561 "Accessible_child",
1563 0, 0,
1564 0, 0, 0, NULL,
1565 0, 0, 0, 0,
1566 FALSE, 0,
1568};
1569
1571{
1572 { &AccessibleVtbl },
1573 { &Accessible2Vtbl },
1574 { &OleWindowVtbl },
1576 1,
1577 "Accessible_child2",
1579 0, 0,
1580 0, 0, 0, NULL,
1581 0, 0, 0, 0,
1582 FALSE, 0,
1584};
1585
1587{
1590};
1591
1593{
1596};
1597
1599{
1603};
1604
1606{
1608
1613
1614 IRawElementProviderSimple *responder_prov;
1616};
1617
1618static struct Provider
1619{
1620 IRawElementProviderSimple IRawElementProviderSimple_iface;
1621 IRawElementProviderFragment IRawElementProviderFragment_iface;
1622 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface;
1623 IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface;
1624 IRawElementProviderAdviseEvents IRawElementProviderAdviseEvents_iface;
1625 IProxyProviderWinEventHandler IProxyProviderWinEventHandler_iface;
1626 IValueProvider IValueProvider_iface;
1627 ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface;
1629
1630 const char *prov_name;
1631 IRawElementProviderFragment *parent;
1632 IRawElementProviderFragmentRoot *frag_root;
1633 IRawElementProviderFragment *prev_sibling;
1634 IRawElementProviderFragment *next_sibling;
1635 IRawElementProviderFragment *first_child;
1636 IRawElementProviderFragment *last_child;
1650 IRawElementProviderFragment *focus_prov;
1651 IRawElementProviderFragmentRoot **embedded_frag_roots;
1660static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links);
1661static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count);
1662static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val);
1663static void initialize_provider_tree(BOOL initialize_nav_links);
1664static void provider_add_child(struct Provider *prov, struct Provider *child);
1665
1666static const WCHAR *uia_bstr_prop_str = L"uia-string";
1667static const ULONG uia_i4_prop_val = 0xdeadbeef;
1668static const ULONG uia_i4_arr_prop_val[] = { 0xfeedbeef, 0xdeadcafe, 0xfefedede };
1669static const double uia_r8_prop_val = 128.256f;
1670static const double uia_r8_arr_prop_val[] = { 2.4, 8.16, 32.64 };
1671static const IRawElementProviderSimple *uia_unk_arr_prop_val[] = { &Provider_child.IRawElementProviderSimple_iface,
1672 &Provider_child2.IRawElementProviderSimple_iface };
1674{
1675 SAFEARRAY *sa;
1676 LONG idx;
1677
1679 return NULL;
1680
1681 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
1683
1684 return sa;
1685}
1686
1688{
1689 SAFEARRAY *sa;
1690 LONG idx;
1691
1693 return NULL;
1694
1695 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
1697
1698 return sa;
1699}
1700
1702{
1703 SAFEARRAY *sa;
1704 LONG idx;
1705
1707 return NULL;
1708
1709 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
1711
1712 return sa;
1713}
1714
1715enum {
1730};
1731
1732static const char *prov_method_str[] = {
1733 "get_ProviderOptions",
1734 "GetPatternProvider",
1735 "GetPropertyValue",
1736 "get_HostRawElementProvider",
1737 "Navigate",
1738 "GetRuntimeId",
1739 "get_FragmentRoot",
1740 "get_BoundingRectangle",
1741 "GetEmbeddedFragmentRoots",
1742 "GetFocus",
1743 "GetOverrideProviderForHwnd",
1744 "AdviseEventAdded",
1745 "AdviseEventRemoved",
1746 "RespondToWinEvent",
1747};
1748
1749static const char *get_prov_method_str(int method)
1750{
1752 return NULL;
1753 else
1754 return prov_method_str[method];
1755}
1756
1757enum {
1760};
1761
1766};
1767
1770
1771/*
1772 * This sequence of method calls is always used when creating an HUIANODE from
1773 * an IRawElementProviderSimple.
1774 */
1775#define NODE_CREATE_SEQ(prov) \
1776 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1777 /* Win10v1507 and below call this. */ \
1778 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1779 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1780 { prov , PROV_GET_PROPERTY_VALUE }, \
1781 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1782 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1783
1784#define NODE_CREATE_SEQ_OPTIONAL(prov) \
1785 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1786 /* Win10v1507 and below call this. */ \
1787 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1788 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1789 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, \
1790 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1791 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1792
1793/*
1794 * This sequence of method calls is always used when creating an HUIANODE from
1795 * an IRawElementProviderSimple that returns an HWND from get_HostRawElementProvider.
1796 */
1797#define NODE_CREATE_SEQ2(prov) \
1798 { prov , PROV_GET_PROVIDER_OPTIONS }, \
1799 /* Win10v1507 and below call this. */ \
1800 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1801 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1802 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1803 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1804
1805#define NODE_CREATE_SEQ2_OPTIONAL(prov) \
1806 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1807 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, \
1808 { prov , FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */ \
1809 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1810
1811/*
1812 * Node creation sequence with the first get_ProviderOptions call being optional.
1813 * Used for event tests since each Windows version has different amounts of
1814 * calls to get_ProviderOptions before node creation.
1815 */
1816#define NODE_CREATE_SEQ3(prov) \
1817 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
1818 /* Win10v1507 and below call this. */ \
1819 { prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
1820 { prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER }, \
1821 { prov , PROV_GET_PROPERTY_VALUE }, \
1822 { prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
1823 { prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
1824
1825static void flush_method_sequence(void)
1826{
1827 free(sequence);
1828 sequence = NULL;
1830}
1831
1833static void add_method_call(struct Provider *prov, int method)
1834{
1835 struct prov_method_sequence prov_method = {0};
1836
1838 return;
1839
1841 {
1844 }
1845
1846 prov_method.prov = prov;
1847 prov_method.method = method;
1848 prov_method.flags = 0;
1849 sequence[sequence_cnt++] = prov_method;
1850}
1851
1852#define ok_method_sequence( exp, context ) \
1853 ok_method_sequence_( (exp), (context), __FILE__, __LINE__)
1854static void ok_method_sequence_(const struct prov_method_sequence *expected_list, const char *context,
1855 const char *file, int line)
1856{
1857 const struct prov_method_sequence *expected = expected_list;
1858 const struct prov_method_sequence *actual;
1859 unsigned int count = 0;
1860
1863 actual = sequence;
1864
1865 if (context)
1867
1868 while (expected->prov && actual->prov)
1869 {
1870 if (expected->prov == actual->prov && expected->method == actual->method)
1871 {
1872 if (expected->flags & METHOD_TODO)
1873 todo_wine ok_(file, line)(1, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1874 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1875 expected++;
1876 actual++;
1877 }
1878 else if (expected->flags & METHOD_TODO)
1879 {
1880 todo_wine ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1881 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1882 expected++;
1883 }
1884 else if (expected->flags & METHOD_OPTIONAL)
1885 expected++;
1886 else
1887 {
1888 ok_(file, line)(0, "%d: expected %s_%s, got %s_%s\n", count, expected->prov->prov_name,
1889 get_prov_method_str(expected->method), actual->prov->prov_name, get_prov_method_str(actual->method));
1890 expected++;
1891 actual++;
1892 }
1893 count++;
1894 }
1895
1896 /* Handle trailing optional/todo_wine methods. */
1897 while (expected->prov && ((expected->flags & METHOD_OPTIONAL) ||
1898 ((expected->flags & METHOD_TODO) && !strcmp(winetest_platform, "wine"))))
1899 {
1900 if (expected->flags & METHOD_TODO)
1901 todo_wine ok_(file, line)(0, "%d: expected %s_%s\n", count, expected->prov->prov_name,
1902 get_prov_method_str(expected->method));
1903 count++;
1904 expected++;
1905 }
1906
1907 if (expected->prov || actual->prov)
1908 {
1909 if (expected->prov)
1910 ok_( file, line)(0, "incomplete sequence: expected %s_%s, got nothing\n", expected->prov->prov_name,
1911 get_prov_method_str(expected->method));
1912 else
1913 ok_( file, line)(0, "incomplete sequence: expected nothing, got %s_%s\n", actual->prov->prov_name,
1914 get_prov_method_str(actual->method));
1915 }
1916
1917 if (context)
1919
1921}
1922
1924{
1925 if (prov->method_call_event_handle && (prov->method_call_event_method_id == method))
1926 SetEvent(prov->method_call_event_handle);
1927}
1928
1929/*
1930 * Parsing the string returned by UIA_ProviderDescriptionPropertyId is
1931 * the only way to know what an HUIANODE represents internally. It
1932 * returns a formatted string which always starts with:
1933 * "[pid:<process-id>,providerId:0x<hwnd-ptr> "
1934 * On Windows versions 10v1507 and below, "providerId:" is "hwnd:"
1935 *
1936 * This is followed by strings for each provider it represents. These are
1937 * formatted as:
1938 * "<prov-type>:<prov-desc> (<origin>)"
1939 * and are terminated with ";", the final provider has no ";" terminator,
1940 * instead it has "]".
1941 *
1942 * If the given provider is the one used for navigation towards a parent, it has
1943 * "(parent link)" as a suffix on "<prov-type>".
1944 *
1945 * <prov-type> is one of "Annotation", "Main", "Override", "Hwnd", or
1946 * "Nonclient".
1947 *
1948 * <prov-desc> is the string returned from calling GetPropertyValue on the
1949 * IRawElementProviderSimple being represented with a property ID of
1950 * UIA_ProviderDescriptionPropertyId.
1951 *
1952 * <origin> is the name of the module that the
1953 * IRawElementProviderSimple comes from. For unmanaged code, it's:
1954 * "unmanaged:<executable>"
1955 * and for managed code, it's:
1956 * "managed:<assembly-qualified-name>"
1957 *
1958 * An example:
1959 * [pid:1500,providerId:0x2F054C Main:Provider (unmanaged:uiautomation_test.exe); Hwnd(parent link):HWND Proxy (unmanaged:uiautomationcore.dll)]
1960 */
1961static BOOL get_provider_desc(BSTR prov_desc, const WCHAR *prov_type, WCHAR *out_name)
1962{
1963 const WCHAR *str, *str2;
1964
1965 str = wcsstr(prov_desc, prov_type);
1966 if (!str)
1967 return FALSE;
1968
1969 if (!out_name)
1970 return TRUE;
1971
1972 str += wcslen(prov_type);
1973 str2 = wcschr(str, L'(');
1974 lstrcpynW(out_name, str, ((str2 - str)));
1975
1976 return TRUE;
1977}
1978
1979#define check_node_provider_desc_todo( prov_desc, prov_type, prov_name, parent_link ) \
1980 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), TRUE, __FILE__, __LINE__)
1981#define check_node_provider_desc( prov_desc, prov_type, prov_name, parent_link ) \
1982 check_node_provider_desc_( (prov_desc), (prov_type), (prov_name), (parent_link), FALSE, __FILE__, __LINE__)
1983static void check_node_provider_desc_(BSTR prov_desc, const WCHAR *prov_type, const WCHAR *prov_name,
1984 BOOL parent_link, BOOL todo, const char *file, int line)
1985{
1986 WCHAR buf[2048];
1987
1988 if (parent_link)
1989 wsprintfW(buf, L"%s(parent link):", prov_type);
1990 else
1991 wsprintfW(buf, L"%s:", prov_type);
1992
1993 if (!get_provider_desc(prov_desc, buf, buf))
1994 {
1995 if (parent_link)
1996 wsprintfW(buf, L"%s:", prov_type);
1997 else
1998 wsprintfW(buf, L"%s(parent link):", prov_type);
1999
2000 if (!get_provider_desc(prov_desc, buf, buf))
2001 todo_wine_if(todo) ok_(file, line)(0, "failed to get provider string for %s\n", debugstr_w(prov_type));
2002 else
2003 {
2004 if (parent_link)
2005 todo_wine_if(todo) ok_(file, line)(0, "expected parent link provider %s\n", debugstr_w(prov_type));
2006 else
2007 todo_wine_if(todo) ok_(file, line)(0, "unexpected parent link provider %s\n", debugstr_w(prov_type));
2008 }
2009
2010 return;
2011 }
2012
2013 if (prov_name)
2014 ok_(file, line)(!wcscmp(prov_name, buf), "unexpected provider name %s\n", debugstr_w(buf));
2015}
2016
2017#define check_node_provider_desc_prefix( prov_desc, pid, prov_id ) \
2018 check_node_provider_desc_prefix_( (prov_desc), (pid), (prov_id), __FILE__, __LINE__)
2019static void check_node_provider_desc_prefix_(BSTR prov_desc, DWORD pid, HWND prov_id, const char *file, int line)
2020{
2021 const WCHAR *str, *str2;
2022 WCHAR buf[128];
2023 DWORD prov_pid;
2024 HWND prov_hwnd;
2025 WCHAR *end;
2026
2027 str = wcsstr(prov_desc, L"pid:");
2028 str += wcslen(L"pid:");
2029 str2 = wcschr(str, L',');
2030 lstrcpynW(buf, str, (str2 - str) + 1);
2031 prov_pid = wcstoul(buf, &end, 10);
2032 ok_(file, line)(prov_pid == pid, "Unexpected pid %lu\n", prov_pid);
2033
2034 str = wcsstr(prov_desc, L"providerId:");
2035 if (str)
2036 str += wcslen(L"providerId:");
2037 else
2038 {
2039 str = wcsstr(prov_desc, L"hwnd:");
2040 str += wcslen(L"hwnd:");
2041 }
2042 str2 = wcschr(str, L' ');
2043 lstrcpynW(buf, str, (str2 - str) + 1);
2044 prov_hwnd = ULongToHandle(wcstoul(buf, &end, 16));
2045 ok_(file, line)(prov_hwnd == prov_id, "Unexpected hwnd %p\n", prov_hwnd);
2046}
2047
2048/*
2049 * For node providers that come from an HWND belonging to another process
2050 * or another thread, the provider is considered 'nested', a node in a node.
2051 */
2052static BOOL get_nested_provider_desc(BSTR prov_desc, const WCHAR *prov_type, BOOL parent_link, WCHAR *out_desc)
2053{
2054 const WCHAR *str, *str2;
2055 WCHAR buf[1024];
2056
2057 if (!parent_link)
2058 wsprintfW(buf, L"%s:Nested ", prov_type);
2059 else
2060 wsprintfW(buf, L"%s(parent link):Nested ", prov_type);
2061 str = wcsstr(prov_desc, buf);
2062 /* Check with and without parent-link. */
2063 if (!str)
2064 return FALSE;
2065
2066 if (!out_desc)
2067 return TRUE;
2068
2069 str += wcslen(buf);
2070 str2 = wcschr(str, L']');
2071 /* We want to include the ']' character, so + 2. */
2072 lstrcpynW(out_desc, str, ((str2 - str) + 2));
2073
2074 return TRUE;
2075}
2076
2077#define check_runtime_id( exp_runtime_id, exp_size, runtime_id ) \
2078 check_runtime_id_( (exp_runtime_id), (exp_size), (runtime_id), __FILE__, __LINE__)
2079static void check_runtime_id_(int *exp_runtime_id, int exp_size, SAFEARRAY *runtime_id, const char *file, int line)
2080{
2081 LONG i, idx, lbound, ubound, elems;
2082 HRESULT hr;
2083 UINT dims;
2084 int val;
2085
2086 dims = SafeArrayGetDim(runtime_id);
2087 ok_(file, line)(dims == 1, "Unexpected array dims %d\n", dims);
2088
2089 hr = SafeArrayGetLBound(runtime_id, 1, &lbound);
2090 ok_(file, line)(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
2091
2092 hr = SafeArrayGetUBound(runtime_id, 1, &ubound);
2093 ok_(file, line)(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
2094
2095 elems = (ubound - lbound) + 1;
2096 ok_(file, line)(exp_size == elems, "Unexpected runtime_id array size %#lx\n", elems);
2097
2098 for (i = 0; i < elems; i++)
2099 {
2100 idx = lbound + i;
2101 hr = SafeArrayGetElement(runtime_id, &idx, &val);
2102 ok_(file, line)(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
2103 ok_(file, line)(val == exp_runtime_id[i], "Unexpected runtime_id[%ld] %#x\n", i, val);
2104 }
2105}
2106
2107static inline struct Provider *impl_from_ProviderSimple(IRawElementProviderSimple *iface)
2108{
2110}
2111
2112HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
2113{
2114 struct Provider *This = impl_from_ProviderSimple(iface);
2115
2116 *ppv = NULL;
2117 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
2118 *ppv = iface;
2119 else if (IsEqualIID(riid, &IID_IRawElementProviderFragment))
2120 *ppv = &This->IRawElementProviderFragment_iface;
2121 else if (IsEqualIID(riid, &IID_IRawElementProviderFragmentRoot))
2122 *ppv = &This->IRawElementProviderFragmentRoot_iface;
2123 else if (IsEqualIID(riid, &IID_IRawElementProviderHwndOverride))
2124 *ppv = &This->IRawElementProviderHwndOverride_iface;
2125 else if (IsEqualIID(riid, &IID_IRawElementProviderAdviseEvents))
2126 *ppv = &This->IRawElementProviderAdviseEvents_iface;
2127 else if (IsEqualIID(riid, &IID_IValueProvider))
2128 *ppv = &This->IValueProvider_iface;
2129 else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider))
2130 *ppv = &This->ILegacyIAccessibleProvider_iface;
2131 else if (This->win_event_handler_data.is_supported && IsEqualIID(riid, &IID_IProxyProviderWinEventHandler))
2132 *ppv = &This->IProxyProviderWinEventHandler_iface;
2133 else
2134 return E_NOINTERFACE;
2135
2136 IRawElementProviderSimple_AddRef(iface);
2137 return S_OK;
2138}
2139
2140ULONG WINAPI ProviderSimple_AddRef(IRawElementProviderSimple *iface)
2141{
2142 struct Provider *This = impl_from_ProviderSimple(iface);
2143 return InterlockedIncrement(&This->ref);
2144}
2145
2146ULONG WINAPI ProviderSimple_Release(IRawElementProviderSimple *iface)
2147{
2148 struct Provider *This = impl_from_ProviderSimple(iface);
2149 return InterlockedDecrement(&This->ref);
2150}
2151
2152HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *iface,
2153 enum ProviderOptions *ret_val)
2154{
2155 struct Provider *This = impl_from_ProviderSimple(iface);
2156
2158 if (This->expected_tid)
2159 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2160 This->last_call_tid = GetCurrentThreadId();
2162 PROV_METHOD_TRACE(This, get_ProviderOptions);
2163
2164 *ret_val = 0;
2165 if (This->prov_opts)
2166 {
2167 *ret_val = This->prov_opts;
2168 return S_OK;
2169 }
2170
2171 return E_NOTIMPL;
2172}
2173
2174HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface,
2175 PATTERNID pattern_id, IUnknown **ret_val)
2176{
2177 struct Provider *This = impl_from_ProviderSimple(iface);
2178
2180 if (This->expected_tid)
2181 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2182 This->last_call_tid = GetCurrentThreadId();
2183 PROV_METHOD_TRACE2(This, GetPatternProvider, pattern_id, uia_pattern_id_strs);
2184
2185 *ret_val = NULL;
2186 switch (pattern_id)
2187 {
2188 case UIA_ValuePatternId:
2189 if (This->value_pattern_data.is_supported)
2190 *ret_val = (IUnknown *)iface;
2191 break;
2192
2193 case UIA_LegacyIAccessiblePatternId:
2194 if (This->legacy_acc_pattern_data.is_supported)
2195 *ret_val = (IUnknown *)iface;
2196 break;
2197
2198 default:
2199 break;
2200 }
2201
2202 if (*ret_val)
2203 IUnknown_AddRef(*ret_val);
2204
2206 return S_OK;
2207}
2208
2209HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface,
2210 PROPERTYID prop_id, VARIANT *ret_val)
2211{
2212 struct Provider *This = impl_from_ProviderSimple(iface);
2213
2215 if (This->expected_tid)
2216 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2217 This->last_call_tid = GetCurrentThreadId();
2219 PROV_METHOD_TRACE2(This, GetPropertyValue, prop_id, uia_prop_id_strs);
2220
2221 if (This->prop_override && This->prop_override_count)
2222 {
2223 int i;
2224
2225 for (i = 0; i < This->prop_override_count; i++)
2226 {
2227 if (This->prop_override[i].prop_id == prop_id)
2228 {
2229 *ret_val = This->prop_override[i].val;
2230 if (V_VT(ret_val) == VT_UNKNOWN)
2231 IUnknown_AddRef(V_UNKNOWN(ret_val));
2232
2233 return S_OK;
2234 }
2235 }
2236 }
2237
2238 VariantInit(ret_val);
2239 switch (prop_id)
2240 {
2241 case UIA_NativeWindowHandlePropertyId:
2242 if (This->ret_invalid_prop_type)
2243 {
2244 V_VT(ret_val) = VT_R8;
2245 V_R8(ret_val) = uia_r8_prop_val;
2246 }
2247 else if (!This->ignore_hwnd_prop)
2248 {
2249 V_VT(ret_val) = VT_I4;
2250 V_I4(ret_val) = HandleToULong(This->hwnd);
2251 }
2252 break;
2253
2254 case UIA_ProcessIdPropertyId:
2255 case UIA_ControlTypePropertyId:
2256 case UIA_CulturePropertyId:
2257 case UIA_OrientationPropertyId:
2258 case UIA_LiveSettingPropertyId:
2259 case UIA_PositionInSetPropertyId:
2260 case UIA_SizeOfSetPropertyId:
2261 case UIA_LevelPropertyId:
2262 case UIA_LandmarkTypePropertyId:
2263 case UIA_FillColorPropertyId:
2264 case UIA_FillTypePropertyId:
2265 case UIA_VisualEffectsPropertyId:
2266 case UIA_HeadingLevelPropertyId:
2267 if (This->ret_invalid_prop_type)
2268 {
2269 V_VT(ret_val) = VT_R8;
2270 V_R8(ret_val) = uia_r8_prop_val;
2271 }
2272 else
2273 {
2274 V_VT(ret_val) = VT_I4;
2275 V_I4(ret_val) = uia_i4_prop_val;
2276 }
2277 break;
2278
2279 case UIA_RotationPropertyId:
2280 if (This->ret_invalid_prop_type)
2281 {
2282 V_VT(ret_val) = VT_I4;
2283 V_I4(ret_val) = uia_i4_prop_val;
2284 }
2285 else
2286 {
2287 V_VT(ret_val) = VT_R8;
2288 V_R8(ret_val) = uia_r8_prop_val;
2289 }
2290 break;
2291
2292 case UIA_LocalizedControlTypePropertyId:
2293 case UIA_NamePropertyId:
2294 case UIA_AcceleratorKeyPropertyId:
2295 case UIA_AccessKeyPropertyId:
2296 case UIA_AutomationIdPropertyId:
2297 case UIA_ClassNamePropertyId:
2298 case UIA_HelpTextPropertyId:
2299 case UIA_ItemTypePropertyId:
2300 case UIA_FrameworkIdPropertyId:
2301 case UIA_ItemStatusPropertyId:
2302 case UIA_AriaRolePropertyId:
2303 case UIA_AriaPropertiesPropertyId:
2304 case UIA_LocalizedLandmarkTypePropertyId:
2305 case UIA_FullDescriptionPropertyId:
2306 if (This->ret_invalid_prop_type)
2307 {
2308 V_VT(ret_val) = VT_I4;
2309 V_I4(ret_val) = uia_i4_prop_val;
2310 }
2311 else
2312 {
2313 V_VT(ret_val) = VT_BSTR;
2315 }
2316 break;
2317
2318 case UIA_HasKeyboardFocusPropertyId:
2319 case UIA_IsKeyboardFocusablePropertyId:
2320 case UIA_IsEnabledPropertyId:
2321 case UIA_IsControlElementPropertyId:
2322 case UIA_IsContentElementPropertyId:
2323 case UIA_IsPasswordPropertyId:
2324 case UIA_IsOffscreenPropertyId:
2325 case UIA_IsRequiredForFormPropertyId:
2326 case UIA_IsDataValidForFormPropertyId:
2327 case UIA_OptimizeForVisualContentPropertyId:
2328 case UIA_IsPeripheralPropertyId:
2329 case UIA_IsDialogPropertyId:
2330 if (This->ret_invalid_prop_type)
2331 {
2332 V_VT(ret_val) = VT_R8;
2333 V_R8(ret_val) = uia_r8_prop_val;
2334 }
2335 else
2336 {
2337 V_VT(ret_val) = VT_BOOL;
2338 V_BOOL(ret_val) = VARIANT_TRUE;
2339 }
2340 break;
2341
2342 case UIA_AnnotationTypesPropertyId:
2343 case UIA_OutlineColorPropertyId:
2344 if (This->ret_invalid_prop_type)
2345 {
2346 V_VT(ret_val) = VT_ARRAY | VT_R8;
2347 V_ARRAY(ret_val) = create_r8_safearray();
2348 }
2349 else
2350 {
2351 V_VT(ret_val) = VT_ARRAY | VT_I4;
2352 V_ARRAY(ret_val) = create_i4_safearray();
2353 }
2354 break;
2355
2356 case UIA_OutlineThicknessPropertyId:
2357 case UIA_SizePropertyId:
2358 if (This->ret_invalid_prop_type)
2359 {
2360 V_VT(ret_val) = VT_ARRAY | VT_I4;
2361 V_ARRAY(ret_val) = create_i4_safearray();
2362 }
2363 else
2364 {
2365 V_VT(ret_val) = VT_ARRAY | VT_R8;
2366 V_ARRAY(ret_val) = create_r8_safearray();
2367 }
2368 break;
2369
2370 case UIA_LabeledByPropertyId:
2371 if (This->ret_invalid_prop_type)
2372 {
2373 V_VT(ret_val) = VT_I4;
2374 V_I4(ret_val) = uia_i4_prop_val;
2375 }
2376 else
2377 {
2378 V_VT(ret_val) = VT_UNKNOWN;
2379 V_UNKNOWN(ret_val) = (IUnknown *)&Provider_child.IRawElementProviderSimple_iface;
2380 IUnknown_AddRef(V_UNKNOWN(ret_val));
2381 }
2382 break;
2383
2384 case UIA_AnnotationObjectsPropertyId:
2385 case UIA_DescribedByPropertyId:
2386 case UIA_FlowsFromPropertyId:
2387 case UIA_FlowsToPropertyId:
2388 case UIA_ControllerForPropertyId:
2389 if (This->ret_invalid_prop_type)
2390 {
2391 V_VT(ret_val) = VT_ARRAY | VT_I4;
2392 V_ARRAY(ret_val) = create_i4_safearray();
2393 }
2394 else
2395 {
2396 V_VT(ret_val) = VT_UNKNOWN | VT_ARRAY;
2397 V_ARRAY(ret_val) = create_unk_safearray();
2398 }
2399 break;
2400
2401 case UIA_ProviderDescriptionPropertyId:
2402 {
2403#ifdef __REACTOS__
2404 WCHAR buf[1024];
2405#else
2406 WCHAR buf[1024] = {};
2407 memset(&buf, 0, sizeof(buf));
2408#endif
2409
2410 mbstowcs(buf, This->prov_name, strlen(This->prov_name));
2411 V_VT(ret_val) = VT_BSTR;
2412 V_BSTR(ret_val) = SysAllocString(buf);
2413 break;
2414 }
2415
2416 default:
2417 break;
2418 }
2419
2420 return S_OK;
2421}
2422
2424 IRawElementProviderSimple **ret_val)
2425{
2426 struct Provider *This = impl_from_ProviderSimple(iface);
2427
2429 if (This->expected_tid)
2430 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2431 This->last_call_tid = GetCurrentThreadId();
2433 PROV_METHOD_TRACE(This, get_HostRawElementProvider);
2434
2435 *ret_val = NULL;
2436 if (This->hwnd)
2437 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
2438
2439 return S_OK;
2440}
2441
2442IRawElementProviderSimpleVtbl ProviderSimpleVtbl = {
2450};
2451
2452static inline struct Provider *impl_from_ProviderFragment(IRawElementProviderFragment *iface)
2453{
2455}
2456
2457static HRESULT WINAPI ProviderFragment_QueryInterface(IRawElementProviderFragment *iface, REFIID riid,
2458 void **ppv)
2459{
2461 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2462}
2463
2464static ULONG WINAPI ProviderFragment_AddRef(IRawElementProviderFragment *iface)
2465{
2467 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2468}
2469
2470static ULONG WINAPI ProviderFragment_Release(IRawElementProviderFragment *iface)
2471{
2473 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2474}
2475
2476static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *iface,
2477 enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
2478{
2479 struct Provider *This = impl_from_ProviderFragment(iface);
2480
2482 if (This->expected_tid)
2483 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2484 This->last_call_tid = GetCurrentThreadId();
2486
2487 *ret_val = NULL;
2488 switch (direction)
2489 {
2491 *ret_val = This->parent;
2492 break;
2493
2495 *ret_val = This->next_sibling;
2496 break;
2497
2499 *ret_val = This->prev_sibling;
2500 break;
2501
2503 *ret_val = This->first_child;
2504 break;
2505
2507 *ret_val = This->last_child;
2508 break;
2509
2510 default:
2511 trace("Invalid navigate direction %d\n", direction);
2512 break;
2513 }
2514
2515 if (*ret_val)
2516 IRawElementProviderFragment_AddRef(*ret_val);
2517
2519 return S_OK;
2520}
2521
2522static HRESULT WINAPI ProviderFragment_GetRuntimeId(IRawElementProviderFragment *iface,
2523 SAFEARRAY **ret_val)
2524{
2525 struct Provider *This = impl_from_ProviderFragment(iface);
2526
2528 if (This->expected_tid)
2529 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2530 This->last_call_tid = GetCurrentThreadId();
2532 PROV_METHOD_TRACE(This, GetRuntimeId);
2533
2534 *ret_val = NULL;
2535 if (This->runtime_id[0] || This->runtime_id[1])
2536 {
2537 SAFEARRAY *sa;
2538 LONG idx;
2539
2540 if (!(sa = SafeArrayCreateVector(VT_I4, 0, ARRAY_SIZE(This->runtime_id))))
2541 return E_FAIL;
2542
2543 for (idx = 0; idx < ARRAY_SIZE(This->runtime_id); idx++)
2544 SafeArrayPutElement(sa, &idx, (void *)&This->runtime_id[idx]);
2545
2546 *ret_val = sa;
2547 }
2548
2549 return S_OK;
2550}
2551
2552static HRESULT WINAPI ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment *iface,
2553 struct UiaRect *ret_val)
2554{
2555 struct Provider *This = impl_from_ProviderFragment(iface);
2556
2558 if (This->expected_tid)
2559 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2560 This->last_call_tid = GetCurrentThreadId();
2562 PROV_METHOD_TRACE(This, get_BoundingRectangle);
2563
2564 *ret_val = This->bounds_rect;
2565 return S_OK;
2566}
2567
2568static HRESULT WINAPI ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface,
2569 SAFEARRAY **ret_val)
2570{
2571 struct Provider *This = impl_from_ProviderFragment(iface);
2572
2574 if (This->expected_tid)
2575 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2576 This->last_call_tid = GetCurrentThreadId();
2578 PROV_METHOD_TRACE(This, GetEmbeddedFragmentRoots);
2579
2580 *ret_val = NULL;
2581 if (This->embedded_frag_roots && This->embedded_frag_roots_count)
2582 {
2583 SAFEARRAY *sa;
2584 LONG idx;
2585
2586 if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, This->embedded_frag_roots_count)))
2587 return E_FAIL;
2588
2589 for (idx = 0; idx < This->embedded_frag_roots_count; idx++)
2590 SafeArrayPutElement(sa, &idx, (IUnknown *)This->embedded_frag_roots[idx]);
2591
2592 *ret_val = sa;
2593 }
2594
2595 return S_OK;
2596}
2597
2598static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *iface)
2599{
2600 ok(0, "unexpected call\n");
2601 return E_NOTIMPL;
2602}
2603
2604static HRESULT WINAPI ProviderFragment_get_FragmentRoot(IRawElementProviderFragment *iface,
2605 IRawElementProviderFragmentRoot **ret_val)
2606{
2607 struct Provider *This = impl_from_ProviderFragment(iface);
2608
2610 if (This->expected_tid)
2611 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2612 This->last_call_tid = GetCurrentThreadId();
2613 PROV_METHOD_TRACE(This, get_FragmentRoot);
2614
2615 *ret_val = NULL;
2616 if (This->frag_root)
2617 {
2618 *ret_val = This->frag_root;
2619 IRawElementProviderFragmentRoot_AddRef(This->frag_root);
2620 }
2621
2623 return S_OK;
2624}
2625
2626static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl = {
2636};
2637
2638static inline struct Provider *impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot *iface)
2639{
2641}
2642
2643static HRESULT WINAPI ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot *iface, REFIID riid,
2644 void **ppv)
2645{
2647 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2648}
2649
2650static ULONG WINAPI ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot *iface)
2651{
2653 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2654}
2655
2656static ULONG WINAPI ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot *iface)
2657{
2659 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2660}
2661
2662static HRESULT WINAPI ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot *iface,
2663 double x, double y, IRawElementProviderFragment **ret_val)
2664{
2665 ok(0, "unexpected call\n");
2666 return E_NOTIMPL;
2667}
2668
2669static HRESULT WINAPI ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot *iface,
2670 IRawElementProviderFragment **ret_val)
2671{
2673
2676 ok(Provider->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2679
2680 *ret_val = NULL;
2681 if (Provider->focus_prov)
2682 {
2683 *ret_val = Provider->focus_prov;
2684 IRawElementProviderFragment_AddRef(*ret_val);
2685 }
2686
2688 return S_OK;
2689}
2690
2691static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl = {
2697};
2698
2699static inline struct Provider *impl_from_ProviderHwndOverride(IRawElementProviderHwndOverride *iface)
2700{
2702}
2703
2704static HRESULT WINAPI ProviderHwndOverride_QueryInterface(IRawElementProviderHwndOverride *iface, REFIID riid,
2705 void **ppv)
2706{
2708 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2709}
2710
2711static ULONG WINAPI ProviderHwndOverride_AddRef(IRawElementProviderHwndOverride *iface)
2712{
2714 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2715}
2716
2717static ULONG WINAPI ProviderHwndOverride_Release(IRawElementProviderHwndOverride *iface)
2718{
2720 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2721}
2722
2723static HRESULT WINAPI ProviderHwndOverride_GetOverrideProviderForHwnd(IRawElementProviderHwndOverride *iface,
2724 HWND hwnd, IRawElementProviderSimple **ret_val)
2725{
2727
2730 PROV_METHOD_TRACE(This, GetOverrideProviderForHwnd);
2731
2732 *ret_val = NULL;
2733 if (This->override_hwnd == hwnd)
2734 {
2735 return IRawElementProviderSimple_QueryInterface(&Provider_override.IRawElementProviderSimple_iface,
2736 &IID_IRawElementProviderSimple, (void **)ret_val);
2737 }
2738
2739 return S_OK;
2740}
2741
2742static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl = {
2747};
2748
2749static inline struct Provider *impl_from_ProviderAdviseEvents(IRawElementProviderAdviseEvents *iface)
2750{
2752}
2753
2754static HRESULT WINAPI ProviderAdviseEvents_QueryInterface(IRawElementProviderAdviseEvents *iface, REFIID riid,
2755 void **ppv)
2756{
2758 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2759}
2760
2761static ULONG WINAPI ProviderAdviseEvents_AddRef(IRawElementProviderAdviseEvents *iface)
2762{
2764 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2765}
2766
2767static ULONG WINAPI ProviderAdviseEvents_Release(IRawElementProviderAdviseEvents *iface)
2768{
2770 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2771}
2772
2773static HRESULT WINAPI ProviderAdviseEvents_AdviseEventAdded(IRawElementProviderAdviseEvents *iface,
2774 EVENTID event_id, SAFEARRAY *prop_ids)
2775{
2777
2779 if (This->expected_tid)
2780 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2781 This->last_call_tid = GetCurrentThreadId();
2782 This->advise_events_added_event_id = event_id;
2783 PROV_METHOD_TRACE2(This, AdviseEventAdded, event_id, uia_event_id_strs);
2784
2786 return S_OK;
2787}
2788
2789static HRESULT WINAPI ProviderAdviseEvents_AdviseEventRemoved(IRawElementProviderAdviseEvents *iface,
2790 EVENTID event_id, SAFEARRAY *prop_ids)
2791{
2793
2795 if (This->expected_tid)
2796 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2797 This->last_call_tid = GetCurrentThreadId();
2798 This->advise_events_removed_event_id = event_id;
2799 PROV_METHOD_TRACE2(This, AdviseEventRemoved, event_id, uia_event_id_strs);
2800
2802 return S_OK;
2803}
2804
2805static const IRawElementProviderAdviseEventsVtbl ProviderAdviseEventsVtbl = {
2811};
2812
2813static inline struct Provider *impl_from_ProviderWinEventHandler(IProxyProviderWinEventHandler *iface)
2814{
2816}
2817
2818static HRESULT WINAPI ProviderWinEventHandler_QueryInterface(IProxyProviderWinEventHandler *iface, REFIID riid,
2819 void **ppv)
2820{
2822 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2823}
2824
2825static ULONG WINAPI ProviderWinEventHandler_AddRef(IProxyProviderWinEventHandler *iface)
2826{
2828 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2829}
2830
2831static ULONG WINAPI ProviderWinEventHandler_Release(IProxyProviderWinEventHandler *iface)
2832{
2834 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2835}
2836
2837static HRESULT WINAPI ProviderWinEventHandler_RespondToWinEvent(IProxyProviderWinEventHandler *iface,
2838 DWORD event_id, HWND hwnd, LONG obj_id, LONG child_id, IProxyProviderWinEventSink *event_sink)
2839{
2842 HRESULT hr;
2843
2844 PROV_METHOD_TRACE(This, RespondToWinEvent);
2845 data = &This->win_event_handler_data;
2846 if ((data->exp_win_event_id != event_id) || (data->exp_win_event_hwnd != hwnd) || (data->exp_win_event_obj_id != obj_id) ||
2847 (data->exp_win_event_child_id != child_id))
2848 return S_OK;
2849
2851 if (This->expected_tid)
2852 ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
2853 This->last_call_tid = GetCurrentThreadId();
2854
2855 if (data->responder_prov)
2856 {
2857 /*
2858 * The IProxyProviderWinEventSink interface uses the free threaded
2859 * marshaler, so no proxy will be created in-process.
2860 */
2861 check_interface_marshal_proxy_creation((IUnknown *)event_sink, &IID_IProxyProviderWinEventSink, FALSE);
2862 hr = IProxyProviderWinEventSink_AddAutomationEvent(event_sink, data->responder_prov, data->responder_event);
2863 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
2864 }
2865
2867 return S_OK;
2868}
2869
2870static const IProxyProviderWinEventHandlerVtbl ProviderWinEventHandlerVtbl = {
2875};
2876
2877static inline struct Provider *impl_from_ProviderValuePattern(IValueProvider *iface)
2878{
2879 return CONTAINING_RECORD(iface, struct Provider, IValueProvider_iface);
2880}
2881
2883 void **ppv)
2884{
2886 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2887}
2888
2889static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface)
2890{
2892 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2893}
2894
2895static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface)
2896{
2898 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2899}
2900
2902{
2903 ok(0, "unexpected call\n");
2904 return E_NOTIMPL;
2905}
2906
2907static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
2908{
2909 ok(0, "unexpected call\n");
2910 return E_NOTIMPL;
2911}
2912
2913static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val)
2914{
2916
2917 *ret_val = Provider->value_pattern_data.is_read_only;
2918
2919 return S_OK;
2920}
2921
2922static const IValueProviderVtbl ProviderValuePatternVtbl = {
2929};
2930
2931static inline struct Provider *impl_from_ProviderLegacyIAccessiblePattern(ILegacyIAccessibleProvider *iface)
2932{
2934}
2935
2937 void **ppv)
2938{
2940 return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
2941}
2942
2943static ULONG WINAPI ProviderLegacyIAccessiblePattern_AddRef(ILegacyIAccessibleProvider *iface)
2944{
2946 return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
2947}
2948
2949static ULONG WINAPI ProviderLegacyIAccessiblePattern_Release(ILegacyIAccessibleProvider *iface)
2950{
2952 return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
2953}
2954
2955static HRESULT WINAPI ProviderLegacyIAccessiblePattern_Select(ILegacyIAccessibleProvider *iface, LONG select_flags)
2956{
2957 ok(0, "unexpected call\n");
2958 return E_NOTIMPL;
2959}
2960
2961static HRESULT WINAPI ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider *iface)
2962{
2963 ok(0, "unexpected call\n");
2964 return E_NOTIMPL;
2965}
2966
2967static HRESULT WINAPI ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val)
2968{
2969 ok(0, "unexpected call\n");
2970 return E_NOTIMPL;
2971}
2972
2973static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider *iface,
2974 IAccessible **out_acc)
2975{
2976 ok(0, "unexpected call\n");
2977 return E_NOTIMPL;
2978}
2979
2980static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_ChildId(ILegacyIAccessibleProvider *iface, int *out_cid)
2981{
2983
2984 *out_cid = Provider->legacy_acc_pattern_data.child_id;
2985 return S_OK;
2986}
2987
2988static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name)
2989{
2990 ok(0, "unexpected call\n");
2991 return E_NOTIMPL;
2992}
2993
2994static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value)
2995{
2996 ok(0, "unexpected call\n");
2997 return E_NOTIMPL;
2998}
2999
3000static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider *iface,
3001 BSTR *out_description)
3002{
3003 ok(0, "unexpected call\n");
3004 return E_NOTIMPL;
3005}
3006
3007static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role)
3008{
3010
3011 *out_role = Provider->legacy_acc_pattern_data.role;
3012 return S_OK;
3013}
3014
3015static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
3016{
3017 ok(0, "unexpected call\n");
3018 return E_NOTIMPL;
3019}
3020
3021static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help)
3022{
3023 ok(0, "unexpected call\n");
3024 return E_NOTIMPL;
3025}
3026
3028 BSTR *out_kbd_shortcut)
3029{
3030 ok(0, "unexpected call\n");
3031 return E_NOTIMPL;
3032}
3033
3034static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider *iface,
3035 SAFEARRAY **out_selected)
3036{
3037 ok(0, "unexpected call\n");
3038 return E_NOTIMPL;
3039}
3040
3042 BSTR *out_default_action)
3043{
3044 ok(0, "unexpected call\n");
3045 return E_NOTIMPL;
3046}
3047
3048static const ILegacyIAccessibleProviderVtbl ProviderLegacyIAccessiblePatternVtbl = {
3066};
3067
3068static struct Provider Provider =
3069{
3070 { &ProviderSimpleVtbl },
3078 1,
3079 "Provider",
3080 NULL, NULL,
3081 NULL, NULL,
3082 &Provider_child.IRawElementProviderFragment_iface, &Provider_child2.IRawElementProviderFragment_iface,
3083 0, 0, 0,
3084};
3085
3086static struct Provider Provider2 =
3087{
3088 { &ProviderSimpleVtbl },
3096 1,
3097 "Provider2",
3098 NULL, NULL,
3099 NULL, NULL,
3100 NULL, NULL,
3101 0, 0, 0,
3102};
3103
3105{
3106 { &ProviderSimpleVtbl },
3114 1,
3115 "Provider_child",
3117 NULL, &Provider_child2.IRawElementProviderFragment_iface,
3118 NULL, NULL,
3120};
3121
3123{
3124 { &ProviderSimpleVtbl },
3132 1,
3133 "Provider_child2",
3135 &Provider_child.IRawElementProviderFragment_iface, NULL,
3136 NULL, NULL,
3138};
3139
3141{
3142 { &ProviderSimpleVtbl },
3150 1,
3151 "Provider_hwnd",
3152 NULL, NULL,
3153 NULL, NULL,
3154 NULL, NULL,
3156};
3157
3158static struct Provider Provider_nc =
3159{
3160 { &ProviderSimpleVtbl },
3168 1,
3169 "Provider_nc",
3170 NULL, NULL,
3171 NULL, NULL,
3172 NULL, NULL,
3174 0, 0,
3175};
3176
3178{
3179 { &ProviderSimpleVtbl },
3187 1,
3188 "Provider_proxy",
3189 NULL, NULL,
3190 NULL, NULL,
3191 NULL, NULL,
3193 0, 0,
3194};
3195
3197{
3198 { &ProviderSimpleVtbl },
3206 1,
3207 "Provider_proxy2",
3208 NULL, NULL,
3209 NULL, NULL,
3210 NULL, NULL,
3212 0, 0,
3213};
3214
3215static struct Provider Provider_override =
3216{
3217 { &ProviderSimpleVtbl },
3225 1,
3226 "Provider_override",
3227 NULL, NULL,
3228 NULL, NULL,
3229 NULL, NULL,
3231 0, 0,
3232};
3233
3234#define DEFINE_PROVIDER(name) \
3235 static struct Provider Provider_ ## name = \
3236 { \
3237 { &ProviderSimpleVtbl }, \
3238 { &ProviderFragmentVtbl }, \
3239 { &ProviderFragmentRootVtbl }, \
3240 { &ProviderHwndOverrideVtbl }, \
3241 { &ProviderAdviseEventsVtbl }, \
3242 { &ProviderWinEventHandlerVtbl }, \
3243 { &ProviderValuePatternVtbl }, \
3244 { &ProviderLegacyIAccessiblePatternVtbl }, \
3245 1, \
3246 "Provider_" # name "", \
3247 NULL, NULL, \
3248 NULL, NULL, \
3249 NULL, NULL, \
3250 ProviderOptions_ServerSideProvider, 0, 0 \
3251 }
3252
3254DEFINE_PROVIDER(hwnd_child2);
3257DEFINE_PROVIDER(child_child);
3258DEFINE_PROVIDER(child_child2);
3259DEFINE_PROVIDER(child2_child);
3260DEFINE_PROVIDER(child2_child_child);
3265
3267static IRawElementProviderSimple *prov_root;
3269{
3270 switch (message)
3271 {
3272 case WM_GETOBJECT:
3273 if (lParam == (DWORD)OBJID_CLIENT)
3274 {
3275 CHECK_EXPECT(winproc_GETOBJECT_CLIENT);
3276 if (acc_client)
3277 return LresultFromObject(&IID_IAccessible, wParam, (IUnknown *)acc_client);
3278
3279 break;
3280 }
3281 else if (lParam == UiaRootObjectId)
3282 {
3283 CHECK_EXPECT(winproc_GETOBJECT_UiaRoot);
3284 if (prov_root)
3286
3287 break;
3288 }
3289
3290 break;
3291
3292 default:
3293 break;
3294 }
3295
3297}
3298
3299static IRawElementProviderSimple *child_win_prov_root;
3301{
3302 switch (message)
3303 {
3304 case WM_GETOBJECT:
3305 if (lParam == UiaRootObjectId)
3306 {
3307 CHECK_EXPECT(child_winproc_GETOBJECT_UiaRoot);
3310
3311 break;
3312 }
3313
3314 break;
3315
3316 default:
3317 break;
3318 }
3319
3321}
3322
3324{
3325 IRawElementProviderSimple *p, *p2;
3326 enum ProviderOptions prov_opt;
3327 WNDCLASSA cls;
3328 HRESULT hr;
3329 HWND hwnd;
3330 VARIANT v;
3331 int i;
3332
3333 cls.style = 0;
3335 cls.cbClsExtra = 0;
3336 cls.cbWndExtra = 0;
3338 cls.hIcon = 0;
3339 cls.hCursor = NULL;
3340 cls.hbrBackground = NULL;
3341 cls.lpszMenuName = NULL;
3342 cls.lpszClassName = "HostProviderFromHwnd class";
3343
3344 RegisterClassA(&cls);
3345
3346 hwnd = CreateWindowExA(0, "HostProviderFromHwnd class", "Test window 1",
3348 0, 0, 100, 100, GetDesktopWindow(), NULL, GetModuleHandleA(NULL), NULL);
3349 ok(hwnd != NULL, "Failed to create a test window.\n");
3350
3351 p = (void *)0xdeadbeef;
3353 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3354 ok(p == NULL, "Unexpected instance.\n");
3355
3357 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3358
3359 p = NULL;
3361 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
3362
3363 p2 = NULL;
3365 ok(hr == S_OK, "Failed to get host provider, hr %#lx.\n", hr);
3366 ok(p != p2, "Unexpected instance.\n");
3367 IRawElementProviderSimple_Release(p2);
3368
3369 hr = IRawElementProviderSimple_get_HostRawElementProvider(p, &p2);
3370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3371 ok(p2 == NULL, "Unexpected instance.\n");
3372
3373 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
3374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3375 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
3376 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
3377
3378 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
3379 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3380 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3381 VariantClear(&v);
3382
3383 /* No patterns are implemented on the HWND Host provider. */
3384 for (i = UIA_InvokePatternId; i < (UIA_CustomNavigationPatternId + 1); i++)
3385 {
3386 IUnknown *unk;
3387
3388 unk = (void *)0xdeadbeef;
3389 hr = IRawElementProviderSimple_GetPatternProvider(p, i, &unk);
3390 ok(hr == S_OK, "Unexpected hr %#lx, %d.\n", hr, i);
3391 ok(!unk, "Pattern %d returned %p\n", i, unk);
3392 }
3393
3394 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
3395 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3396 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
3397 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3398 "Unexpected provider options %#x\n", prov_opt);
3399
3400 /* Test behavior post Window destruction. */
3402
3403 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_NativeWindowHandlePropertyId, &v);
3404 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3405 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
3406 ok(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
3407
3408 hr = IRawElementProviderSimple_GetPropertyValue(p, UIA_ProviderDescriptionPropertyId, &v);
3409 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3410 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
3411 VariantClear(&v);
3412
3413 hr = IRawElementProviderSimple_get_ProviderOptions(p, &prov_opt);
3414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3415 ok((prov_opt == ProviderOptions_ServerSideProvider) ||
3416 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
3417 "Unexpected provider options %#x\n", prov_opt);
3418
3419 IRawElementProviderSimple_Release(p);
3420
3421 UnregisterClassA("HostProviderFromHwnd class", NULL);
3422}
3423
3425{
3426 IStream **stream = param;
3427 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
3428 HRESULT hr;
3429
3431
3432 hr = CoGetInterfaceAndReleaseStream(stream[0], &IID_IUnknown, (void **)&unk_ns);
3433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3434
3435 hr = CoGetInterfaceAndReleaseStream(stream[1], &IID_IUnknown, (void **)&unk_ma);
3436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3437
3439 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3440
3442 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3443
3444 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
3445 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
3446
3448
3449 return 0;
3450}
3451
3453{
3454 IUnknown *unk_ns, *unk_ns2, *unk_ma, *unk_ma2;
3455 IStream *stream[2];
3456 IMarshal *marshal;
3457 HANDLE thread;
3458 ULONG refcnt;
3459 HRESULT hr;
3460
3461 /* ReservedNotSupportedValue. */
3463 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3464
3466 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3467 ok(unk_ns != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.\n");
3468
3469 refcnt = IUnknown_AddRef(unk_ns);
3470 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3471
3472 refcnt = IUnknown_AddRef(unk_ns);
3473 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3474
3475 refcnt = IUnknown_Release(unk_ns);
3476 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3477
3479 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3480 ok(unk_ns2 != NULL, "UiaGetReservedNotSupportedValue returned NULL interface.");
3481 ok(unk_ns2 == unk_ns, "UiaGetReservedNotSupported pointer mismatch, unk_ns2 %p, unk_ns %p\n", unk_ns2, unk_ns);
3482
3483 marshal = NULL;
3484 hr = IUnknown_QueryInterface(unk_ns, &IID_IMarshal, (void **)&marshal);
3485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3486 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
3487
3488 refcnt = IMarshal_AddRef(marshal);
3489 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
3490
3491 refcnt = IMarshal_Release(marshal);
3492 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3493
3494 refcnt = IMarshal_Release(marshal);
3495 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
3496
3497 /* ReservedMixedAttributeValue. */
3499 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
3500
3502 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3503 ok(unk_ma != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
3504
3505 refcnt = IUnknown_AddRef(unk_ma);
3506 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3507
3508 refcnt = IUnknown_AddRef(unk_ma);
3509 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3510
3511 refcnt = IUnknown_Release(unk_ma);
3512 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3513
3515 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3516 ok(unk_ma2 != NULL, "UiaGetReservedMixedAttributeValue returned NULL interface.");
3517 ok(unk_ma2 == unk_ma, "UiaGetReservedMixedAttribute pointer mismatch, unk_ma2 %p, unk_ma %p\n", unk_ma2, unk_ma);
3518
3519 marshal = NULL;
3520 hr = IUnknown_QueryInterface(unk_ma, &IID_IMarshal, (void **)&marshal);
3521 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3522 ok(marshal != NULL, "Failed to get IMarshal interface.\n");
3523
3524 refcnt = IMarshal_AddRef(marshal);
3525 ok(refcnt == 2, "Expected refcnt %d, got %ld\n", 2, refcnt);
3526
3527 refcnt = IMarshal_Release(marshal);
3528 ok(refcnt == 1, "Expected refcnt %d, got %ld\n", 1, refcnt);
3529
3530 refcnt = IMarshal_Release(marshal);
3531 ok(refcnt == 0, "Expected refcnt %d, got %ld\n", 0, refcnt);
3532
3533 /* Test cross-thread marshaling behavior. */
3535
3537 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3540
3543 {
3544 MSG msg;
3545 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
3546 {
3549 }
3550 }
3552
3554}
3555
3556static struct ProxyEventSink
3557{
3558 IProxyProviderWinEventSink IProxyProviderWinEventSink_iface;
3560
3561 IRawElementProviderSimple *event_elprov;
3563
3564 IRawElementProviderSimple *prop_change_elprov;
3567
3568 IRawElementProviderSimple *structure_change_elprov;
3572
3573static void proxy_event_sink_clear(void)
3574{
3576 IRawElementProviderSimple_Release(ProxyEventSink.event_elprov);
3579
3581 IRawElementProviderSimple_Release(ProxyEventSink.prop_change_elprov);
3585
3587 IRawElementProviderSimple_Release(ProxyEventSink.structure_change_elprov);
3591}
3592
3593static inline struct ProxyEventSink *impl_from_ProxyEventSink(IProxyProviderWinEventSink *iface)
3594{
3596}
3597
3598static HRESULT WINAPI ProxyEventSink_QueryInterface(IProxyProviderWinEventSink *iface, REFIID riid, void **obj)
3599{
3600 *obj = NULL;
3601 if (IsEqualIID(riid, &IID_IProxyProviderWinEventSink) || IsEqualIID(riid, &IID_IUnknown))
3602 *obj = iface;
3603 else
3604 return E_NOINTERFACE;
3605
3606 IProxyProviderWinEventSink_AddRef(iface);
3607 return S_OK;
3608}
3609
3610static ULONG WINAPI ProxyEventSink_AddRef(IProxyProviderWinEventSink *iface)
3611{
3613 return InterlockedIncrement(&This->ref);
3614}
3615
3616static ULONG WINAPI ProxyEventSink_Release(IProxyProviderWinEventSink *iface)
3617{
3619 return InterlockedDecrement(&This->ref);
3620}
3621
3622static HRESULT WINAPI ProxyEventSink_AddAutomationPropertyChangedEvent(IProxyProviderWinEventSink *iface,
3623 IRawElementProviderSimple *elprov, PROPERTYID prop_id, VARIANT new_value)
3624{
3626
3628 This->prop_change_elprov = elprov;
3629 if (elprov)
3630 IRawElementProviderSimple_AddRef(elprov);
3631
3632 This->prop_change_prop_id = prop_id;
3633 VariantCopy(&This->prop_change_value, &new_value);
3634
3635 return S_OK;
3636}
3637
3638static HRESULT WINAPI ProxyEventSink_AddAutomationEvent(IProxyProviderWinEventSink *iface,
3639 IRawElementProviderSimple *elprov, EVENTID event_id)
3640{
3642
3644 This->event_elprov = elprov;
3645 if (elprov)
3646 IRawElementProviderSimple_AddRef(elprov);
3647 This->event_id = event_id;
3648
3649 return S_OK;
3650}
3651
3652static HRESULT WINAPI ProxyEventSink_AddStructureChangedEvent(IProxyProviderWinEventSink *iface,
3653 IRawElementProviderSimple *elprov, enum StructureChangeType structure_change_type, SAFEARRAY *runtime_id)
3654{
3656 HRESULT hr;
3657
3659 This->structure_change_elprov = elprov;
3660 if (elprov)
3661 IRawElementProviderSimple_AddRef(elprov);
3662 This->structure_change_type = structure_change_type;
3663
3664 hr = SafeArrayCopy(runtime_id, &This->structure_change_rt_id);
3665 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3666
3667 return S_OK;
3668}
3669
3670static const IProxyProviderWinEventSinkVtbl ProxyEventSinkVtbl = {
3677};
3678
3680{
3681 { &ProxyEventSinkVtbl },
3682 1,
3683};
3684
3685static void set_accessible_props(struct Accessible *acc, INT role, INT state,
3686 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height);
3687static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id);
3689{
3690 IProxyProviderWinEventHandler *handler;
3691 IRawElementProviderSimple *elprov;
3692 HRESULT hr;
3693
3694 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
3696 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3697 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3698
3699 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IProxyProviderWinEventHandler, (void **)&handler);
3700 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3701 ok(!!handler, "Handler == NULL\n");
3702
3703 /* EVENT_SYSTEM_ALERT */
3705 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_SYSTEM_ALERT, hwnd, OBJID_CLIENT, CHILDID_SELF,
3707 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3709 ok(ProxyEventSink.event_id == UIA_SystemAlertEventId, "Unexpected event_id %d\n", ProxyEventSink.event_id);
3710 ok(ProxyEventSink.event_elprov == elprov, "Unexpected event_elprov %p\n", ProxyEventSink.event_elprov);
3712
3713 /* EVENT_OBJECT_FOCUS is not handled. */
3714 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, CHILDID_SELF,
3716 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3717
3718 /* EVENT_OBJECT_NAMECHANGE. */
3720 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
3721 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF,
3723 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3724 todo_wine ok(ProxyEventSink.prop_change_elprov == elprov, "Unexpected prop_change_elprov %p\n", ProxyEventSink.prop_change_elprov);
3725 todo_wine ok(ProxyEventSink.prop_change_prop_id == UIA_NamePropertyId, "Unexpected prop_change_prop_id %d\n",
3727 todo_wine ok(V_VT(&ProxyEventSink.prop_change_value) == VT_BSTR, "Unexpected prop_change_value vt %d\n",
3730 ok(!lstrcmpW(V_BSTR(&ProxyEventSink.prop_change_value), Accessible.name), "Unexpected BSTR %s\n",
3735
3736 /* EVENT_OBJECT_REORDER. */
3738 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3740 hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_REORDER, hwnd, OBJID_CLIENT, CHILDID_SELF,
3742 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3743 todo_wine ok(ProxyEventSink.structure_change_elprov == elprov, "Unexpected structure_change_elprov %p\n",
3747 ok(!ProxyEventSink.structure_change_rt_id, "structure_change_rt_id != NULL\n");
3748 todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3751
3752 acc_client = NULL;
3753 IProxyProviderWinEventHandler_Release(handler);
3754 IRawElementProviderSimple_Release(elprov);
3755}
3756
3757DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
3759{
3761 HRESULT hr;
3762
3763 hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void**)&sp);
3764 if (SUCCEEDED(hr))
3765 {
3766 IAccessible *acc2 = NULL;
3767
3768 hr = IServiceProvider_QueryService(sp, &SID_AccFromDAWrapper, &IID_IAccessible, (void**)&acc2);
3769 IServiceProvider_Release(sp);
3770 if (SUCCEEDED(hr) && acc2)
3771 return acc2;
3772 }
3773
3774 return NULL;
3775}
3776
3777#define check_msaa_prov_acc( elprov, acc, cid) \
3778 check_msaa_prov_acc_( ((IUnknown *)elprov), (acc), (cid), __LINE__)
3779static void check_msaa_prov_acc_(IUnknown *elprov, IAccessible *acc, INT cid, int line)
3780{
3781 ILegacyIAccessibleProvider *accprov;
3782 IAccessible *acc2, *acc3;
3783 INT child_id;
3784 HRESULT hr;
3785
3786 hr = IUnknown_QueryInterface(elprov, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
3787 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3788 ok_(__FILE__, line)(!!accprov, "accprov == NULL\n");
3789
3790 acc2 = acc3 = NULL;
3791 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc2);
3792 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3793
3794 /*
3795 * Potentially get our IAccessible out of a direct annotation wrapper
3796 * IAccessible.
3797 */
3798 if (acc && acc2 && (acc != acc2) && (acc3 = msaa_acc_da_unwrap(acc2)))
3799 {
3800 IAccessible_Release(acc2);
3801 acc2 = acc3;
3802 }
3803 ok_(__FILE__, line)(acc2 == acc, "acc2 != acc\n");
3804 if (acc2)
3805 IAccessible_Release(acc2);
3806
3807 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
3808 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3809 ok_(__FILE__, line)(child_id == cid, "child_id != cid\n");
3810
3811 ILegacyIAccessibleProvider_Release(accprov);
3812}
3813
3814#define check_msaa_prov_host_elem_prov( elem, exp_host_prov) \
3815 check_msaa_prov_host_elem_prov_( ((IUnknown *)elem), (exp_host_prov), __LINE__)
3816static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov, int line)
3817{
3818 IRawElementProviderSimple *elprov, *elprov2;
3819 HRESULT hr;
3820
3821 hr = IUnknown_QueryInterface(elem, &IID_IRawElementProviderSimple, (void **)&elprov);
3822 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3823 ok_(__FILE__, line)(!!elprov, "elprov == NULL\n");
3824
3825 elprov2 = (void *)0xdeadbeef;
3826 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
3827 ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3828 ok_(__FILE__, line)((elprov2 != (void *)0xdeadbeef) && !!elprov2 == exp_host_prov, "Unexpected provider %p from get_HostRawElementProvider\n", elprov2);
3829
3830 if (elprov2)
3831 IRawElementProviderSimple_Release(elprov2);
3832 IRawElementProviderSimple_Release(elprov);
3833}
3834
3836{
3837 IRawElementProviderFragmentRoot *elroot, *elroot2;
3838 IRawElementProviderFragment *elfrag, *elfrag2;
3839 IRawElementProviderSimple *elprov;
3840 SAFEARRAY *ret_arr;
3841 ULONG old_ref;
3842 HRESULT hr;
3843
3844 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
3847
3848 elprov = NULL;
3849 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
3850 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3851 ok(!!elprov, "elprov == NULL\n");
3852
3853 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
3854 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3855 ok(!!elfrag, "elfrag == NULL\n");
3856
3857 /* GetEmbeddedFragmentRoots test. */
3858 ret_arr = (void *)0xdeadbeef;
3859 hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &ret_arr);
3860 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3861 ok(!ret_arr, "ret_arr != NULL\n");
3862
3863 /*
3864 * get_FragmentRoot does the equivalent of calling
3865 * AccessibleObjectFromWindow with OBJID_CLIENT on the HWND associated
3866 * with our IAccessible. Unlike UiaProviderFromIAccessible, it will create
3867 * a provider from a default oleacc proxy.
3868 */
3869 elroot = NULL;
3870 acc_client = NULL;
3871 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3872 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3874 ok(!!elroot, "elroot == NULL\n");
3875 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3876
3877 /*
3878 * ILegacyIAccessibleProvider::GetIAccessible returns a NULL
3879 * IAccessible if the provider represents an oleacc proxy.
3880 */
3882
3883 /*
3884 * Returns a provider from get_HostRawElementProvider without having
3885 * to query the HWND.
3886 */
3888
3889 hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
3890 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3891 ok(!!elfrag2, "elfrag2 == NULL\n");
3892
3893 /*
3894 * Even on a provider retrieved from get_FragmentRoot, the HWND is
3895 * queried and a new fragment root is returned rather than just
3896 * returning our current fragment root interface.
3897 */
3898 elroot2 = NULL;
3899 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3900 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
3901 IRawElementProviderFragment_Release(elfrag2);
3902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3903 ok(!!elroot2, "elroot2 == NULL\n");
3905 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3906
3907 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
3908 IRawElementProviderFragmentRoot_Release(elroot2);
3909 IRawElementProviderFragmentRoot_Release(elroot);
3910
3911 /*
3912 * Accessible is now the IAccessible for our HWND, so we'll get it instead
3913 * of an oleacc proxy.
3914 */
3916 elroot = NULL;
3917 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3918 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
3919 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3920 ok(!!elroot, "elroot == NULL\n");
3921 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3923
3924 /*
3925 * Returns a provider from get_HostRawElementProvider without having
3926 * to query the HWND, same as before.
3927 */
3929
3930 hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
3931 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3932 ok(!!elfrag2, "elfrag2 == NULL\n");
3933
3934 /* Same deal as before, unique FragmentRoot even on a known root. */
3935 elroot2 = NULL;
3936 SET_EXPECT(winproc_GETOBJECT_CLIENT);
3937 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
3938 IRawElementProviderFragment_Release(elfrag2);
3939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3940 ok(!!elroot2, "elroot2 == NULL\n");
3942 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
3943
3944 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
3945 IRawElementProviderFragmentRoot_Release(elroot2);
3946
3947 IRawElementProviderFragmentRoot_Release(elroot);
3948 IRawElementProviderFragment_Release(elfrag);
3949
3950 /*
3951 * IRawElementProviderFragmentRoot::GetFocus will call get_accFocus.
3952 */
3953 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
3954 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3955 ok(!!elroot, "elroot == NULL\n");
3956
3957 /* Focus is CHILDID_SELF, returns NULL. */
3958 elfrag = (void *)0xdeadbeef;
3960 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
3961 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
3962 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3963 ok(!elfrag, "elfrag != NULL\n");
3964 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
3965
3966 /*
3967 * get_accFocus returns child ID 1, which is a simple child element.
3968 * get_accState for child ID 1 returns STATE_SYSTEM_INVISIBLE, so no
3969 * element will be returned.
3970 */
3971 elfrag = (void *)0xdeadbeef;
3973
3974 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
3975 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
3976 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
3977 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
3978 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3979 ok(!elfrag, "elfrag != NULL\n");
3980 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
3981 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
3982 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
3983
3984 /*
3985 * get_accFocus returns child ID 3, which is another simple child
3986 * element. get_accState for child ID 3 does not have
3987 * STATE_SYSTEM_INVISIBLE set, so it will return an element.
3988 */
3989 elfrag = (void *)0xdeadbeef;
3991
3992 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
3993 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
3994 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
3995 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
3996 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
3997 ok(!!elfrag, "elfrag == NULL\n");
3999 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4000 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4001 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4002
4003 IRawElementProviderFragment_Release(elfrag);
4004
4005 /*
4006 * get_accFocus returns child ID 2 which is a full IAccessible,
4007 * Accessible_child.
4008 */
4009 elfrag = (void *)0xdeadbeef;
4012
4013 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4014 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4016 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4019 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4020 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4021 ok(!!elfrag, "elfrag == NULL\n");
4022 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4023 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4028
4029 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4030 IRawElementProviderFragment_Release(elfrag);
4031
4032 /*
4033 * get_accFocus returns child ID 2 which is a full IAccessible,
4034 * Accessible_child. It returns failure from get_accState so it isn't
4035 * returned.
4036 */
4037 elfrag = (void *)0xdeadbeef;
4039 Accessible_child.state = 0;
4040
4041 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4042 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4044 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4046 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4047 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4048 ok(!elfrag, "elfrag != NULL\n");
4049 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4050 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4054
4055 /*
4056 * get_accFocus returns child ID 7 which is a full IAccessible,
4057 * Accessible. This is the same IAccessible interface as the one we called
4058 * get_accFocus on, so it is ignored. Same behavior as CHILDID_SELF.
4059 */
4060 elfrag = (void *)0xdeadbeef;
4063
4064 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4065 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4066 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4067 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4069 ok(!elfrag, "elfrag != NULL\n");
4070 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4071 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4072 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4073
4074 /*
4075 * Return E_NOTIMPL from get_accFocus, returns a new provider representing
4076 * the same IAccessible.
4077 */
4078 elfrag = (void *)0xdeadbeef;
4079 old_ref = Accessible.ref;
4081
4082 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4083 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4084 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4085 ok(!!elfrag, "elfrag == NULL\n");
4086 ok(Accessible.ref > old_ref, "Unexpected ref %ld\n", Accessible.ref);
4087 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4088
4089 /* Two unique COM objects that represent the same IAccessible. */
4090 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elfrag), "elroot == elfrag\n");
4092 IRawElementProviderFragment_Release(elfrag);
4093 ok(Accessible.ref == old_ref, "Unexpected ref %ld\n", Accessible.ref);
4095
4096 /*
4097 * Similar to CHILDID_SELF, if the same IAccessible interface is returned
4098 * as a VT_DISPATCH, we'll get no element.
4099 */
4100 elfrag = (void *)0xdeadbeef;
4102
4103 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4104 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4105 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4107 ok(!elfrag, "elfrag != NULL\n");
4108 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4109 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4110
4111 /*
4112 * Return Accessible_child as a VT_DISPATCH - will get an element.
4113 */
4114 elfrag = (void *)0xdeadbeef;
4115 Accessible.focus_acc = &Accessible_child.IAccessible_iface;
4117
4118 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4120 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4123 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4124 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4125 ok(!!elfrag, "elfrag == NULL\n");
4126 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4131
4132 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4133 IRawElementProviderFragment_Release(elfrag);
4134
4135 /*
4136 * Fail get_accFocus on child.
4137 */
4138 Accessible_child.focus_child_id = -1;
4140
4141 elfrag = (void *)0xdeadbeef;
4142 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
4144 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4147 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4148 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4149 ok(!!elfrag, "elfrag == NULL\n");
4150 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
4155
4156 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4157 IRawElementProviderFragment_Release(elfrag);
4158
4159 IRawElementProviderFragmentRoot_Release(elroot);
4160 IRawElementProviderSimple_Release(elprov);
4161
4162 /*
4163 * Test simple child element.
4164 */
4165 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
4166 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4167
4168 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4169 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4170 ok(!!elfrag, "elfrag == NULL\n");
4171
4172 /* GetEmbeddedFragmentRoots test. */
4173 ret_arr = (void *)0xdeadbeef;
4174 hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &ret_arr);
4175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4176 ok(!ret_arr, "ret_arr != NULL\n");
4177
4178 /*
4179 * Simple child element queries HWND as well, does not just return its
4180 * parent.
4181 */
4182 elroot = NULL;
4183 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4184 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
4185 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4186 ok(!!elroot, "elroot == NULL\n");
4187 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4190
4191 IRawElementProviderFragmentRoot_Release(elroot);
4192 IRawElementProviderFragment_Release(elfrag);
4193
4194 /*
4195 * IRawElementProviderFragmentRoot::GetFocus will not call get_accFocus
4196 * on a simple child IAccessible.
4197 */
4198 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
4199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4200 ok(!!elroot, "elroot == NULL\n");
4201
4202 elfrag = (void *)0xdeadbeef;
4203 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4205 ok(!elfrag, "elfrag != NULL\n");
4206
4207 IRawElementProviderFragmentRoot_Release(elroot);
4208 IRawElementProviderSimple_Release(elprov);
4209
4210 /*
4211 * Test child of root HWND IAccessible.
4212 */
4213 set_accessible_props(&Accessible_child, ROLE_SYSTEM_TEXT, 0, 0, L"acc_child_name", 0, 0, 0, 0);
4215
4216 elprov = NULL;
4217 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent); /* Gets HWND from parent IAccessible. */
4219 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4220 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4221 ok(!!elprov, "elprov == NULL\n");
4224
4225 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4226 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4227 ok(!!elfrag, "elfrag == NULL\n");
4228
4229 /* GetEmbeddedFragmentRoots test. */
4230 ret_arr = (void *)0xdeadbeef;
4231 hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &ret_arr);
4232 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4233 ok(!ret_arr, "ret_arr != NULL\n");
4234
4235 /*
4236 * Again, same behavior as simple children. It doesn't just retrieve the
4237 * parent IAccessible, it queries the HWND.
4238 */
4239 elroot = NULL;
4240 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4241 hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
4242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4243 ok(!!elroot, "elroot == NULL\n");
4244 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4246
4247 IRawElementProviderFragmentRoot_Release(elroot);
4248 IRawElementProviderFragment_Release(elfrag);
4249
4250 /*
4251 * GetFocus tests.
4252 */
4253 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
4254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4255 ok(!!elroot, "elroot == NULL\n");
4256
4257 /*
4258 * get_accFocus returns E_NOTIMPL, returns new provider for same
4259 * IAccessible.
4260 */
4261 elfrag = (void *)0xdeadbeef;
4262 old_ref = Accessible_child.ref;
4263 Accessible_child.focus_child_id = -1;
4265 hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
4266 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4267 ok(!!elfrag, "elfrag == NULL\n");
4268 ok(Accessible_child.ref > old_ref, "Unexpected ref %ld\n", Accessible.ref);
4270
4271 /* Again, two unique COM objects that represent the same IAccessible. */
4272 ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elfrag), "elroot == elfrag\n");
4273 check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4274 IRawElementProviderFragment_Release(elfrag);
4275 ok(Accessible_child.ref == old_ref, "Unexpected ref %ld\n", Accessible.ref);
4276
4277 IRawElementProviderFragmentRoot_Release(elroot);
4278 IRawElementProviderSimple_Release(elprov);
4279
4281 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4282 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4283 acc_client = NULL;
4284}
4285
4289};
4290
4292 { ROLE_SYSTEM_TITLEBAR, UIA_TitleBarControlTypeId },
4293 { ROLE_SYSTEM_MENUBAR, UIA_MenuBarControlTypeId },
4294 { ROLE_SYSTEM_SCROLLBAR, UIA_ScrollBarControlTypeId },
4295 { ROLE_SYSTEM_GRIP, UIA_ThumbControlTypeId },
4296 { ROLE_SYSTEM_WINDOW, UIA_WindowControlTypeId },
4297 { ROLE_SYSTEM_MENUPOPUP, UIA_MenuControlTypeId },
4298 { ROLE_SYSTEM_MENUITEM, UIA_MenuItemControlTypeId },
4299 { ROLE_SYSTEM_TOOLTIP, UIA_ToolTipControlTypeId },
4300 { ROLE_SYSTEM_APPLICATION, UIA_WindowControlTypeId },
4301 { ROLE_SYSTEM_DOCUMENT, UIA_DocumentControlTypeId },
4302 { ROLE_SYSTEM_PANE, UIA_PaneControlTypeId },
4303 { ROLE_SYSTEM_GROUPING, UIA_GroupControlTypeId },
4304 { ROLE_SYSTEM_SEPARATOR, UIA_SeparatorControlTypeId },
4305 { ROLE_SYSTEM_TOOLBAR, UIA_ToolBarControlTypeId },
4306 { ROLE_SYSTEM_STATUSBAR, UIA_StatusBarControlTypeId },
4307 { ROLE_SYSTEM_TABLE, UIA_TableControlTypeId },
4308 { ROLE_SYSTEM_COLUMNHEADER, UIA_HeaderControlTypeId },
4309 { ROLE_SYSTEM_ROWHEADER, UIA_HeaderControlTypeId },
4310 { ROLE_SYSTEM_CELL, UIA_DataItemControlTypeId },
4311 { ROLE_SYSTEM_LINK, UIA_HyperlinkControlTypeId },
4312 { ROLE_SYSTEM_LIST, UIA_ListControlTypeId },
4313 { ROLE_SYSTEM_LISTITEM, UIA_ListItemControlTypeId },
4314 { ROLE_SYSTEM_OUTLINE, UIA_TreeControlTypeId },
4315 { ROLE_SYSTEM_OUTLINEITEM, UIA_TreeItemControlTypeId },
4316 { ROLE_SYSTEM_PAGETAB, UIA_TabItemControlTypeId },
4317 { ROLE_SYSTEM_INDICATOR, UIA_ThumbControlTypeId },
4318 { ROLE_SYSTEM_GRAPHIC, UIA_ImageControlTypeId },
4319 { ROLE_SYSTEM_STATICTEXT, UIA_TextControlTypeId },
4320 { ROLE_SYSTEM_TEXT, UIA_EditControlTypeId },
4321 { ROLE_SYSTEM_PUSHBUTTON, UIA_ButtonControlTypeId },
4322 { ROLE_SYSTEM_CHECKBUTTON, UIA_CheckBoxControlTypeId },
4323 { ROLE_SYSTEM_RADIOBUTTON, UIA_RadioButtonControlTypeId },
4324 { ROLE_SYSTEM_COMBOBOX, UIA_ComboBoxControlTypeId },
4325 { ROLE_SYSTEM_PROGRESSBAR, UIA_ProgressBarControlTypeId },
4326 { ROLE_SYSTEM_SLIDER, UIA_SliderControlTypeId },
4327 { ROLE_SYSTEM_SPINBUTTON, UIA_SpinnerControlTypeId },
4328 { ROLE_SYSTEM_BUTTONDROPDOWN, UIA_SplitButtonControlTypeId },
4329 { ROLE_SYSTEM_BUTTONMENU, UIA_MenuItemControlTypeId },
4330 { ROLE_SYSTEM_BUTTONDROPDOWNGRID, UIA_ButtonControlTypeId },
4331 { ROLE_SYSTEM_PAGETABLIST, UIA_TabControlTypeId },
4332 { ROLE_SYSTEM_SPLITBUTTON, UIA_SplitButtonControlTypeId },
4333 /* These accessible roles have no equivalent in UI Automation. */
4334 { ROLE_SYSTEM_SOUND, 0 },
4335 { ROLE_SYSTEM_CURSOR, 0 },
4336 { ROLE_SYSTEM_CARET, 0 },
4337 { ROLE_SYSTEM_ALERT, 0 },
4338 { ROLE_SYSTEM_CLIENT, 0 },
4339 { ROLE_SYSTEM_CHART, 0 },
4340 { ROLE_SYSTEM_DIALOG, 0 },
4341 { ROLE_SYSTEM_BORDER, 0 },
4342 { ROLE_SYSTEM_COLUMN, 0 },
4343 { ROLE_SYSTEM_ROW, 0 },
4344 { ROLE_SYSTEM_HELPBALLOON, 0 },
4345 { ROLE_SYSTEM_CHARACTER, 0 },
4346 { ROLE_SYSTEM_PROPERTYPAGE, 0 },
4347 { ROLE_SYSTEM_DROPLIST, 0 },
4348 { ROLE_SYSTEM_DIAL, 0 },
4349 { ROLE_SYSTEM_HOTKEYFIELD, 0 },
4350 { ROLE_SYSTEM_DIAGRAM, 0 },
4351 { ROLE_SYSTEM_ANIMATION, 0 },
4352 { ROLE_SYSTEM_EQUATION, 0 },
4353 { ROLE_SYSTEM_WHITESPACE, 0 },
4354 { ROLE_SYSTEM_IPADDRESS, 0 },
4355 { ROLE_SYSTEM_OUTLINEBUTTON, 0 },
4356};
4357
4361};
4362
4364 { STATE_SYSTEM_FOCUSED, UIA_HasKeyboardFocusPropertyId },
4365 { STATE_SYSTEM_FOCUSABLE, UIA_IsKeyboardFocusablePropertyId },
4366 { ~STATE_SYSTEM_UNAVAILABLE, UIA_IsEnabledPropertyId },
4367 { STATE_SYSTEM_PROTECTED, UIA_IsPasswordPropertyId },
4368};
4369
4370static void set_accessible_props(struct Accessible *acc, INT role, INT state,
4371 LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height)
4372{
4373
4374 acc->role = role;
4375 acc->state = state;
4376 acc->child_count = child_count;
4377 acc->name = name;
4378 acc->left = left;
4379 acc->top = top;
4380 acc->width = width;
4381 acc->height = height;
4382}
4383
4384static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id)
4385{
4386 acc->enable_ia2 = enable_ia2;
4387 acc->unique_id = unique_id;
4388}
4389
4391{
4392 IRawElementProviderSimple *elprov, *elprov2;
4393 HRESULT hr;
4394
4395 /* Only one exposes an IA2 interface, no match. */
4396 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
4398 set_accessible_props(&Accessible2, ROLE_SYSTEM_TEXT, 0, 0, L"acc_name", 0, 0, 0, 0);
4400
4401 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4402 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4403 if (Accessible.ref != 3)
4404 {
4405 IRawElementProviderSimple_Release(elprov);
4406 win_skip("UiaProviderFromIAccessible has no IAccessible2 support, skipping tests.\n");
4407 return;
4408 }
4409
4410 acc_client = &Accessible2.IAccessible_iface;
4411 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4412 /* The four below are only called on Win10v1909. */
4413 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4414 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4415 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4416 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4417 elprov2 = (void *)0xdeadbeef;
4418 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4419 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4420 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4421 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4422 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4423
4424 /*
4425 * Win10v1909 has IAccessible2 support, but it's not used for checking if
4426 * two IAccessible interfaces match. Skip the comparison tests for this
4427 * Windows version.
4428 */
4429 if (Accessible.called_get_accRole)
4430 {
4431 IRawElementProviderSimple_Release(elprov);
4432 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4433 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4434 CHECK_ACC_METHOD_CALLED(&Accessible2, QI_IAccIdentity);
4435 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accParent);
4436 win_skip("Win10v1909 doesn't support IAccessible2 interface comparison, skipping tests.\n");
4437 return;
4438 }
4439 Accessible.called_get_accRole = Accessible.expect_get_accRole = 0;
4440 Accessible2.called_get_accRole = Accessible2.expect_get_accRole = 0;
4441 Accessible2.called_QI_IAccIdentity = Accessible2.expect_QI_IAccIdentity = 0;
4442 Accessible2.called_get_accParent = Accessible2.expect_get_accParent = 0;
4443
4444 Accessible.role = Accessible2.role = 0;
4445 elprov2 = (void *)0xdeadbeef;
4446 acc_client = NULL;
4447 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4448 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4449 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4450
4451 IRawElementProviderSimple_Release(elprov);
4452 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4453
4454 /*
4455 * If &Accessible returns a failure code on get_uniqueID, &Accessible2's
4456 * uniqueID is not checked.
4457 */
4460 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4461 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4462 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4463
4464 acc_client = &Accessible2.IAccessible_iface;
4465 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4466 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4467 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4468 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4469 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4470 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4471 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
4472 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
4473 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
4474 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4475 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4476 elprov2 = (void *)0xdeadbeef;
4477 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4478 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4479 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4480 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4481 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4482 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4483 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4484 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4485 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4486 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4487 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
4488 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
4489 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
4492 IRawElementProviderSimple_Release(elprov2);
4493
4494 elprov2 = (void *)0xdeadbeef;
4495 acc_client = NULL;
4496 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4497 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4498 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4499 IRawElementProviderSimple_Release(elprov2);
4500
4501 IRawElementProviderSimple_Release(elprov);
4502 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4503
4504 /* Unique ID matches. */
4507 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4509 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4510
4511 acc_client = &Accessible2.IAccessible_iface;
4512 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4513 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
4514 SET_ACC_METHOD_EXPECT(&Accessible2, get_uniqueID);
4515 elprov2 = (void *)0xdeadbeef;
4516 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4517 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4518 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4519 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4520 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4521 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
4522 CHECK_ACC_METHOD_CALLED(&Accessible2, get_uniqueID);
4523 IRawElementProviderSimple_Release(elprov2);
4524
4525 elprov2 = (void *)0xdeadbeef;
4526 acc_client = NULL;
4527 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4528 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4529 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4530 IRawElementProviderSimple_Release(elprov2);
4531
4532 IRawElementProviderSimple_Release(elprov);
4533 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4534
4535 /* Unique ID mismatch. */
4538 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4539 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4540 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4541
4542 acc_client = &Accessible2.IAccessible_iface;
4543 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4544 SET_ACC_METHOD_EXPECT(&Accessible, get_uniqueID);
4545 SET_ACC_METHOD_EXPECT(&Accessible2, get_uniqueID);
4546 elprov2 = (void *)0xdeadbeef;
4547 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4548 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4549 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4550 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
4551 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4552 CHECK_ACC_METHOD_CALLED(&Accessible, get_uniqueID);
4553 CHECK_ACC_METHOD_CALLED(&Accessible2, get_uniqueID);
4554
4555 elprov2 = (void *)0xdeadbeef;
4556 acc_client = NULL;
4557 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4558 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4559 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
4560
4561 IRawElementProviderSimple_Release(elprov);
4562 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4563
4564 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
4566 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
4568}
4569
4570#define check_fragment_acc( fragment, acc, cid) \
4571 check_fragment_acc_( (fragment), (acc), (cid), __LINE__)
4572static void check_fragment_acc_(IRawElementProviderFragment *elfrag, IAccessible *acc,
4573 INT cid, int line)
4574{
4575 ILegacyIAccessibleProvider *accprov;
4576 IAccessible *accessible;
4577 INT child_id;
4578 HRESULT hr;
4579
4580 hr = IRawElementProviderFragment_QueryInterface(elfrag, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
4581 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
4582 ok_(__FILE__, line) (!!accprov, "accprov == NULL\n");
4583
4584 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &accessible);
4585 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
4586 ok_(__FILE__, line) (accessible == acc, "accessible != acc\n");
4587 IAccessible_Release(accessible);
4588
4589 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
4590 ok_(__FILE__, line) (hr == S_OK, "Unexpected hr %#lx.\n", hr);
4591 ok_(__FILE__, line) (child_id == cid, "child_id != cid\n");
4592
4593 ILegacyIAccessibleProvider_Release(accprov);
4594}
4595
4597{
4598 IRawElementProviderFragment *elfrag, *elfrag2, *elfrag3;
4599 IRawElementProviderSimple *elprov, *elprov2;
4600 HRESULT hr;
4601
4602 /*
4603 * Full IAccessible parent, with 4 children:
4604 * childid 1 is a simple element, with STATE_SYSTEM_INVISIBLE.
4605 * childid 2 is Accessible_child.
4606 * childid 3 is a simple element with STATE_SYSTEM_NORMAL.
4607 * childid 4 is Accessible_child2.
4608 */
4609 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
4610 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4611 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4612
4613 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4614 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4615 ok(!!elfrag, "elfrag == NULL\n");
4616
4617 /*
4618 * First time doing NavigateDirection_Parent will result in the same root
4619 * accessible check as get_HostRawElementProvider. If this IAccessible is
4620 * the root for its associated HWND, NavigateDirection_Parent and
4621 * NavigateDirection_Next/PreviousSibling will do nothing, as UI Automation
4622 * provides non-client area providers for the root IAccessible's parent
4623 * and siblings.
4624 */
4625 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
4626 L"acc_name", 0, 0, 50, 50);
4627 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 4,
4628 L"acc_name", 0, 0, 50, 50);
4629 acc_client = &Accessible2.IAccessible_iface;
4630 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4631 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
4632 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4633 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4634 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
4635 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
4636 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4637 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
4638 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
4639 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
4640 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
4641 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4642 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4643 elfrag2 = (void *)0xdeadbeef;
4644 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4645 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4647 ok(!elfrag2, "elfrag2 != NULL\n");
4648 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4649 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
4650 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4651 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4652 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
4653 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
4654 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4655 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
4656 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
4657 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
4658 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
4661 acc_client = NULL;
4662
4663 /* No check against root IAccessible, since it was done previously. */
4664 elprov2 = (void *)0xdeadbeef;
4665 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
4666 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4667 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
4668 IRawElementProviderSimple_Release(elprov2);
4669
4670 /* Do nothing. */
4671 elfrag2 = (void *)0xdeadbeef;
4672 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4673 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4674 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4675 ok(!elfrag2, "elfrag2 != NULL\n");
4676
4677 elfrag2 = (void *)0xdeadbeef;
4678 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4679 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4680 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4681 ok(!elfrag2, "elfrag2 != NULL\n");
4682
4683 elfrag2 = (void *)0xdeadbeef;
4684 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
4685 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4686 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4687 ok(!elfrag2, "elfrag2 != NULL\n");
4688
4689 /*
4690 * Retrieve childid 2 (Accessible_child) as first child. childid 1 is skipped due to
4691 * having a state of STATE_SYSTEM_INVISIBLE.
4692 */
4695 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 3);
4696 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 2);
4697 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4700 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4701 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4702 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4703 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4704 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4705 ok(!!elfrag2, "elfrag2 == NULL\n");
4706 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 3);
4707 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 2);
4711
4712 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
4713 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4714 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4715 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4716 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_NextSibling, &elfrag3);
4717 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
4718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4719 ok(!!elfrag3, "elfrag2 == NULL\n");
4720 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4721 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4722 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4724
4725 IRawElementProviderFragment_Release(elfrag3);
4726 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4727 IRawElementProviderFragment_Release(elfrag2);
4728 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4729 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4730
4731 /* Retrieve childid 3 as first child now that Accessible_child is invisible. */
4733 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 4);
4734 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 3);
4735 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accState, 2);
4737 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4738 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4740 ok(!!elfrag2, "elfrag2 == NULL\n");
4741 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 4);
4742 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 3);
4743 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accState, 2);
4746 IRawElementProviderFragment_Release(elfrag2);
4747 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4748
4749 /* Retrieve childid 4 (Accessible_child2) as last child. */
4751 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 2);
4752 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4756 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4757 ok(Accessible_child2.ref == 2, "Unexpected refcnt %ld\n", Accessible_child2.ref);
4758 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4760 ok(!!elfrag2, "elfrag2 == NULL\n");
4761 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 2);
4762 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4766
4767 check_fragment_acc(elfrag2, &Accessible_child2.IAccessible_iface, CHILDID_SELF);
4768 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4769 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4770 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4771 hr = IRawElementProviderFragment_Navigate(elfrag2, NavigateDirection_PreviousSibling, &elfrag3);
4772 ok(Accessible.ref == 5, "Unexpected refcnt %ld\n", Accessible.ref);
4773 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4774 ok(!!elfrag3, "elfrag2 == NULL\n");
4775 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4776 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4777 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4779
4780 IRawElementProviderFragment_Release(elfrag3);
4781 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4782 IRawElementProviderFragment_Release(elfrag2);
4783 ok(Accessible_child2.ref == 1, "Unexpected refcnt %ld\n", Accessible_child2.ref);
4784 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4785
4786 /* Retrieve childid 3 as last child, now that Accessible_child2 is STATE_SYSTEM_INVISIBLE. */
4788 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 3);
4789 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 2);
4790 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4792 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4793 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4794 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4795 ok(!!elfrag2, "elfrag2 == NULL\n");
4796 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 3);
4797 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 2);
4798 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4801 IRawElementProviderFragment_Release(elfrag2);
4802 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4803
4804 IRawElementProviderFragment_Release(elfrag);
4805 IRawElementProviderSimple_Release(elprov);
4806 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4807
4808 /*
4809 * Full IAccessible child tests.
4810 */
4812 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4813 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, 0, UIA_PFIA_DEFAULT, &elprov);
4814 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4817 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
4818
4819 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4821 ok(!!elfrag, "elfrag == NULL\n");
4822
4823 /*
4824 * After determining this isn't the root IAccessible, get_accParent will
4825 * be used to get the parent.
4826 */
4827 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4828 set_accessible_props(&Accessible_child, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
4829 acc_client = &Accessible2.IAccessible_iface;
4830 SET_EXPECT(winproc_GETOBJECT_CLIENT);
4832 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4833 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
4834 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
4835 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
4836 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4837 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4838 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4839 ok(!!elfrag2, "elfrag2 == NULL\n");
4842 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
4845 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
4847 IRawElementProviderFragment_Release(elfrag2);
4848 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4849 acc_client = NULL;
4850
4851 /* Second call only does get_accParent, no root check. */
4852 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4853 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4854 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4855 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4856 ok(!!elfrag2, "elfrag2 == NULL\n");
4859 IRawElementProviderFragment_Release(elfrag2);
4860 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4861
4862 /* ChildCount of 0, do nothing for First/Last child.*/
4863 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4864 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4865 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4866 ok(!elfrag2, "elfrag2 != NULL\n");
4867 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4868
4869 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4870 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4872 ok(!elfrag2, "elfrag2 != NULL\n");
4873 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4874
4875 /*
4876 * In the case of sibling navigation on an IAccessible that wasn't
4877 * received through previous navigation from a parent (i.e, from
4878 * NavigateDirection_First/LastChild), we have to figure out which
4879 * IAccessible child we represent by comparing against all children of our
4880 * IAccessible parent. If we find more than one IAccessible that matches,
4881 * or none at all that do, navigation will fail.
4882 */
4884 L"acc_child", 0, 0, 50, 50);
4886 L"acc_child", 0, 0, 50, 50);
4887 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 5);
4888 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 4);
4889 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4892 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accChildCount);
4897 SET_ACC_METHOD_EXPECT(&Accessible_child2, get_accChildCount);
4900 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4901 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4902 ok(!elfrag2, "elfrag2 != NULL\n");
4903 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 5);
4904 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 4);
4908 CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accChildCount);
4913 CHECK_ACC_METHOD_CALLED(&Accessible_child2, get_accChildCount);
4916
4917 /* Now they have a role mismatch, we can determine our position. */
4919 L"acc_child", 0, 0, 50, 50);
4920 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChildCount, 6);
4921 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accChild, 5);
4922 /* Check ChildID 1 for STATE_SYSTEM_INVISIBLE. */
4923 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4924 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
4927 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_PreviousSibling, &elfrag2);
4928 /*
4929 * Even though we didn't get a new fragment, now that we know our
4930 * position, a reference is added to the parent IAccessible.
4931 */
4932 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4933 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4934 ok(!elfrag2, "elfrag2 != NULL\n");
4935 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChildCount, 6);
4936 CHECK_ACC_METHOD_CALLED_MULTI(&Accessible, get_accChild, 5);
4937 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4941
4942 /* Now that we know our position, no extra nav work. */
4943 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
4944 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
4945 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
4946 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
4947 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
4948 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4949 ok(!!elfrag2, "elfrag2 == NULL\n");
4950 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
4951 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
4952 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
4953 if (elfrag2)
4954 {
4956 IRawElementProviderFragment_Release(elfrag2);
4957 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4958 }
4959
4960 IRawElementProviderFragment_Release(elfrag);
4961 IRawElementProviderSimple_Release(elprov);
4962 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
4963 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
4964
4965 /*
4966 * Simple element child tests.
4967 */
4968 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
4969 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4970 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4971
4972 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
4973 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4974 ok(!!elfrag, "elfrag == NULL\n");
4975
4976 /*
4977 * Simple child elements don't check the root IAccessible, because they
4978 * can't be the root IAccessible.
4979 */
4980 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2);
4981 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
4982 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4983 ok(!!elfrag2, "elfrag2 == NULL\n");
4985 IRawElementProviderFragment_Release(elfrag2);
4986 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4987
4988 /*
4989 * Test NavigateDirection_First/LastChild on simple child element. Does
4990 * nothing, as simple children cannot have children.
4991 */
4992 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_FirstChild, &elfrag2);
4993 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4994 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
4995 ok(!elfrag2, "elfrag2 != NULL\n");
4996
4997 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_LastChild, &elfrag2);
4998 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
4999 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5000 ok(!elfrag2, "elfrag2 != NULL\n");
5001
5002 /*
5003 * NavigateDirection_Next/PreviousSibling behaves normally, no IAccessible
5004 * comparisons.
5005 */
5006 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5007 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
5010 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
5011 hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_NextSibling, &elfrag2);
5012 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
5013 ok(Accessible.ref == 4, "Unexpected refcnt %ld\n", Accessible.ref);
5014 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5015 ok(!!elfrag2, "elfrag2 == NULL\n");
5016 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5017 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
5021 check_fragment_acc(elfrag2, &Accessible_child.IAccessible_iface, CHILDID_SELF);
5022
5023 IRawElementProviderFragment_Release(elfrag2);
5024 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
5025 ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref);
5026 IRawElementProviderFragment_Release(elfrag);
5027 IRawElementProviderSimple_Release(elprov);
5028 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5029
5030 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
5031 set_accessible_props(&Accessible2, 0, 0, 0, NULL, 0, 0, 0, 0);
5032 set_accessible_props(&Accessible_child, 0, 0, 0, NULL, 0, 0, 0, 0);
5033 set_accessible_props(&Accessible_child2, 0, 0, 0, NULL, 0, 0, 0, 0);
5034}
5035
5037{
5038 IRawElementProviderSimple *elprov;
5039 RECT rect[2] = { 0 };
5040 HRESULT hr;
5041 VARIANT v;
5042 int i, x;
5043
5044 /* MSAA role to UIA control type test. */
5045 VariantInit(&v);
5046 for (i = 0; i < ARRAY_SIZE(msaa_role_uia_types); i++)
5047 {
5048 const struct msaa_role_uia_type *role = &msaa_role_uia_types[i];
5049 ILegacyIAccessibleProvider *accprov;
5050 DWORD role_val;
5051 IUnknown *unk;
5052
5053 /*
5054 * Roles get cached once a valid one is mapped, so create a new
5055 * element for each role.
5056 */
5057 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5058 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5059 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5060
5061 Accessible.role = role->acc_role;
5062 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5063 VariantClear(&v);
5064 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5065 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5066 if (role->uia_control_type)
5067 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
5068 else
5069 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
5070 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5071
5072 if (!role->uia_control_type)
5073 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5074 VariantClear(&v);
5075 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5077 if (role->uia_control_type)
5078 ok(check_variant_i4(&v, role->uia_control_type), "MSAA role %d: V_I4(&v) = %ld\n", role->acc_role, V_I4(&v));
5079 else
5080 ok(V_VT(&v) == VT_EMPTY, "MSAA role %d: V_VT(&v) = %d\n", role->acc_role, V_VT(&v));
5081 if (!role->uia_control_type)
5082 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5083
5084 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
5085 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5086 ok(!!unk, "unk == NULL\n");
5087
5088 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
5089 IUnknown_Release(unk);
5090 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5091 ok(!!accprov, "accprov == NULL\n");
5092
5093 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5094 hr = ILegacyIAccessibleProvider_get_Role(accprov, &role_val);
5095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5096 ok(role_val == Accessible.role, "role_val != Accessible.role\n");
5097 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5098
5099 ILegacyIAccessibleProvider_Release(accprov);
5100 IRawElementProviderSimple_Release(elprov);
5101 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5102 }
5103
5104 /* ROLE_SYSTEM_CLOCK has no mapping in Windows < 10 1809. */
5105 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5106 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5107 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5108
5109 Accessible.role = ROLE_SYSTEM_CLOCK;
5110 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5111 VariantClear(&v);
5112 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5113 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5114 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
5115 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
5116 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5117
5118 if (V_VT(&v) == VT_EMPTY)
5119 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5120 VariantClear(&v);
5121 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ControlTypePropertyId, &v);
5122 ok(check_variant_i4(&v, UIA_ButtonControlTypeId) || broken(V_VT(&v) == VT_EMPTY), /* Windows < 10 1809 */
5123 "MSAA role %d: V_I4(&v) = %ld\n", Accessible.role, V_I4(&v));
5124 if (V_VT(&v) == VT_EMPTY)
5125 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5126
5127 Accessible.role = 0;
5128 IRawElementProviderSimple_Release(elprov);
5129 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5130
5131 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5132 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5133 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5134
5135 /* UIA PropertyId's that correspond directly to individual MSAA state flags. */
5136 for (i = 0; i < ARRAY_SIZE(msaa_state_uia_props); i++)
5137 {
5139
5140 for (x = 0; x < 2; x++)
5141 {
5142 Accessible.state = x ? state->acc_state : ~state->acc_state;
5143 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5144 hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v);
5145 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5146 ok(check_variant_bool(&v, x), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
5147 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5148 }
5149
5150 /* Failure HRESULTs are passed through. */
5151 Accessible.state = 0;
5152 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5153 hr = IRawElementProviderSimple_GetPropertyValue(elprov, state->prop_id, &v);
5154 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
5155 ok(V_VT(&v) == VT_EMPTY, "Unexpected V_VT %d\n", V_VT(&v));
5156 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5157 }
5158 Accessible.state = 0;
5159
5160 /*
5161 * UIA_IsOffscreenPropertyId relies upon either STATE_SYSTEM_OFFSCREEN
5162 * being set, or accLocation returning a location that is within the
5163 * client area bounding box of the HWND it is contained within.
5164 */
5165 set_accessible_props(&Accessible, 0, STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0);
5166 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5167 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5169 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5170 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5171 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5172
5173 /* accLocation fails, will return FALSE. */
5174 set_accessible_props(&Accessible, 0, ~STATE_SYSTEM_OFFSCREEN, 0, L"Accessible", 0, 0, 0, 0);
5175 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5176 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5177 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5178 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5179 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5180 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5181 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5182 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5183
5184 /* Window is visible, Accessible is within its bounds. */
5186 ok(GetClientRect(Accessible.ow_hwnd, &rect[0]), "GetClientRect returned FALSE\n");
5188
5190 (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top));
5191 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5192 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5193 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5195 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
5196 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5197 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5198 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5199
5200 /*
5201 * Window is invisible, Accessible is within its bounds. Window visibility
5202 * doesn't effect whether or not an IAccessible is considered offscreen.
5203 */
5206 (rect[0].right - rect[0].left), (rect[0].bottom - rect[0].top));
5207 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5208 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5209 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5210 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5211 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
5212 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5213 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5214 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5215
5216 /* Accessible now outside of its window's bounds. */
5218 10, 10);
5219 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5220 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5221 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5222 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5223 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5224 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5225 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5226 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5227
5228 /* Accessible within window bounds, but not client area bounds. */
5229 ok(GetWindowRect(Accessible.ow_hwnd, &rect[1]), "GetWindowRect returned FALSE\n");
5231 (rect[0].left - rect[1].left) - 1, (rect[0].top - rect[1].top) - 1);
5232
5233 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5234 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5235 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_IsOffscreenPropertyId, &v);
5236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5237 ok(V_VT(&v) == VT_BOOL, "V_VT(&v) = %d\n", V_VT(&v));
5238 ok(check_variant_bool(&v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(&v));
5239 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5240 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5241
5242 IRawElementProviderSimple_Release(elprov);
5243 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5244
5245 /* UIA_NamePropertyId tests. */
5246 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible", 0, 0, 0, 0);
5247 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5248 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5249 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5250
5251 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5252 VariantInit(&v);
5253 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
5254 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5255 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
5256 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
5257 VariantClear(&v);
5258 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5259
5260 /* Name is not cached. */
5261 set_accessible_props(&Accessible, 0, 0, 0, L"Accessible2", 0, 0, 0, 0);
5262 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5263 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_NamePropertyId, &v);
5264 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5265 ok(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
5266 ok(!lstrcmpW(V_BSTR(&v), Accessible.name), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
5267 VariantClear(&v);
5268 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5269
5270 IRawElementProviderSimple_Release(elprov);
5271 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5272}
5273
5275{
5276 ILegacyIAccessibleProvider *accprov;
5277 IRawElementProviderSimple *elprov, *elprov2;
5278 IRawElementProviderFragment *elfrag;
5279 enum ProviderOptions prov_opt;
5280 struct UiaRect rect;
5281 IAccessible *acc;
5282 IUnknown *unk;
5283 WNDCLASSA cls;
5284 HRESULT hr;
5285 HWND hwnd;
5286 VARIANT v;
5287 INT cid;
5288
5290 cls.style = 0;
5292 cls.cbClsExtra = 0;
5293 cls.cbWndExtra = 0;
5295 cls.hIcon = 0;
5296 cls.hCursor = NULL;
5297 cls.hbrBackground = NULL;
5298 cls.lpszMenuName = NULL;
5299 cls.lpszClassName = "UiaProviderFromIAccessible class";
5300
5301 RegisterClassA(&cls);
5302
5303 hwnd = CreateWindowA("UiaProviderFromIAccessible class", "Test window", WS_OVERLAPPEDWINDOW,
5304 0, 0, 100, 100, NULL, NULL, NULL, NULL);
5305
5306 hr = pUiaProviderFromIAccessible(NULL, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5307 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5308
5309 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, NULL);
5310 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
5311
5312 /*
5313 * UiaProviderFromIAccessible will not wrap an MSAA proxy, this is
5314 * detected by checking for the 'IIS_IsOleaccProxy' service from the
5315 * IServiceProvider interface.
5316 */
5317 hr = CreateStdAccessibleObject(hwnd, OBJID_CLIENT, &IID_IAccessible, (void**)&acc);
5318 ok(hr == S_OK, "got %#lx\n", hr);
5319 ok(!!acc, "acc == NULL\n");
5320
5321 hr = pUiaProviderFromIAccessible(acc, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5322 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
5323 IAccessible_Release(acc);
5324
5325 /* Don't return an HWND from accNavigate or OleWindow. */
5326 SET_ACC_METHOD_EXPECT(&Accessible, accNavigate);
5327 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent);
5330 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5331 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
5332 CHECK_ACC_METHOD_CALLED(&Accessible, accNavigate);
5333 CHECK_ACC_METHOD_CALLED(&Accessible, get_accParent);
5334
5335 /* Return an HWND from accNavigate, not OleWindow. */
5336 SET_ACC_METHOD_EXPECT(&Accessible, accNavigate);
5337 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5341 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5342 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5343 CHECK_ACC_METHOD_CALLED(&Accessible, accNavigate);
5344 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5345 IRawElementProviderSimple_Release(elprov);
5346 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5347 acc_client = NULL;
5348
5349 /* Skip tests on Win10v1507. */
5350 if (called_winproc_GETOBJECT_CLIENT)
5351 {
5352 win_skip("UiaProviderFromIAccessible behaves inconsistently on Win10 1507, skipping tests.\n");
5353 return;
5354 }
5355 expect_winproc_GETOBJECT_CLIENT = FALSE;
5356
5357 /* Return an HWND from parent IAccessible's IOleWindow interface. */
5359 SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
5362 hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5363 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5366 ok(Accessible_child.ref == 2, "Unexpected refcnt %ld\n", Accessible_child.ref);
5367 IRawElementProviderSimple_Release(elprov);
5368 ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
5369
5370 /* Return an HWND from OleWindow, not accNavigate. */
5373 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5375 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5376
5377 hr = IRawElementProviderSimple_get_ProviderOptions(elprov, &prov_opt);
5378 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5380 broken(prov_opt == ProviderOptions_ClientSideProvider), /* Windows < 10 1507 */
5381 "Unexpected provider options %#x\n", prov_opt);
5382
5383 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
5384
5385 hr = IRawElementProviderSimple_GetPropertyValue(elprov, UIA_ProviderDescriptionPropertyId, &v);
5386 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5387 ok(V_VT(&v) == VT_BSTR, "V_VT(&v) = %d\n", V_VT(&v));
5388 VariantClear(&v);
5389
5390 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
5391 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5392 ok(!!unk, "unk == NULL\n");
5393 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
5394
5395 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
5396 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5397 ok(!!accprov, "accprov == NULL\n");
5398
5399 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
5400 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5401 ok(cid == CHILDID_SELF, "cid != CHILDID_SELF\n");
5402
5403 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
5404 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5405 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
5406 IAccessible_Release(acc);
5407 IUnknown_Release(unk);
5408 ILegacyIAccessibleProvider_Release(accprov);
5409
5410 IRawElementProviderSimple_Release(elprov);
5411 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5412
5413 /* ChildID other than CHILDID_SELF. */
5414 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
5415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5416 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5417
5418 /* Even simple children implement IRawElementProviderFragmentRoot. */
5419 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
5420
5421 /*
5422 * Simple child element (IAccessible without CHILDID_SELF) cannot be root
5423 * IAccessible. No checks against the root HWND IAccessible will be done.
5424 */
5425 elprov2 = (void *)0xdeadbeef;
5426 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5427 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5428 ok(!elprov2, "elprov != NULL\n");
5429
5430 hr = IRawElementProviderSimple_GetPatternProvider(elprov, UIA_LegacyIAccessiblePatternId, &unk);
5431 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5432 ok(!!unk, "unk == NULL\n");
5433 ok(iface_cmp((IUnknown *)elprov, unk), "unk != elprov\n");
5434
5435 hr = IUnknown_QueryInterface(unk, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
5436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5437 ok(!!accprov, "accprov == NULL\n");
5438
5439 hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &cid);
5440 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5441 ok(cid == 1, "cid != CHILDID_SELF\n");
5442
5443 hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc);
5444 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5445 ok(acc == &Accessible.IAccessible_iface, "acc != &Accessible.IAccessible_iface\n");
5446 IAccessible_Release(acc);
5447 IUnknown_Release(unk);
5448 ILegacyIAccessibleProvider_Release(accprov);
5449
5450 IRawElementProviderSimple_Release(elprov);
5451 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5452
5453 /*
5454 * &Accessible.IAccessible_iface will be compared against the default
5455 * client accessible object. Since we have all properties set to 0,
5456 * we return failure HRESULTs and all properties will get queried but not
5457 * compared.
5458 */
5459 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5460 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5461 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5462
5463 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5464 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5465 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5466 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5467 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5468 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5469 elprov2 = (void *)0xdeadbeef;
5470 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5471 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5472 ok(!elprov2, "elprov != NULL\n");
5473 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5474 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5475 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5476 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5477 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5478 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5479
5480 /*
5481 * Interface that isn't the HWND root, still implements
5482 * IRawElementProviderFragmentRoot.
5483 */
5484 test_implements_interface(elprov, &IID_IRawElementProviderFragmentRoot, TRUE);
5485
5486 /* Second call won't send WM_GETOBJECT. */
5487 elprov2 = (void *)0xdeadbeef;
5488 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5490 ok(!elprov2, "elprov != NULL\n");
5491
5492 IRawElementProviderSimple_Release(elprov);
5493 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5494
5495 /*
5496 * Return &Accessible.IAccessible_iface in response to OBJID_CLIENT,
5497 * interface pointers will be compared, no method calls to check property
5498 * values.
5499 */
5500 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5502 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5503
5504 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5505 elprov2 = (void *)0xdeadbeef;
5507 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5509 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5510 IRawElementProviderSimple_Release(elprov2);
5511 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5512
5513 /* Second call, no checks. */
5514 elprov2 = (void *)0xdeadbeef;
5515 acc_client = NULL;
5516 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5517 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5518 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5519 IRawElementProviderSimple_Release(elprov2);
5520
5521 IRawElementProviderSimple_Release(elprov);
5522 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5523
5524 /*
5525 * Return &Accessible2.IAccessible_iface in response to OBJID_CLIENT,
5526 * interface pointers won't match, so properties will be compared.
5527 */
5528 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5529 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5530 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5531
5532 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
5533 L"acc_name", 0, 0, 50, 50);
5534 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
5535 L"acc_name", 0, 0, 50, 50);
5536
5537 acc_client = &Accessible2.IAccessible_iface;
5538 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5539 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5540 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5541 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5542 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5543 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5544 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5545 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5546 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5547 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
5548 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
5549 /*
5550 * The IAccessible returned by WM_GETOBJECT will be checked for an
5551 * IAccIdentity interface to see if Dynamic Annotation properties should
5552 * be queried. If not present on the current IAccessible, it will check
5553 * the parent IAccessible for one.
5554 */
5555 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5556 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5557 elprov2 = (void *)0xdeadbeef;
5558 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5559 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5560 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5561 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5562 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5563 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5564 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5565 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5566 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5567 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5568 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5569 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5570 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5571 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
5572 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
5575 IRawElementProviderSimple_Release(elprov2);
5576
5577 elprov2 = (void *)0xdeadbeef;
5578 acc_client = NULL;
5579 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5580 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5581 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5582 IRawElementProviderSimple_Release(elprov2);
5583
5584 IRawElementProviderSimple_Release(elprov);
5585 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5586
5587 /*
5588 * If a failure HRESULT is returned from the IRawElementProviderSimple
5589 * IAccessible, the corresponding AOFW IAccessible method isn't called.
5590 * An exception is get_accChildCount, which is always called, but only
5591 * checked if the HRESULT return value is not a failure. If Role/State/Name
5592 * are not queried, no IAccIdentity check is done.
5593 */
5594 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5596 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5597
5598 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
5599 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1,
5600 L"acc_name", 0, 0, 50, 50);
5601
5602 acc_client = &Accessible2.IAccessible_iface;
5603 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5604 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5605 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5606 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5607 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5608 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5609 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5610 elprov2 = (void *)0xdeadbeef;
5611 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5612 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5613 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5614 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5615 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5616 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5617 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5618 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5619 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5620 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5621
5622 acc_client = NULL;
5623 elprov2 = (void *)0xdeadbeef;
5624 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5626 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5627
5628 IRawElementProviderSimple_Release(elprov);
5629 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5630
5631 /*
5632 * Properties are checked in a sequence of accRole, accState,
5633 * accChildCount, accLocation, and finally accName. If a mismatch is found
5634 * early in the sequence, the rest aren't checked.
5635 */
5636 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5638 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5639
5640 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
5641 set_accessible_props(&Accessible2, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSABLE, 0, NULL, 0, 0, 0, 0);
5642
5643 acc_client = &Accessible2.IAccessible_iface;
5644 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5645 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5646 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5647 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5648 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5649 elprov2 = (void *)0xdeadbeef;
5650 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5651 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5652 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5653 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5654 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5655 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5658
5659 elprov2 = (void *)0xdeadbeef;
5660 acc_client = NULL;
5661 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5662 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5663 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5664
5665 IRawElementProviderSimple_Release(elprov);
5666 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5667
5668 /* 4/5 properties match, considered a match. */
5669 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5671 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5672
5673 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
5674 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 50, 50);
5675
5676 acc_client = &Accessible2.IAccessible_iface;
5677 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5678 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5679 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5680 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5681 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5682 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5683 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5684 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5685 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5686 SET_ACC_METHOD_EXPECT(&Accessible2, accLocation);
5687 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5688 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5689 elprov2 = (void *)0xdeadbeef;
5690 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5691 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5692 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5693 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5694 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5695 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5696 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5697 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5698 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5699 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5700 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5701 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5702 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5703 CHECK_ACC_METHOD_CALLED(&Accessible2, accLocation);
5706 IRawElementProviderSimple_Release(elprov2);
5707
5708 elprov2 = (void *)0xdeadbeef;
5709 acc_client = NULL;
5710 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5711 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5712 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5713 IRawElementProviderSimple_Release(elprov2);
5714
5715 IRawElementProviderSimple_Release(elprov);
5716 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5717
5718 /* 3/5 properties match, not considered a match. */
5719 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5720 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5721 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5722
5723 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
5724 set_accessible_props(&Accessible2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 1, NULL, 0, 0, 0, 0);
5725
5726 acc_client = &Accessible2.IAccessible_iface;
5727 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5728 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5729 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5730 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5731 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5732 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5733 SET_ACC_METHOD_EXPECT(&Accessible2, get_accRole);
5734 SET_ACC_METHOD_EXPECT(&Accessible2, get_accState);
5735 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5736 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5737 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5738 elprov2 = (void *)0xdeadbeef;
5739 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5740 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5741 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5742 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5743 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5744 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5745 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5746 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5747 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5748 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accRole);
5749 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accState);
5750 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5753
5754 elprov2 = (void *)0xdeadbeef;
5755 acc_client = NULL;
5756 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5757 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5758 ok(!elprov2, "elprov != NULL, elprov %p\n", elprov2);
5759
5760 IRawElementProviderSimple_Release(elprov);
5761 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5762
5763 /* Only name matches, considered a match. */
5764 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5765 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5766 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5767
5768 set_accessible_props(&Accessible, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
5769 set_accessible_props(&Accessible2, 0, 0, 0, L"acc_name", 0, 0, 0, 0);
5770
5771 acc_client = &Accessible2.IAccessible_iface;
5772 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5773 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5774 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5775 SET_ACC_METHOD_EXPECT(&Accessible, get_accChildCount);
5776 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5777 SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
5778 SET_ACC_METHOD_EXPECT(&Accessible2, get_accChildCount);
5779 SET_ACC_METHOD_EXPECT(&Accessible2, get_accName);
5780 SET_ACC_METHOD_EXPECT(&Accessible2, QI_IAccIdentity);
5781 SET_ACC_METHOD_EXPECT(&Accessible2, get_accParent);
5782 elprov2 = (void *)0xdeadbeef;
5783 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5785 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5786 ok(Accessible2.ref == 1, "Unexpected refcnt %ld\n", Accessible2.ref);
5787 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5788 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5789 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5790 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChildCount);
5791 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5792 CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
5793 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accChildCount);
5794 CHECK_ACC_METHOD_CALLED(&Accessible2, get_accName);
5797 IRawElementProviderSimple_Release(elprov2);
5798
5799 elprov2 = (void *)0xdeadbeef;
5800 acc_client = NULL;
5801 hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
5802 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5803 ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2);
5804 IRawElementProviderSimple_Release(elprov2);
5805
5806 IRawElementProviderSimple_Release(elprov);
5807 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5808
5809 /*
5810 * Test IRawElementProviderFragment_get_BoundingRectangle.
5811 */
5812 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, L"acc_name", 25, 25, 50, 50);
5813 /* Test the case where Accessible is not the root for its HWND. */
5814 acc_client = NULL;
5815 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5816 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5817 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5818
5819 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
5820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5821 ok(!!elfrag, "elfrag == NULL\n");
5822
5823 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5824 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
5825 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5826 SET_ACC_METHOD_EXPECT(&Accessible, accLocation);
5827 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5828 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5829 ok(rect.left == (double)Accessible.left, "Unexpected left value %f\n", rect.left);
5830 ok(rect.top == (double)Accessible.top, "Unexpected top value %f\n", rect.top);
5831 ok(rect.width == (double)Accessible.width, "Unexpected width value %f\n", rect.width);
5832 ok(rect.height == (double)Accessible.height, "Unexpected height value %f\n", rect.height);
5833 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5834 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
5835 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5836 CHECK_ACC_METHOD_CALLED(&Accessible, accLocation);
5837
5838 /* If Accessible has STATE_SYSTEM_OFFSCREEN, it will return an empty rect. */
5839 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_OFFSCREEN, 0, L"acc_name", 0, 0, 50, 50);
5840 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
5841 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5842 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5843 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5844 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5845 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5846 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5847 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
5848
5849 IRawElementProviderFragment_Release(elfrag);
5850 IRawElementProviderSimple_Release(elprov);
5851 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5852
5853 /* Test case where accessible is the root accessible. */
5854 set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
5856 hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
5857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5858 ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
5859
5860 hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
5861 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5862 ok(!!elfrag, "elfrag == NULL\n");
5863
5864 SET_EXPECT(winproc_GETOBJECT_CLIENT);
5865 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5866 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5867 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5868 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5869 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5870 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5871 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
5872
5873 /* Second call does nothing. */
5874 hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect);
5875 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
5876 ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left);
5877 ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top);
5878 ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width);
5879 ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height);
5880
5881 IRawElementProviderFragment_Release(elfrag);
5882 IRawElementProviderSimple_Release(elprov);
5883 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
5884 acc_client = NULL;
5885
5891
5894 UnregisterClassA("pUiaProviderFromIAccessible class", NULL);
5897}
5898
5900 const GUID *guid;
5901 int id;
5902};
5903
5905 { &RuntimeId_Property_GUID, UIA_RuntimeIdPropertyId },
5906 { &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId },
5907 { &ProcessId_Property_GUID, UIA_ProcessIdPropertyId },
5908 { &ControlType_Property_GUID, UIA_ControlTypePropertyId },
5909 { &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId },
5910 { &Name_Property_GUID, UIA_NamePropertyId },
5911 { &AcceleratorKey_Property_GUID, UIA_AcceleratorKeyPropertyId },
5912 { &AccessKey_Property_GUID, UIA_AccessKeyPropertyId },
5913 { &HasKeyboardFocus_Property_GUID, UIA_HasKeyboardFocusPropertyId },
5914 { &IsKeyboardFocusable_Property_GUID, UIA_IsKeyboardFocusablePropertyId },
5915 { &IsEnabled_Property_GUID, UIA_IsEnabledPropertyId },
5916 { &AutomationId_Property_GUID, UIA_AutomationIdPropertyId },
5917 { &ClassName_Property_GUID, UIA_ClassNamePropertyId },
5918 { &HelpText_Property_GUID, UIA_HelpTextPropertyId },
5919 { &ClickablePoint_Property_GUID, UIA_ClickablePointPropertyId },
5920 { &Culture_Property_GUID, UIA_CulturePropertyId },
5921 { &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId },
5922 { &IsContentElement_Property_GUID, UIA_IsContentElementPropertyId },
5923 { &LabeledBy_Property_GUID, UIA_LabeledByPropertyId },
5924 { &IsPassword_Property_GUID, UIA_IsPasswordPropertyId },
5925 { &NewNativeWindowHandle_Property_GUID, UIA_NativeWindowHandlePropertyId },
5926 { &ItemType_Property_GUID, UIA_ItemTypePropertyId },
5927 { &IsOffscreen_Property_GUID, UIA_IsOffscreenPropertyId },
5928 { &Orientation_Property_GUID, UIA_OrientationPropertyId },
5929 { &FrameworkId_Property_GUID, UIA_FrameworkIdPropertyId },
5930 { &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId },
5931 { &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId },
5932 { &IsDockPatternAvailable_Property_GUID, UIA_IsDockPatternAvailablePropertyId },
5933 { &IsExpandCollapsePatternAvailable_Property_GUID, UIA_IsExpandCollapsePatternAvailablePropertyId },
5934 { &IsGridItemPatternAvailable_Property_GUID, UIA_IsGridItemPatternAvailablePropertyId },
5935 { &IsGridPatternAvailable_Property_GUID, UIA_IsGridPatternAvailablePropertyId },
5936 { &IsInvokePatternAvailable_Property_GUID, UIA_IsInvokePatternAvailablePropertyId },
5937 { &IsMultipleViewPatternAvailable_Property_GUID, UIA_IsMultipleViewPatternAvailablePropertyId },
5938 { &IsRangeValuePatternAvailable_Property_GUID, UIA_IsRangeValuePatternAvailablePropertyId },
5939 { &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId },
5940 { &IsScrollItemPatternAvailable_Property_GUID, UIA_IsScrollItemPatternAvailablePropertyId },
5941 { &IsSelectionItemPatternAvailable_Property_GUID, UIA_IsSelectionItemPatternAvailablePropertyId },
5942 { &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId },
5943 { &IsTablePatternAvailable_Property_GUID, UIA_IsTablePatternAvailablePropertyId },
5944 { &IsTableItemPatternAvailable_Property_GUID, UIA_IsTableItemPatternAvailablePropertyId },
5945 { &IsTextPatternAvailable_Property_GUID, UIA_IsTextPatternAvailablePropertyId },
5946 { &IsTogglePatternAvailable_Property_GUID, UIA_IsTogglePatternAvailablePropertyId },
5947 { &IsTransformPatternAvailable_Property_GUID, UIA_IsTransformPatternAvailablePropertyId },
5948 { &IsValuePatternAvailable_Property_GUID, UIA_IsValuePatternAvailablePropertyId },
5949 { &IsWindowPatternAvailable_Property_GUID, UIA_IsWindowPatternAvailablePropertyId },
5950 { &Value_Value_Property_GUID, UIA_ValueValuePropertyId },
5951 { &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId },
5952 { &RangeValue_Value_Property_GUID, UIA_RangeValueValuePropertyId },
5953 { &RangeValue_IsReadOnly_Property_GUID, UIA_RangeValueIsReadOnlyPropertyId },
5954 { &RangeValue_Minimum_Property_GUID, UIA_RangeValueMinimumPropertyId },
5955 { &RangeValue_Maximum_Property_GUID, UIA_RangeValueMaximumPropertyId },
5956 { &RangeValue_LargeChange_Property_GUID, UIA_RangeValueLargeChangePropertyId },
5957 { &RangeValue_SmallChange_Property_GUID, UIA_RangeValueSmallChangePropertyId },
5958 { &Scroll_HorizontalScrollPercent_Property_GUID, UIA_ScrollHorizontalScrollPercentPropertyId },
5959 { &Scroll_HorizontalViewSize_Property_GUID, UIA_ScrollHorizontalViewSizePropertyId },
5960 { &Scroll_VerticalScrollPercent_Property_GUID, UIA_ScrollVerticalScrollPercentPropertyId },
5961 { &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId },
5962 { &Scroll_HorizontallyScrollable_Property_GUID, UIA_ScrollHorizontallyScrollablePropertyId },
5963 { &Scroll_VerticallyScrollable_Property_GUID, UIA_ScrollVerticallyScrollablePropertyId },
5964 { &Selection_Selection_Property_GUID, UIA_SelectionSelectionPropertyId },
5965 { &Selection_CanSelectMultiple_Property_GUID, UIA_SelectionCanSelectMultiplePropertyId },
5966 { &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId },
5967 { &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId },
5968 { &Grid_ColumnCount_Property_GUID, UIA_GridColumnCountPropertyId },
5969 { &GridItem_Row_Property_GUID, UIA_GridItemRowPropertyId },
5970 { &GridItem_Column_Property_GUID, UIA_GridItemColumnPropertyId },
5971 { &GridItem_RowSpan_Property_GUID, UIA_GridItemRowSpanPropertyId },
5972 { &GridItem_ColumnSpan_Property_GUID, UIA_GridItemColumnSpanPropertyId },
5973 { &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId },
5974 { &Dock_DockPosition_Property_GUID, UIA_DockDockPositionPropertyId },
5975 { &ExpandCollapse_ExpandCollapseState_Property_GUID, UIA_ExpandCollapseExpandCollapseStatePropertyId },
5976 { &MultipleView_CurrentView_Property_GUID, UIA_MultipleViewCurrentViewPropertyId },
5977 { &MultipleView_SupportedViews_Property_GUID, UIA_MultipleViewSupportedViewsPropertyId },
5978 { &Window_CanMaximize_Property_GUID, UIA_WindowCanMaximizePropertyId },
5979 { &Window_CanMinimize_Property_GUID, UIA_WindowCanMinimizePropertyId },
5980 { &Window_WindowVisualState_Property_GUID, UIA_WindowWindowVisualStatePropertyId },
5981 { &Window_WindowInteractionState_Property_GUID, UIA_WindowWindowInteractionStatePropertyId },
5982 { &Window_IsModal_Property_GUID, UIA_WindowIsModalPropertyId },
5983 { &Window_IsTopmost_Property_GUID, UIA_WindowIsTopmostPropertyId },
5984 { &SelectionItem_IsSelected_Property_GUID, UIA_SelectionItemIsSelectedPropertyId },
5985 { &SelectionItem_SelectionContainer_Property_GUID, UIA_SelectionItemSelectionContainerPropertyId },
5986 { &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId },
5987 { &Table_ColumnHeaders_Property_GUID, UIA_TableColumnHeadersPropertyId },
5988 { &Table_RowOrColumnMajor_Property_GUID, UIA_TableRowOrColumnMajorPropertyId },
5989 { &TableItem_RowHeaderItems_Property_GUID, UIA_TableItemRowHeaderItemsPropertyId },
5990 { &TableItem_ColumnHeaderItems_Property_GUID, UIA_TableItemColumnHeaderItemsPropertyId },
5991 { &Toggle_ToggleState_Property_GUID, UIA_ToggleToggleStatePropertyId },
5992 { &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId },
5993 { &Transform_CanResize_Property_GUID, UIA_TransformCanResizePropertyId },
5994 { &Transform_CanRotate_Property_GUID, UIA_TransformCanRotatePropertyId },
5995 { &IsLegacyIAccessiblePatternAvailable_Property_GUID, UIA_IsLegacyIAccessiblePatternAvailablePropertyId },
5996 { &LegacyIAccessible_ChildId_Property_GUID, UIA_LegacyIAccessibleChildIdPropertyId },
5997 { &LegacyIAccessible_Name_Property_GUID, UIA_LegacyIAccessibleNamePropertyId },
5998 { &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId },
5999 { &LegacyIAccessible_Description_Property_GUID, UIA_LegacyIAccessibleDescriptionPropertyId },
6000 { &LegacyIAccessible_Role_Property_GUID, UIA_LegacyIAccessibleRolePropertyId },
6001 { &LegacyIAccessible_State_Property_GUID, UIA_LegacyIAccessibleStatePropertyId },
6002 { &LegacyIAccessible_Help_Property_GUID, UIA_LegacyIAccessibleHelpPropertyId },
6003 { &LegacyIAccessible_KeyboardShortcut_Property_GUID, UIA_LegacyIAccessibleKeyboardShortcutPropertyId },
6004 { &LegacyIAccessible_Selection_Property_GUID, UIA_LegacyIAccessibleSelectionPropertyId },
6005 { &LegacyIAccessible_DefaultAction_Property_GUID, UIA_LegacyIAccessibleDefaultActionPropertyId },
6006 { &AriaRole_Property_GUID, UIA_AriaRolePropertyId },
6007 { &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId },
6008 { &IsDataValidForForm_Property_GUID, UIA_IsDataValidForFormPropertyId },
6009 { &ControllerFor_Property_GUID, UIA_ControllerForPropertyId },
6010 { &DescribedBy_Property_GUID, UIA_DescribedByPropertyId },
6011 { &FlowsTo_Property_GUID, UIA_FlowsToPropertyId },
6012 { &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId },
6013 { &IsItemContainerPatternAvailable_Property_GUID, UIA_IsItemContainerPatternAvailablePropertyId },
6014 { &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId },
6015 { &IsSynchronizedInputPatternAvailable_Property_GUID, UIA_IsSynchronizedInputPatternAvailablePropertyId },
6016 /* Implemented on Win8+ */
6017 { &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId },
6018 { &IsObjectModelPatternAvailable_Property_GUID, UIA_IsObjectModelPatternAvailablePropertyId },
6019 { &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId },
6020 { &Annotation_AnnotationTypeName_Property_GUID, UIA_AnnotationAnnotationTypeNamePropertyId },
6021 { &Annotation_Author_Property_GUID, UIA_AnnotationAuthorPropertyId },
6022 { &Annotation_DateTime_Property_GUID, UIA_AnnotationDateTimePropertyId },
6023 { &Annotation_Target_Property_GUID, UIA_AnnotationTargetPropertyId },
6024 { &IsAnnotationPatternAvailable_Property_GUID, UIA_IsAnnotationPatternAvailablePropertyId },
6025 { &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId },
6026 { &Styles_StyleId_Property_GUID, UIA_StylesStyleIdPropertyId },
6027 { &Styles_StyleName_Property_GUID, UIA_StylesStyleNamePropertyId },
6028 { &Styles_FillColor_Property_GUID, UIA_StylesFillColorPropertyId },
6029 { &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId },
6030 { &Styles_Shape_Property_GUID, UIA_StylesShapePropertyId },
6031 { &Styles_FillPatternColor_Property_GUID, UIA_StylesFillPatternColorPropertyId },
6032 { &Styles_ExtendedProperties_Property_GUID, UIA_StylesExtendedPropertiesPropertyId },
6033 { &IsStylesPatternAvailable_Property_GUID, UIA_IsStylesPatternAvailablePropertyId },
6034 { &IsSpreadsheetPatternAvailable_Property_GUID, UIA_IsSpreadsheetPatternAvailablePropertyId },
6035 { &SpreadsheetItem_Formula_Property_GUID, UIA_SpreadsheetItemFormulaPropertyId },
6036 { &SpreadsheetItem_AnnotationObjects_Property_GUID, UIA_SpreadsheetItemAnnotationObjectsPropertyId },
6037 { &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId },
6038 { &IsSpreadsheetItemPatternAvailable_Property_GUID, UIA_IsSpreadsheetItemPatternAvailablePropertyId },
6039 { &Transform2_CanZoom_Property_GUID, UIA_Transform2CanZoomPropertyId },
6040 { &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId },
6041 { &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId },
6042 { &IsTextChildPatternAvailable_Property_GUID, UIA_IsTextChildPatternAvailablePropertyId },
6043 { &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId },
6044 { &Drag_IsGrabbed_Property_GUID, UIA_DragIsGrabbedPropertyId },
6045 { &Drag_DropEffect_Property_GUID, UIA_DragDropEffectPropertyId },
6046 { &Drag_DropEffects_Property_GUID, UIA_DragDropEffectsPropertyId },
6047 { &IsDropTargetPatternAvailable_Property_GUID, UIA_IsDropTargetPatternAvailablePropertyId },
6048 { &DropTarget_DropTargetEffect_Property_GUID, UIA_DropTargetDropTargetEffectPropertyId },
6049 { &DropTarget_DropTargetEffects_Property_GUID, UIA_DropTargetDropTargetEffectsPropertyId },
6050 { &Drag_GrabbedItems_Property_GUID, UIA_DragGrabbedItemsPropertyId },
6051 { &Transform2_ZoomLevel_Property_GUID, UIA_Transform2ZoomLevelPropertyId },
6052 { &Transform2_ZoomMinimum_Property_GUID, UIA_Transform2ZoomMinimumPropertyId },
6053 { &Transform2_ZoomMaximum_Property_GUID, UIA_Transform2ZoomMaximumPropertyId },
6054 { &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId },
6055 { &IsTextEditPatternAvailable_Property_GUID, UIA_IsTextEditPatternAvailablePropertyId },
6056 { &IsPeripheral_Property_GUID, UIA_IsPeripheralPropertyId },
6057 /* Implemented on Win10v1507+. */
6058 { &IsCustomNavigationPatternAvailable_Property_GUID, UIA_IsCustomNavigationPatternAvailablePropertyId },
6059 { &PositionInSet_Property_GUID, UIA_PositionInSetPropertyId },
6060 { &SizeOfSet_Property_GUID, UIA_SizeOfSetPropertyId },
6061 { &Level_Property_GUID, UIA_LevelPropertyId },
6062 { &AnnotationTypes_Property_GUID, UIA_AnnotationTypesPropertyId },
6063 { &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId },
6064 /* Implemented on Win10v1809+. */
6065 { &LandmarkType_Property_GUID, UIA_LandmarkTypePropertyId },
6066 { &LocalizedLandmarkType_Property_GUID, UIA_LocalizedLandmarkTypePropertyId },
6067 { &FullDescription_Property_GUID, UIA_FullDescriptionPropertyId },
6068 { &FillColor_Property_GUID, UIA_FillColorPropertyId },
6069 { &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId },
6070 { &FillType_Property_GUID, UIA_FillTypePropertyId },
6071 { &VisualEffects_Property_GUID, UIA_VisualEffectsPropertyId },
6072 { &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId },
6073 { &CenterPoint_Property_GUID, UIA_CenterPointPropertyId },
6074 { &Rotation_Property_GUID, UIA_RotationPropertyId },
6075 { &Size_Property_GUID, UIA_SizePropertyId },
6076 { &IsSelectionPattern2Available_Property_GUID, UIA_IsSelectionPattern2AvailablePropertyId },
6077 { &Selection2_FirstSelectedItem_Property_GUID, UIA_Selection2FirstSelectedItemPropertyId },
6078 { &Selection2_LastSelectedItem_Property_GUID, UIA_Selection2LastSelectedItemPropertyId },
6079 { &Selection2_CurrentSelectedItem_Property_GUID, UIA_Selection2CurrentSelectedItemPropertyId },
6080 { &Selection2_ItemCount_Property_GUID, UIA_Selection2ItemCountPropertyId },
6081 { &HeadingLevel_Property_GUID, UIA_HeadingLevelPropertyId },
6082 { &IsDialog_Property_GUID, UIA_IsDialogPropertyId },
6083};
6084
6085static const struct uia_lookup_id uia_event_lookup_ids[] = {
6086 { &ToolTipOpened_Event_GUID, UIA_ToolTipOpenedEventId },
6087 { &ToolTipClosed_Event_GUID, UIA_ToolTipClosedEventId },
6088 { &StructureChanged_Event_GUID, UIA_StructureChangedEventId },
6089 { &MenuOpened_Event_GUID, UIA_MenuOpenedEventId },
6090 { &AutomationPropertyChanged_Event_GUID, UIA_AutomationPropertyChangedEventId },
6091 { &AutomationFocusChanged_Event_GUID, UIA_AutomationFocusChangedEventId },
6092 { &AsyncContentLoaded_Event_GUID, UIA_AsyncContentLoadedEventId },
6093 { &MenuClosed_Event_GUID, UIA_MenuClosedEventId },
6094 { &LayoutInvalidated_Event_GUID, UIA_LayoutInvalidatedEventId },
6095 { &Invoke_Invoked_Event_GUID, UIA_Invoke_InvokedEventId },
6096 { &SelectionItem_ElementAddedToSelectionEvent_Event_GUID, UIA_SelectionItem_ElementAddedToSelectionEventId },
6097 { &SelectionItem_ElementRemovedFromSelectionEvent_Event_GUID, UIA_SelectionItem_ElementRemovedFromSelectionEventId },
6098 { &SelectionItem_ElementSelectedEvent_Event_GUID, UIA_SelectionItem_ElementSelectedEventId },
6099 { &Selection_InvalidatedEvent_Event_GUID, UIA_Selection_InvalidatedEventId },
6100 { &Text_TextSelectionChangedEvent_Event_GUID, UIA_Text_TextSelectionChangedEventId },
6101 { &Text_TextChangedEvent_Event_GUID, UIA_Text_TextChangedEventId },
6102 { &Window_WindowOpened_Event_GUID, UIA_Window_WindowOpenedEventId },
6103 { &Window_WindowClosed_Event_GUID, UIA_Window_WindowClosedEventId },
6104 { &MenuModeStart_Event_GUID, UIA_MenuModeStartEventId },
6105 { &MenuModeEnd_Event_GUID, UIA_MenuModeEndEventId },
6106 { &InputReachedTarget_Event_GUID, UIA_InputReachedTargetEventId },
6107 { &InputReachedOtherElement_Event_GUID, UIA_InputReachedOtherElementEventId },
6108 { &InputDiscarded_Event_GUID, UIA_InputDiscardedEventId },
6109 /* Implemented on Win8+ */
6110 { &SystemAlert_Event_GUID, UIA_SystemAlertEventId },
6111 { &LiveRegionChanged_Event_GUID, UIA_LiveRegionChangedEventId },
6112 { &HostedFragmentRootsInvalidated_Event_GUID, UIA_HostedFragmentRootsInvalidatedEventId },
6113 { &Drag_DragStart_Event_GUID, UIA_Drag_DragStartEventId },
6114 { &Drag_DragCancel_Event_GUID, UIA_Drag_DragCancelEventId },
6115 { &Drag_DragComplete_Event_GUID, UIA_Drag_DragCompleteEventId },
6116 { &DropTarget_DragEnter_Event_GUID, UIA_DropTarget_DragEnterEventId },
6117 { &DropTarget_DragLeave_Event_GUID, UIA_DropTarget_DragLeaveEventId },
6118 { &DropTarget_Dropped_Event_GUID, UIA_DropTarget_DroppedEventId },
6119 { &TextEdit_TextChanged_Event_GUID, UIA_TextEdit_TextChangedEventId },
6120 { &TextEdit_ConversionTargetChanged_Event_GUID, UIA_TextEdit_ConversionTargetChangedEventId },
6121 /* Implemented on Win10v1809+. */
6122 { &Changes_Event_GUID, UIA_ChangesEventId },
6123 { &Notification_Event_GUID, UIA_NotificationEventId },
6124};
6125
6126static const struct uia_lookup_id uia_pattern_lookup_ids[] = {
6127 { &Invoke_Pattern_GUID, UIA_InvokePatternId },
6128 { &Selection_Pattern_GUID, UIA_SelectionPatternId },
6129 { &Value_Pattern_GUID, UIA_ValuePatternId },
6130 { &RangeValue_Pattern_GUID, UIA_RangeValuePatternId },
6131 { &Scroll_Pattern_GUID, UIA_ScrollPatternId },
6132 { &ExpandCollapse_Pattern_GUID, UIA_ExpandCollapsePatternId },
6133 { &Grid_Pattern_GUID, UIA_GridPatternId },
6134 { &GridItem_Pattern_GUID, UIA_GridItemPatternId },
6135 { &MultipleView_Pattern_GUID, UIA_MultipleViewPatternId },
6136 { &Window_Pattern_GUID, UIA_WindowPatternId },
6137 { &SelectionItem_Pattern_GUID, UIA_SelectionItemPatternId },
6138 { &Dock_Pattern_GUID, UIA_DockPatternId },
6139 { &Table_Pattern_GUID, UIA_TablePatternId },
6140 { &TableItem_Pattern_GUID, UIA_TableItemPatternId },
6141 { &Text_Pattern_GUID, UIA_TextPatternId },
6142 { &Toggle_Pattern_GUID, UIA_TogglePatternId },
6143 { &Transform_Pattern_GUID, UIA_TransformPatternId },
6144 { &ScrollItem_Pattern_GUID, UIA_ScrollItemPatternId },
6145 { &LegacyIAccessible_Pattern_GUID, UIA_LegacyIAccessiblePatternId },
6146 { &ItemContainer_Pattern_GUID, UIA_ItemContainerPatternId },
6147 { &VirtualizedItem_Pattern_GUID, UIA_VirtualizedItemPatternId },
6148 { &SynchronizedInput_Pattern_GUID, UIA_SynchronizedInputPatternId },
6149 /* Implemented on Win8+ */
6150 { &ObjectModel_Pattern_GUID, UIA_ObjectModelPatternId },
6151 { &Annotation_Pattern_GUID, UIA_AnnotationPatternId },
6152 { &Text_Pattern2_GUID, UIA_TextPattern2Id },
6153 { &Styles_Pattern_GUID, UIA_StylesPatternId },
6154 { &Spreadsheet_Pattern_GUID, UIA_SpreadsheetPatternId },
6155 { &SpreadsheetItem_Pattern_GUID, UIA_SpreadsheetItemPatternId },
6156 { &Tranform_Pattern2_GUID, UIA_TransformPattern2Id },
6157 { &TextChild_Pattern_GUID, UIA_TextChildPatternId },
6158 { &Drag_Pattern_GUID, UIA_DragPatternId },
6159 { &DropTarget_Pattern_GUID, UIA_DropTargetPatternId },
6160 { &TextEdit_Pattern_GUID, UIA_TextEditPatternId },
6161 /* Implemented on Win10+. */
6162 { &CustomNavigation_Pattern_GUID, UIA_CustomNavigationPatternId },
6163};
6164
6166 { &Button_Control_GUID, UIA_ButtonControlTypeId },
6167 { &Calendar_Control_GUID, UIA_CalendarControlTypeId },
6168 { &CheckBox_Control_GUID, UIA_CheckBoxControlTypeId },
6169 { &ComboBox_Control_GUID, UIA_ComboBoxControlTypeId },
6170 { &Edit_Control_GUID, UIA_EditControlTypeId },
6171 { &Hyperlink_Control_GUID, UIA_HyperlinkControlTypeId },
6172 { &Image_Control_GUID, UIA_ImageControlTypeId },
6173 { &ListItem_Control_GUID, UIA_ListItemControlTypeId },
6174 { &List_Control_GUID, UIA_ListControlTypeId },
6175 { &Menu_Control_GUID, UIA_MenuControlTypeId },
6176 { &MenuBar_Control_GUID, UIA_MenuBarControlTypeId },
6177 { &MenuItem_Control_GUID, UIA_MenuItemControlTypeId },
6178 { &ProgressBar_Control_GUID, UIA_ProgressBarControlTypeId },
6179 { &RadioButton_Control_GUID, UIA_RadioButtonControlTypeId },
6180 { &ScrollBar_Control_GUID, UIA_ScrollBarControlTypeId },
6181 { &Slider_Control_GUID, UIA_SliderControlTypeId },
6182 { &Spinner_Control_GUID, UIA_SpinnerControlTypeId },
6183 { &StatusBar_Control_GUID, UIA_StatusBarControlTypeId },
6184 { &Tab_Control_GUID, UIA_TabControlTypeId },
6185 { &TabItem_Control_GUID, UIA_TabItemControlTypeId },
6186 { &Text_Control_GUID, UIA_TextControlTypeId },
6187 { &ToolBar_Control_GUID, UIA_ToolBarControlTypeId },
6188 { &ToolTip_Control_GUID, UIA_ToolTipControlTypeId },
6189 { &Tree_Control_GUID, UIA_TreeControlTypeId },
6190 { &TreeItem_Control_GUID, UIA_TreeItemControlTypeId },
6191 { &Custom_Control_GUID, UIA_CustomControlTypeId },
6192 { &Group_Control_GUID, UIA_GroupControlTypeId },
6193 { &Thumb_Control_GUID, UIA_ThumbControlTypeId },
6194 { &DataGrid_Control_GUID, UIA_DataGridControlTypeId },
6195 { &DataItem_Control_GUID, UIA_DataItemControlTypeId },
6196 { &Document_Control_GUID, UIA_DocumentControlTypeId },
6197 { &SplitButton_Control_GUID, UIA_SplitButtonControlTypeId },
6198 { &Window_Control_GUID, UIA_WindowControlTypeId },
6199 { &Pane_Control_GUID, UIA_PaneControlTypeId },
6200 { &Header_Control_GUID, UIA_HeaderControlTypeId },
6201 { &HeaderItem_Control_GUID, UIA_HeaderItemControlTypeId },
6202 { &Table_Control_GUID, UIA_TableControlTypeId },
6203 { &TitleBar_Control_GUID, UIA_TitleBarControlTypeId },
6204 { &Separator_Control_GUID, UIA_SeparatorControlTypeId },
6205 /* Implemented on Win8+ */
6206 { &SemanticZoom_Control_GUID, UIA_SemanticZoomControlTypeId },
6207 { &AppBar_Control_GUID, UIA_AppBarControlTypeId },
6208};
6209
6210static void test_UiaLookupId(void)
6211{
6212 static const struct {
6213 const char *id_type_name;
6214 int id_type;
6215 const struct uia_lookup_id *ids;
6216 int ids_count;
6217 } tests[] =
6218 {
6223 };
6224 unsigned int i, y;
6225
6226 for (i = 0; i < ARRAY_SIZE(tests); i++)
6227 {
6228 for (y = 0; y < tests[i].ids_count; y++)
6229 {
6230 int id = UiaLookupId(tests[i].id_type, tests[i].ids[y].guid);
6231
6232 if (!id)
6233 {
6234 win_skip("No %s id for GUID %s, skipping further tests.\n", tests[i].id_type_name, debugstr_guid(tests[i].ids[y].guid));
6235 break;
6236 }
6237
6238 ok(id == tests[i].ids[y].id, "Unexpected %s id, expected %d, got %d\n", tests[i].id_type_name, tests[i].ids[y].id, id);
6239 }
6240 }
6241}
6242
6243static const struct prov_method_sequence node_from_prov1[] = {
6245 { 0 }
6246};
6247
6248static const struct prov_method_sequence node_from_prov2[] = {
6250 /* Win10v1507 and below call this. */
6251 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6253 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6254 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6255 /* Only called on Windows versions past Win10v1507. */
6257 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6258 { 0 }
6259};
6260
6261static const struct prov_method_sequence node_from_prov3[] = {
6263 /* Win10v1507 and below call this. */
6264 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6266 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6267 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6268 /* Only called on Windows versions past Win10v1507. */
6270 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6271 { 0 }
6272};
6273
6274static const struct prov_method_sequence node_from_prov4[] = {
6276 /* Win10v1507 and below call this. */
6277 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6279 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6280 /* Only called on Windows versions past Win10v1507. */
6282 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6283 { 0 }
6284};
6285
6286static const struct prov_method_sequence node_from_prov5[] = {
6288 /* Win10v1507 and below call this. */
6289 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6292 /* Win10v1507 and below call this. */
6293 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6295 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6296 /* These three are only done on Win10v1507 and below. */
6299 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6300 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6301 /* This is only done on Win10v1507. */
6303 /* Only called on Windows versions past Win10v1507. */
6305 /* Win10v1507 and below call this. */
6306 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
6307 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6308 { 0 }
6309};
6310
6311static const struct prov_method_sequence node_from_prov6[] = {
6313 /* Win10v1507 and below call this. */
6314 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6317 /* Win10v1507 and below call this. */
6318 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6320 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6323 /* Only called on Windows versions past Win10v1507. */
6325 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6326 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6327 /* This is only done on Win10v1507. */
6329 /* Only called on Windows versions past Win10v1507. */
6331 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6332 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6333 { 0 }
6334};
6335
6336static const struct prov_method_sequence node_from_prov7[] = {
6338 /* Win10v1507 and below call this. */
6339 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6342 /* Win10v1507 and below call this. */
6343 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6345 { &Provider2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6348 /* Only called on Windows versions past Win10v1507. */
6350 { &Provider2, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
6351 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6352 /* This is only done on Win10v1507. */
6354 /* Only called on Windows versions past Win10v1507. */
6356 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6357 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
6358 { 0 }
6359};
6360
6361static const struct prov_method_sequence node_from_prov8[] = {
6363 /* Win10v1507 and below call this. */
6364 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6366 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6367 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6368 /* Only called on Windows versions past Win10v1507. */
6370 { 0 }
6371};
6372
6373static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com);
6375{
6376 HUIANODE node = param;
6377 HRESULT hr;
6378 VARIANT v;
6379
6380 /*
6381 * Since this is a node representing an IRawElementProviderSimple with
6382 * ProviderOptions_UseComThreading set, it is only usable in threads that
6383 * have initialized COM.
6384 */
6385 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
6386 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
6387
6389
6390 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
6391 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6392 check_uia_prop_val(UIA_ProcessIdPropertyId, UIAutomationType_Int, &v, FALSE);
6393
6394 /*
6395 * When retrieving a UIAutomationType_Element property, if UseComThreading
6396 * is set, we'll get an HUIANODE that will make calls inside of the
6397 * apartment of the node it is retrieved from. I.e, if we received a node
6398 * with UseComThreading set from another node with UseComThreading set
6399 * inside of an STA, the returned node will have all of its methods called
6400 * from the STA thread.
6401 */
6403 Provider_child.expected_tid = Provider.expected_tid;
6404 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6405 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6406 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
6407
6408 /* Unset ProviderOptions_UseComThreading. */
6410 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
6411 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6412
6413 /*
6414 * ProviderOptions_UseComThreading not set, GetPropertyValue will be
6415 * called on the current thread.
6416 */
6417 Provider_child.expected_tid = GetCurrentThreadId();
6418 check_uia_prop_val(UIA_LabeledByPropertyId, UIAutomationType_Element, &v, FALSE);
6419
6421
6422 return 0;
6423}
6424
6426{
6427 HANDLE thread;
6428 HUIANODE node;
6429 HRESULT hr;
6430
6431 /* Test ProviderOptions_UseComThreading. */
6432 Provider.hwnd = NULL;
6433 prov_root = NULL;
6436 ok_method_sequence(node_from_prov8, "node_from_prov8");
6437
6438 /*
6439 * On Windows versions prior to Windows 10, UiaNodeFromProvider ignores the
6440 * ProviderOptions_UseComThreading flag.
6441 */
6442 if (hr == S_OK)
6443 {
6444 win_skip("Skipping ProviderOptions_UseComThreading tests for UiaNodeFromProvider.\n");
6446 return;
6447 }
6448 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx.\n", hr);
6449
6452 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6453 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6454 ok_method_sequence(node_from_prov8, "node_from_prov8");
6455
6459 {
6460 MSG msg;
6461 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
6462 {
6465 }
6466 }
6468
6469 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6470 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6471 Provider_child.expected_tid = Provider.expected_tid = 0;
6472
6474}
6476{
6477 WNDCLASSA cls;
6478 HUIANODE node;
6479 HRESULT hr;
6480 ULONG ref;
6481 HWND hwnd;
6482 VARIANT v;
6483
6484 cls.style = 0;
6486 cls.cbClsExtra = 0;
6487 cls.cbWndExtra = 0;
6489 cls.hIcon = 0;
6490 cls.hCursor = NULL;
6491 cls.hbrBackground = NULL;
6492 cls.lpszMenuName = NULL;
6493 cls.lpszClassName = "UiaNodeFromProvider class";
6494
6495 RegisterClassA(&cls);
6496
6497 hwnd = CreateWindowA("UiaNodeFromProvider class", "Test window", WS_OVERLAPPEDWINDOW,
6498 0, 0, 100, 100, NULL, NULL, NULL, NULL);
6499
6500 /* Run these tests early, we end up in an implicit MTA later. */
6502
6504
6506 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6507
6509 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
6510
6511 /* Must have a successful call to get_ProviderOptions. */
6512 Provider.prov_opts = 0;
6513 node = (void *)0xdeadbeef;
6515 ok(hr == E_NOTIMPL, "Unexpected hr %#lx.\n", hr);
6516 ok(!node, "node != NULL\n");
6517 ok_method_sequence(node_from_prov1, "node_from_prov1");
6518
6519 /* No HWND exposed through Provider. */
6521 node = (void *)0xdeadbeef;
6523 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6524
6525 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6526 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6528 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
6529 VariantClear(&v);
6530
6531 ok_method_sequence(node_from_prov2, "node_from_prov2");
6532
6533 /* HUIANODE represents a COM interface. */
6534 ref = IUnknown_AddRef((IUnknown *)node);
6535 ok(ref == 2, "Unexpected refcnt %ld\n", ref);
6536
6537 ref = IUnknown_AddRef((IUnknown *)node);
6538 ok(ref == 3, "Unexpected refcnt %ld\n", ref);
6539
6540 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6541
6542 ref = IUnknown_Release((IUnknown *)node);
6543 ok(ref == 1, "Unexpected refcnt %ld\n", ref);
6544
6545 ref = IUnknown_Release((IUnknown *)node);
6546 ok(ref == 0, "Unexpected refcnt %ld\n", ref);
6547 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6548
6549 /*
6550 * No HWND exposed through Provider_child, but it returns a parent from
6551 * NavigateDirection_Parent. Behavior doesn't change.
6552 */
6554 node = (void *)0xdeadbeef;
6555 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
6556 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6557
6558 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6559 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6561 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
6562 VariantClear(&v);
6563
6564 ok_method_sequence(node_from_prov3, "node_from_prov3");
6565 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6566 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6567
6568 /* HWND exposed, but Provider2 not returned from WM_GETOBJECT. */
6569 Provider.hwnd = hwnd;
6570 prov_root = NULL;
6571 node = (void *)0xdeadbeef;
6572 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6573 /* Win10v1507 and below send this, Windows 7 sends it twice. */
6574 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
6577 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6578 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6579 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6580 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6581
6582 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6583 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6585 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
6588 VariantClear(&v);
6589
6591 ok_method_sequence(node_from_prov4, "node_from_prov4");
6592
6593 ok(!!node, "node == NULL\n");
6594 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6595 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6596
6597 /*
6598 * Provider is our main provider, since Provider2 is also a main, it won't
6599 * get added.
6600 */
6601 Provider.hwnd = Provider2.hwnd = hwnd;
6603 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = TRUE;
6604 prov_root = &Provider2.IRawElementProviderSimple_iface;
6605 node = (void *)0xdeadbeef;
6606 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6607 /* Windows 7 sends this. */
6608 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6610 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6611 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6612 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6613
6614 /* Win10v1507 and below hold a reference to the root provider for the HWND */
6615 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6616 ok(!!node, "node == NULL\n");
6617
6618 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6619 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6621 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
6624 VariantClear(&v);
6625
6626 Provider.ignore_hwnd_prop = Provider2.ignore_hwnd_prop = FALSE;
6627 ok_method_sequence(node_from_prov5, "node_from_prov5");
6628
6629 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6630 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6631 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6632
6633 /*
6634 * Provider is classified as an Hwnd provider, Provider2 will become our
6635 * Main provider since we don't have one already.
6636 */
6639 prov_root = &Provider2.IRawElementProviderSimple_iface;
6640 node = (void *)0xdeadbeef;
6641 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6642 /* Windows 7 sends this. */
6643 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6645 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6646 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6647 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6648
6649 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6650 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6652 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
6654 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
6655 VariantClear(&v);
6656
6657 ok_method_sequence(node_from_prov6, "node_from_prov6");
6658
6659 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
6660 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6661
6662 ok(!!node, "node == NULL\n");
6663 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6664 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6665 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6666
6667 /* Provider_child has a parent, so it will be "(parent link)". */
6669 Provider_child.hwnd = hwnd;
6671 prov_root = &Provider2.IRawElementProviderSimple_iface;
6672 node = (void *)0xdeadbeef;
6673 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
6674 /* Windows 7 sends this. */
6675 SET_EXPECT(winproc_GETOBJECT_CLIENT);
6676 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
6677 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6678 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
6679 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
6680
6681 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
6682 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6684 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", FALSE);
6686 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_child", TRUE);
6687 VariantClear(&v);
6688
6689 ok_method_sequence(node_from_prov7, "node_from_prov7");
6690
6691 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
6692 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
6693
6694 ok(!!node, "node == NULL\n");
6695 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
6696 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
6697 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
6698
6701 UnregisterClassA("UiaNodeFromProvider class", NULL);
6702 prov_root = NULL;
6703}
6704
6705/* Sequence for types other than UIAutomationType_Element. */
6706static const struct prov_method_sequence get_prop_seq[] = {
6708 { 0 }
6709};
6710
6711/* Sequence for getting a property that returns an invalid type. */
6714 /* Windows 7 calls this. */
6716 { 0 }
6717};
6718
6719/* UIAutomationType_Element sequence. */
6723 /* Win10v1507 and below call this. */
6724 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6726 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6727 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6728 /* Only called on Windows versions past Win10v1507. */
6731 { 0 }
6732};
6733
6734/* UIAutomationType_ElementArray sequence. */
6738 /* Win10v1507 and below call this. */
6739 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6741 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6742 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6745 /* Win10v1507 and below call this. */
6746 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6748 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
6749 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
6753 { 0 }
6754};
6755
6758 { 0 }
6759};
6760
6764 { 0 }
6765};
6766
6770 /*
6771 * Win10v21H2+ and above call these, attempting to get the fragment root's
6772 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6773 */
6776 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6778 { 0 }
6779};
6780
6785 /*
6786 * Win10v21H2+ and above call these, attempting to get the fragment root's
6787 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6788 */
6791 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6793 { 0 }
6794};
6795
6798 /*
6799 * Win10v21H2+ and above call these, attempting to get the fragment root's
6800 * HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
6801 */
6804 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
6806 { 0 }
6807};
6808
6811 { 0 }
6812};
6813
6814static void set_uia_rect(struct UiaRect *rect, double left, double top, double width, double height)
6815{
6816 rect->left = left;
6817 rect->top = top;
6818 rect->width = width;
6819 rect->height = height;
6820}
6821
6822#define check_uia_rect_val( v, rect ) \
6823 check_uia_rect_val_( (v), (rect), __FILE__, __LINE__)
6824static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *file, int line)
6825{
6826 LONG lbound, ubound, elems, idx;
6827 SAFEARRAY *sa;
6828 double tmp[4];
6829 VARTYPE vt;
6830 HRESULT hr;
6831 UINT dims;
6832
6833 ok_(file, line)(V_VT(v) == (VT_R8 | VT_ARRAY), "Unexpected rect VT hr %d.\n", V_VT(v));
6834 if (V_VT(v) != (VT_R8 | VT_ARRAY))
6835 return;
6836
6837 sa = V_ARRAY(v);
6839 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
6840 ok_(file, line)(vt == VT_R8, "Unexpected vt %d\n", vt);
6841
6842 dims = SafeArrayGetDim(sa);
6843 ok_(file, line)(dims == 1, "Unexpected dims %d\n", dims);
6844
6845 lbound = ubound = elems = 0;
6846 hr = SafeArrayGetLBound(sa, 1, &lbound);
6847 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
6848 ok_(file, line)(lbound == 0, "Unexpected lbound %ld\n", lbound);
6849
6850 hr = SafeArrayGetUBound(sa, 1, &ubound);
6851 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
6852 ok_(file, line)(ubound == 3, "Unexpected ubound %ld\n", ubound);
6853
6854 elems = (ubound - lbound) + 1;
6855 ok_(file, line)(elems == 4, "Unexpected rect elems %ld\n", elems);
6856
6857 for (idx = 0; idx < ARRAY_SIZE(tmp); idx++)
6858 {
6859 hr = SafeArrayGetElement(sa, &idx, &tmp[idx]);
6860 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetElement at idx %ld.\n", hr, idx);
6861 }
6862
6863 ok_(file, line)(tmp[0] == rect->left, "Unexpected left value %f, expected %f\n", tmp[0], rect->left);
6864 ok_(file, line)(tmp[1] == rect->top, "Unexpected top value %f, expected %f\n", tmp[1], rect->top);
6865 ok_(file, line)(tmp[2] == rect->width, "Unexpected width value %f, expected %f\n", tmp[2], rect->width);
6866 ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height);
6867}
6868
6869#define check_uia_rect_rect_val( rect, uia_rect ) \
6870 check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__)
6871static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line)
6872{
6873 ok_(file, line)(rect->left == (LONG)uia_rect->left, "Unexpected left value %ld, expected %ld\n", rect->left, (LONG)uia_rect->left);
6874 ok_(file, line)(rect->top == (LONG)uia_rect->top, "Unexpected top value %ld, expected %ld\n", rect->top, (LONG)uia_rect->top);
6875 ok_(file, line)(rect->right == (LONG)(uia_rect->left + uia_rect->width), "Unexpected right value %ld, expected %ld\n", rect->right,
6876 (LONG)(uia_rect->left + uia_rect->width));
6877 ok_(file, line)(rect->bottom == (LONG)(uia_rect->top + uia_rect->height), "Unexpected bottom value %ld, expected %ld\n", rect->bottom,
6878 (LONG)(uia_rect->top + uia_rect->height));
6879}
6880
6881static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com)
6882{
6883 LONG idx;
6884
6885 switch (type)
6886 {
6887 case UIAutomationType_String:
6888 ok(V_VT(v) == VT_BSTR, "Unexpected VT %d\n", V_VT(v));
6889 ok(!lstrcmpW(V_BSTR(v), uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(v)));
6891 break;
6892
6893 case UIAutomationType_Bool:
6894 ok(V_VT(v) == VT_BOOL, "Unexpected VT %d\n", V_VT(v));
6895
6896 /* UIA_IsKeyboardFocusablePropertyId is broken on Win8 and Win10v1507. */
6897 if (prop_id == UIA_IsKeyboardFocusablePropertyId)
6899 "Unexpected BOOL %#x\n", V_BOOL(v));
6900 else
6901 ok(check_variant_bool(v, TRUE), "Unexpected BOOL %#x\n", V_BOOL(v));
6903 break;
6904
6905 case UIAutomationType_Int:
6906 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
6907
6908 if (prop_id == UIA_NativeWindowHandlePropertyId)
6909 ok(ULongToHandle(V_I4(v)) == Provider.hwnd, "Unexpected I4 %#lx\n", V_I4(v));
6910 else
6911 ok(V_I4(v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(v));
6913 break;
6914
6915 case UIAutomationType_IntArray:
6916 ok(V_VT(v) == (VT_ARRAY | VT_I4), "Unexpected VT %d\n", V_VT(v));
6917
6918 for (idx = 0; idx < ARRAY_SIZE(uia_i4_arr_prop_val); idx++)
6919 {
6920 ULONG val;
6921
6923 ok(val == uia_i4_arr_prop_val[idx], "Unexpected I4 %#lx at idx %ld\n", val, idx);
6924 }
6926 break;
6927
6928 case UIAutomationType_Double:
6929 ok(V_VT(v) == VT_R8, "Unexpected VT %d\n", V_VT(v));
6930 ok(V_R8(v) == uia_r8_prop_val, "Unexpected R8 %lf\n", V_R8(v));
6932 break;
6933
6934 case UIAutomationType_DoubleArray:
6935 ok(V_VT(v) == (VT_ARRAY | VT_R8), "Unexpected VT %d\n", V_VT(v));
6936 for (idx = 0; idx < ARRAY_SIZE(uia_r8_arr_prop_val); idx++)
6937 {
6938 double val;
6939
6941 ok(val == uia_r8_arr_prop_val[idx], "Unexpected R8 %lf at idx %ld\n", val, idx);
6942 }
6944 break;
6945
6946 case UIAutomationType_Element:
6947 {
6948 HUIANODE tmp_node;
6949 HRESULT hr;
6950 VARIANT v1;
6951
6952 if (from_com)
6953 {
6954 IUIAutomationElement *elem;
6955
6956 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
6957 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElement, (void **)&elem);
6958 VariantClear(v);
6959 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6960 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6961
6962 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_ControlTypePropertyId, TRUE, &v1);
6963 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6964 IUIAutomationElement_Release(elem);
6965 }
6966 else
6967 {
6968#ifdef _WIN64
6969 ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
6970 tmp_node = (HUIANODE)V_I8(v);
6971#else
6972 ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
6973 tmp_node = (HUIANODE)V_I4(v);
6974#endif
6975 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6976
6977 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
6978 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
6979 ok(UiaNodeRelease(tmp_node), "Failed to release node\n");
6980 }
6981
6982 ok(V_VT(&v1) == VT_I4, "Unexpected VT %d\n", V_VT(&v1));
6983 ok(V_I4(&v1) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v1));
6984 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
6985
6987 break;
6988 }
6989
6990 case UIAutomationType_ElementArray:
6991 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
6992 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
6993 if (from_com)
6994 {
6995 IUIAutomationElementArray *elem_arr = NULL;
6996 HRESULT hr;
6997 int len;
6998
6999 ok(V_VT(v) == VT_UNKNOWN, "Unexpected VT %d\n", V_VT(v));
7000 hr = IUnknown_QueryInterface(V_UNKNOWN(v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
7001 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7002 ok(!!elem_arr, "elem_arr == NULL\n");
7003 if (!elem_arr)
7004 {
7005 VariantClear(v);
7006 break;
7007 }
7008
7009 hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
7010 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7011 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
7012
7013 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
7014 {
7015 IUIAutomationElement *tmp_elem = NULL;
7016 VARIANT v1;
7017
7018 hr = IUIAutomationElementArray_GetElement(elem_arr, idx, &tmp_elem);
7019 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7020 ok(!!tmp_elem, "tmp_elem == NULL\n");
7021
7022 hr = IUIAutomationElement_GetCurrentPropertyValueEx(tmp_elem, UIA_ControlTypePropertyId, TRUE, &v1);
7023 ok(hr == S_OK, "elem[%ld] Unexpected hr %#lx\n", idx, hr);
7024 ok(V_VT(&v1) == VT_I4, "elem[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
7025 ok(V_I4(&v1) == uia_i4_prop_val, "elem[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
7026
7027 IUIAutomationElement_Release(tmp_elem);
7028 VariantClear(&v1);
7029 }
7030
7031 IUIAutomationElementArray_Release(elem_arr);
7032 }
7033 else
7034 {
7035 ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v));
7036 if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN))
7037 break;
7038
7039 for (idx = 0; idx < ARRAY_SIZE(uia_unk_arr_prop_val); idx++)
7040 {
7041 HUIANODE tmp_node;
7042 HRESULT hr;
7043 VARIANT v1;
7044
7045 SafeArrayGetElement(V_ARRAY(v), &idx, &tmp_node);
7046
7047 hr = UiaGetPropertyValue(tmp_node, UIA_ControlTypePropertyId, &v1);
7048 ok(hr == S_OK, "node[%ld] Unexpected hr %#lx\n", idx, hr);
7049 ok(V_VT(&v1) == VT_I4, "node[%ld] Unexpected VT %d\n", idx, V_VT(&v1));
7050 ok(V_I4(&v1) == uia_i4_prop_val, "node[%ld] Unexpected I4 %#lx\n", idx, V_I4(&v1));
7051
7052 ok(UiaNodeRelease(tmp_node), "Failed to release node[%ld]\n", idx);
7053 VariantClear(&v1);
7054 }
7055 }
7056
7057 VariantClear(v);
7058 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7059 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
7061 break;
7062
7063 default:
7064 break;
7065 }
7066
7067 VariantClear(v);
7068 V_VT(v) = VT_EMPTY;
7069}
7070
7073 enum UIAutomationType type;
7075};
7076
7078 { &ProcessId_Property_GUID, UIAutomationType_Int, TRUE },
7079 { &ControlType_Property_GUID, UIAutomationType_Int },
7080 { &LocalizedControlType_Property_GUID, UIAutomationType_String, TRUE },
7081 { &Name_Property_GUID, UIAutomationType_String },
7082 { &AcceleratorKey_Property_GUID, UIAutomationType_String },
7083 { &AccessKey_Property_GUID, UIAutomationType_String },
7084 { &HasKeyboardFocus_Property_GUID, UIAutomationType_Bool },
7085 { &IsKeyboardFocusable_Property_GUID, UIAutomationType_Bool },
7086 { &IsEnabled_Property_GUID, UIAutomationType_Bool },
7087 { &AutomationId_Property_GUID, UIAutomationType_String },
7088 { &ClassName_Property_GUID, UIAutomationType_String },
7089 { &HelpText_Property_GUID, UIAutomationType_String },
7090 { &Culture_Property_GUID, UIAutomationType_Int },
7091 { &IsControlElement_Property_GUID, UIAutomationType_Bool },
7092 { &IsContentElement_Property_GUID, UIAutomationType_Bool },
7093 { &LabeledBy_Property_GUID, UIAutomationType_Element },
7094 { &IsPassword_Property_GUID, UIAutomationType_Bool },
7095 { &NewNativeWindowHandle_Property_GUID, UIAutomationType_Int },
7096 { &ItemType_Property_GUID, UIAutomationType_String },
7097 { &IsOffscreen_Property_GUID, UIAutomationType_Bool },
7098 { &Orientation_Property_GUID, UIAutomationType_Int },
7099 { &FrameworkId_Property_GUID, UIAutomationType_String },
7100 { &IsRequiredForForm_Property_GUID, UIAutomationType_Bool },
7101 { &ItemStatus_Property_GUID, UIAutomationType_String },
7102 { &AriaRole_Property_GUID, UIAutomationType_String },
7103 { &AriaProperties_Property_GUID, UIAutomationType_String },
7104 { &IsDataValidForForm_Property_GUID, UIAutomationType_Bool },
7105 { &ControllerFor_Property_GUID, UIAutomationType_ElementArray },
7106 { &DescribedBy_Property_GUID, UIAutomationType_ElementArray },
7107 { &FlowsTo_Property_GUID, UIAutomationType_ElementArray },
7108 /* Implemented on Win8+ */
7109 { &OptimizeForVisualContent_Property_GUID, UIAutomationType_Bool },
7110 { &LiveSetting_Property_GUID, UIAutomationType_Int },
7111 { &FlowsFrom_Property_GUID, UIAutomationType_ElementArray },
7112 { &IsPeripheral_Property_GUID, UIAutomationType_Bool },
7113 /* Implemented on Win10v1507+. */
7114 { &PositionInSet_Property_GUID, UIAutomationType_Int },
7115 { &SizeOfSet_Property_GUID, UIAutomationType_Int },
7116 { &Level_Property_GUID, UIAutomationType_Int },
7117 { &AnnotationTypes_Property_GUID, UIAutomationType_IntArray },
7118 { &AnnotationObjects_Property_GUID, UIAutomationType_ElementArray },
7119 /* Implemented on Win10v1809+. */
7120 { &LandmarkType_Property_GUID, UIAutomationType_Int },
7121 { &LocalizedLandmarkType_Property_GUID, UIAutomationType_String, TRUE },
7122 { &FullDescription_Property_GUID, UIAutomationType_String },
7123 { &FillColor_Property_GUID, UIAutomationType_Int },
7124 { &OutlineColor_Property_GUID, UIAutomationType_IntArray },
7125 { &FillType_Property_GUID, UIAutomationType_Int },
7126 { &VisualEffects_Property_GUID, UIAutomationType_Int },
7127 { &OutlineThickness_Property_GUID, UIAutomationType_DoubleArray },
7128 { &Rotation_Property_GUID, UIAutomationType_Double },
7129 { &Size_Property_GUID, UIAutomationType_DoubleArray },
7130 { &HeadingLevel_Property_GUID, UIAutomationType_Int },
7131 { &IsDialog_Property_GUID, UIAutomationType_Bool },
7132};
7133
7135{
7136 const struct uia_element_property *elem_prop;
7137 struct UiaRect rect;
7138 IUnknown *unk_ns;
7139 unsigned int i;
7140 HUIANODE node;
7141 int prop_id;
7142 HRESULT hr;
7143 VARIANT v;
7144
7146
7150 node = (void *)0xdeadbeef;
7152 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7153 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7155
7157 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7158
7159 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
7160 {
7161 elem_prop = &element_properties[i];
7162
7164 VariantClear(&v);
7166 if (!prop_id)
7167 {
7168 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
7169 break;
7170 }
7171 winetest_push_context("prop_id %d", prop_id);
7172 hr = UiaGetPropertyValue(node, prop_id, &v);
7173 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7174 check_uia_prop_val(prop_id, elem_prop->type, &v, FALSE);
7175
7176 /*
7177 * Some properties have special behavior if an invalid value is
7178 * returned, skip them here.
7179 */
7180 if (!elem_prop->skip_invalid)
7181 {
7183 hr = UiaGetPropertyValue(node, prop_id, &v);
7184 if (hr == E_NOTIMPL)
7185 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7186 else
7187 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7188 if (SUCCEEDED(hr))
7189 {
7191 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7192 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7193 VariantClear(&v);
7194 }
7195 }
7196
7198 }
7199
7200 /* IValueProvider pattern property IDs. */
7201 Provider.value_pattern_data.is_supported = FALSE;
7202 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
7203 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7204 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7205 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7207 VariantClear(&v);
7208
7209 Provider.value_pattern_data.is_supported = TRUE;
7210 for (i = 0; i < 2; i++)
7211 {
7212 Provider.value_pattern_data.is_read_only = i;
7213
7214 hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
7215 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7216 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
7217 ok(check_variant_bool(&v, i), "Unexpected BOOL %#x\n", V_BOOL(&v));
7219 VariantClear(&v);
7220 }
7221
7222 /* ILegacyIAccessibleProvider pattern property IDs. */
7223 Provider.legacy_acc_pattern_data.is_supported = FALSE;
7224 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v);
7225 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7226 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7227 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7229 VariantClear(&v);
7230
7231 Provider.legacy_acc_pattern_data.is_supported = TRUE;
7232 for (i = 0; i < 2; i++)
7233 {
7235
7236 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleChildIdPropertyId, &v);
7237 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7238 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7239 ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v));
7241 VariantClear(&v);
7242 }
7243
7244 for (i = 0; i < 2; i++)
7245 {
7247
7248 hr = UiaGetPropertyValue(node, UIA_LegacyIAccessibleRolePropertyId, &v);
7249 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7250 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
7251 ok(V_I4(&v) == i, "Unexpected I4 %#lx\n", V_I4(&v));
7253 VariantClear(&v);
7254 }
7255
7256 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7257 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
7259
7260 /*
7261 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
7262 * It's the only version with this behavior.
7263 */
7264 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
7265 {
7266 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
7267 goto exit;
7268 }
7269
7271 node = (void *)0xdeadbeef;
7272 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
7273 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7274 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7275
7276 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
7277 set_uia_rect(&rect, 0, 0, 50, 50);
7278 Provider_child.bounds_rect = rect;
7279 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
7280 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7282 VariantClear(&v);
7283
7284 ok_method_sequence(get_bounding_rect_seq, "get_bounding_rect_seq");
7285
7286 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
7287 set_uia_rect(&rect, 0, 0, 0, 0);
7288 Provider_child.bounds_rect = rect;
7289 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
7290 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7291 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7292 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7293 VariantClear(&v);
7294 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
7295
7296 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
7297 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
7299
7300exit:
7301
7302 IUnknown_Release(unk_ns);
7304}
7305
7306static const struct prov_method_sequence get_runtime_id1[] = {
7308 { 0 }
7309};
7310
7311static const struct prov_method_sequence get_runtime_id2[] = {
7314 { 0 }
7315};
7316
7317static const struct prov_method_sequence get_runtime_id3[] = {
7321 /* Not called on Windows 7. */
7322 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7323 /* Only called on Win8+. */
7326 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7328 { 0 }
7329};
7330
7331static const struct prov_method_sequence get_runtime_id4[] = {
7335 /* Not called on Windows 7. */
7336 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7337 /* These methods are only called on Win8+. */
7341 { 0 }
7342};
7343
7344static const struct prov_method_sequence get_runtime_id5[] = {
7349 { 0 }
7350};
7351
7352static void test_UiaGetRuntimeId(void)
7353{
7356 int rt_id[4], tmp, i;
7357 IUnknown *unk_ns;
7358 SAFEARRAY *sa;
7359 WNDCLASSA cls;
7360 HUIANODE node;
7361 HRESULT hr;
7362 HWND hwnd;
7363 VARIANT v;
7364
7365 VariantInit(&v);
7366 cls.style = 0;
7368 cls.cbClsExtra = 0;
7369 cls.cbWndExtra = 0;
7371 cls.hIcon = 0;
7372 cls.hCursor = NULL;
7373 cls.hbrBackground = NULL;
7374 cls.lpszMenuName = NULL;
7375 cls.lpszClassName = "UiaGetRuntimeId class";
7376
7377 RegisterClassA(&cls);
7378
7379 hwnd = CreateWindowA("UiaGetRuntimeId class", "Test window", WS_OVERLAPPEDWINDOW,
7380 0, 0, 100, 100, NULL, NULL, NULL, NULL);
7381
7383 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7384
7387 Provider.hwnd = Provider2.hwnd = Provider_child.hwnd = NULL;
7388 node = (void *)0xdeadbeef;
7389 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
7390 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7391 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7392
7393 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7394 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7396 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
7397 VariantClear(&v);
7398
7400
7401 /* NULL runtime ID. */
7402 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0;
7403 sa = (void *)0xdeadbeef;
7405 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7406 ok(!sa, "sa != NULL\n");
7407 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
7408
7409 /* No UiaAppendRuntimeId prefix, returns GetRuntimeId array directly. */
7410 Provider_child.runtime_id[0] = rt_id[0] = 5;
7411 Provider_child.runtime_id[1] = rt_id[1] = 2;
7412 sa = (void *)0xdeadbeef;
7414 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7415 ok(!!sa, "sa == NULL\n");
7416 check_runtime_id(rt_id, 2, sa);
7418 ok_method_sequence(get_runtime_id1, "get_runtime_id1");
7419
7420 /*
7421 * If a provider returns a RuntimeId beginning with the constant
7422 * UiaAppendRuntimeId, UI Automation will add a prefix based on the
7423 * providers HWND fragment root before returning to the client. The added
7424 * prefix is 3 int values, with:
7425 *
7426 * idx[0] always being 42. (UIA_RUNTIME_ID_PREFIX)
7427 * idx[1] always being the HWND.
7428 * idx[2] has three different values depending on what type of provider
7429 * the fragment root is. Fragment roots can be an override provider, a
7430 * nonclient provider, or a main provider.
7431 */
7432 Provider_child.frag_root = NULL;
7433 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7434 Provider_child.runtime_id[1] = 2;
7435 sa = (void *)0xdeadbeef;
7436
7437 /* Provider_child has no fragment root for UiaAppendRuntimeId. */
7439 /* Windows 7 returns S_OK. */
7440 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
7441 ok(!sa, "sa != NULL\n");
7442 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
7443
7444 /*
7445 * UIA_RuntimeIdPropertyId won't return a failure code from
7446 * UiaGetPropertyValue.
7447 */
7448 hr = UiaGetPropertyValue(node, UIA_RuntimeIdPropertyId, &v);
7449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7450 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
7451 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
7452 VariantClear(&v);
7453 ok_method_sequence(get_runtime_id2, "get_runtime_id2");
7454
7455 /*
7456 * Provider_child returns a fragment root that doesn't expose an HWND. On
7457 * Win8+, fragment roots are navigated recursively until either a NULL
7458 * fragment root is returned, the same fragment root as the current one is
7459 * returned, or a fragment root with an HWND is returned.
7460 */
7463 Provider2.hwnd = NULL;
7464 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
7465 Provider.hwnd = NULL;
7466 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7467 Provider_child.runtime_id[1] = 2;
7468 sa = (void *)0xdeadbeef;
7470 /* Windows 7 returns S_OK. */
7471 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
7472 ok(!sa, "sa != NULL\n");
7473 ok_method_sequence(get_runtime_id3, "get_runtime_id3");
7474
7475 /* Provider2 returns an HWND. */
7476 Provider.hwnd = NULL;
7477 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
7478 Provider2.hwnd = hwnd;
7480 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7481 Provider_child.runtime_id[1] = rt_id[3] = 2;
7482 sa = NULL;
7484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7485 /* Windows 7 returns a NULL RuntimeId due to no fragment recursion. */
7486 ok(!!sa || broken(!sa), "sa == NULL\n");
7488
7489 ok_method_sequence(get_runtime_id4, "get_runtime_id4");
7490
7491 /* Test RuntimeId values for different root fragment provider types. */
7493 Provider.hwnd = hwnd;
7494 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7495 Provider_child.runtime_id[1] = rt_id[3] = 2;
7496 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
7497 rt_id[1] = HandleToULong(hwnd);
7498 for (i = 0; i < ARRAY_SIZE(root_prov_opts); i++)
7499 {
7500 LONG lbound;
7501
7502 Provider.prov_opts = root_prov_opts[i];
7503 sa = NULL;
7505 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7506 ok(!!sa, "sa == NULL\n");
7507
7508 hr = SafeArrayGetLBound(sa, 1, &lbound);
7509 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
7510
7511 lbound = lbound + 2;
7512 hr = SafeArrayGetElement(sa, &lbound, &tmp);
7513 ok(hr == S_OK, "Failed to get element with hr %#lx\n", hr);
7514 if (i)
7515 ok(rt_id[2] != tmp, "Expected different runtime id value from previous\n");
7516
7517 rt_id[2] = tmp;
7518 check_runtime_id(rt_id, 4, sa);
7519
7521 ok_method_sequence(get_runtime_id5, "get_runtime_id5");
7522 }
7523
7525
7526 /* Test behavior on a node with an associated HWND. */
7529 Provider.hwnd = Provider2.hwnd = hwnd;
7530 prov_root = &Provider2.IRawElementProviderSimple_iface;
7531 node = (void *)0xdeadbeef;
7532 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
7533 /* Windows 7 sends this. */
7534 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7536 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7537 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7538 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7539
7540 VariantInit(&v);
7541 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7542 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7544 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider2", TRUE);
7546 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
7547 VariantClear(&v);
7548
7549 ok_method_sequence(node_from_prov6, "node_from_prov6");
7550
7551 /* No methods called, RuntimeId is based on the node's HWND. */
7553 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7554 ok(!!sa, "sa == NULL\n");
7555 ok(!sequence_cnt, "Unexpected sequence_cnt %d\n", sequence_cnt);
7556
7557 rt_id[0] = UIA_RUNTIME_ID_PREFIX;
7558 rt_id[1] = HandleToULong(hwnd);
7559 check_runtime_id(rt_id, 2, sa);
7562
7564 UnregisterClassA("UiaGetRuntimeId class", NULL);
7566}
7567
7570 { 0 },
7571};
7572
7574{
7575 HUIANODE node, node2;
7576 ULONG node_ref;
7577 HRESULT hr;
7578 VARIANT v;
7579
7581 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7582
7584 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7585
7586 node = (void *)0xdeadbeef;
7587 V_VT(&v) = VT_R8;
7589 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7590 ok(!node, "node != NULL\n");
7591
7592 node = NULL;
7595 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7596 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
7597 ok(!!node, "node == NULL\n");
7598 ok_method_sequence(node_from_var_seq, "node_from_var_seq");
7599
7600 node2 = (void *)0xdeadbeef;
7601 V_VT(&v) = VT_UNKNOWN;
7602 V_UNKNOWN(&v) = (IUnknown *)node;
7603 hr = UiaHUiaNodeFromVariant(&v, &node2);
7604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7605 ok(node == node2, "node != NULL\n");
7606
7607 node_ref = IUnknown_AddRef((IUnknown *)node);
7608 ok(node_ref == 3, "Unexpected node_ref %ld\n", node_ref);
7609 VariantClear(&v);
7610 IUnknown_Release((IUnknown *)node);
7611
7612#ifdef _WIN64
7613 node2 = (void *)0xdeadbeef;
7614 V_VT(&v) = VT_I4;
7615 V_I4(&v) = 0xbeefdead;
7616 hr = UiaHUiaNodeFromVariant(&v, &node2);
7617 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7618 ok(!node2, "node2 != NULL\n");
7619
7620 node2 = (void *)0xdeadbeef;
7621 V_VT(&v) = VT_I8;
7622 V_I8(&v) = (UINT64)node;
7623 hr = UiaHUiaNodeFromVariant(&v, &node2);
7624 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7625 ok(node2 == (void *)V_I8(&v), "node2 != V_I8\n");
7626#else
7627 node2 = (void *)0xdeadbeef;
7628 V_VT(&v) = VT_I8;
7629 V_I8(&v) = 0xbeefdead;
7630 hr = UiaHUiaNodeFromVariant(&v, &node2);
7631 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
7632 ok(!node2, "node2 != NULL\n");
7633
7634 node2 = (void *)0xdeadbeef;
7635 V_VT(&v) = VT_I4;
7636 V_I4(&v) = (UINT32)node;
7637 hr = UiaHUiaNodeFromVariant(&v, &node2);
7638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7639 ok(node2 == (void *)V_I4(&v), "node2 != V_I4\n");
7640#endif
7641
7643}
7644
7645static const struct prov_method_sequence node_from_hwnd1[] = {
7647 { 0 }
7648};
7649
7650static const struct prov_method_sequence node_from_hwnd2[] = {
7652 /* Win10v1507 and below call this. */
7653 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7655 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7658 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7659 /* Windows 10+ calls this. */
7661 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7662 { 0 }
7663};
7664
7665static const struct prov_method_sequence node_from_hwnd3[] = {
7668 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7669 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
7673 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7674 { 0 }
7675};
7676
7677static const struct prov_method_sequence node_from_hwnd4[] = {
7680 /* Win10v1507 and below call this. */
7681 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7683 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7684 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7685 /* Only called on Windows versions past Win10v1507. */
7687 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7688 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7689 { 0 }
7690};
7691
7692static const struct prov_method_sequence node_from_hwnd5[] = {
7693 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
7695 /* Win10v1507 and below call this. */
7696 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7698 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7699 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7701 /* Only done in Windows 8+. */
7704 /* These two are only done on Windows 7. */
7706 { &Provider_child, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7707 { 0 }
7708};
7709
7710static const struct prov_method_sequence node_from_hwnd6[] = {
7713 /* Win10v1507 and below call this. */
7714 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7716 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7717 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7719 /* Next 4 are only done in Windows 8+. */
7725 /* Next two are only done on Win10v1809+. */
7728 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7729 /* Next two are only done on Win10v1809+. */
7732 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7733 { 0 }
7734};
7735
7736static const struct prov_method_sequence node_from_hwnd7[] = {
7739 /* Win10v1507 and below call this. */
7740 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7742 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7746 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7748 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7751 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7752 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7753 { 0 }
7754};
7755
7756static const struct prov_method_sequence node_from_hwnd8[] = {
7759 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win11+ */
7760 /* Windows 11 sends WM_GETOBJECT twice on nested nodes. */
7764 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
7765 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
7766 { 0 }
7767};
7768
7769static const struct prov_method_sequence node_from_hwnd9[] = {
7771 /* Win10v1507 and below call this. */
7772 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7774 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7775 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7777 /* Only done in Windows 8+. */
7780 /* These three are only done on Windows 7. */
7782 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
7783 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
7784 { 0 }
7785};
7786
7789 /* Next two only done on Windows 8+. */
7793 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win11+. */
7794 { 0 }
7795};
7796
7799 /* Win10v1507 and below call this. */
7800 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7802 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7803 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7809 { 0 }
7810};
7811
7814 /* Win10v1507 and below call this. */
7815 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7817 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7818 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7822 { 0 }
7823};
7824
7827 /* Win10v1507 and below call this. */
7828 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7830 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
7831 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7834 { 0 }
7835};
7836
7839 /* Win10v1507 and below call this. */
7840 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
7842 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
7844 { 0 }
7845};
7846
7848{
7849 APTTYPEQUALIFIER apt_qualifier;
7850 APTTYPE apt_type;
7851 WCHAR buf[2048];
7852 HUIANODE node;
7853 HRESULT hr;
7854 DWORD pid;
7855 HWND hwnd;
7856 VARIANT v;
7857
7858 hwnd = FindWindowA("UiaNodeFromHandle class", "Test window");
7859
7860 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7861 ok(hr == CO_E_NOTINITIALIZED, "Unexpected hr %#lx\n", hr);
7862
7864 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7865
7866 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7867 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7868
7869 memset(buf, 0, sizeof(buf));
7871 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7873 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7877
7878 VariantClear(&v);
7879
7880 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7881 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7882 ok(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
7883 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
7884
7885 /*
7886 * On Windows 8 and above, if a node contains a nested provider, the
7887 * process will be in an implicit MTA until the node is released.
7888 */
7889 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7890 ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
7891 if (SUCCEEDED(hr))
7892 {
7893 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7894 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7895 }
7896
7898
7899 /* Node released, we're out of the implicit MTA. */
7900 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
7901
7902 /* Windows 10v1709-1809 are stuck in an implicit MTA. */
7903 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
7904 if (SUCCEEDED(hr))
7905 {
7906 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
7907 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
7908 }
7909}
7910
7912{
7913 HUIANODE node, node2, node3;
7914 HWND hwnd = (HWND)param;
7915 WCHAR buf[2048];
7916 HRESULT hr;
7917 VARIANT v;
7918
7920
7921 /* Only sent twice on Windows 11. */
7922 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
7923 /* Only sent on Win7. */
7924 SET_EXPECT(winproc_GETOBJECT_CLIENT);
7927 Provider.hwnd = hwnd;
7933 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
7934 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
7935 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
7936 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
7937
7938 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
7939 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7940
7941 memset(buf, 0, sizeof(buf));
7942 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
7944 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
7948
7949 VariantClear(&v);
7950
7952 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
7953
7954 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
7955 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7956 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
7957
7958 /*
7959 * On Windows, nested providers are always called on a separate thread if
7960 * UseComThreading isn't set. Since we're doing COM marshaling, if we're
7961 * currently in an MTA, we just call the nested provider from the current
7962 * thread.
7963 */
7965 Provider.last_call_tid != GetWindowThreadProcessId(hwnd, NULL), "Expected method call on separate thread\n");
7966
7967 /*
7968 * Elements returned from nested providers have to be able to get a
7969 * RuntimeId, or else we'll get E_FAIL on Win8+.
7970 */
7972 Provider_child.expected_tid = Provider.expected_tid;
7973 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
7974 Provider_child.runtime_id[1] = 2;
7975 Provider_child.frag_root = NULL;
7976 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7977 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx\n", hr);
7978 if (SUCCEEDED(hr))
7979 {
7980 hr = UiaHUiaNodeFromVariant(&v, &node2);
7981 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7982 UiaNodeRelease(node2);
7983 }
7984
7985 ok_method_sequence(node_from_hwnd5, "node_from_hwnd5");
7986
7987 /* RuntimeId check succeeds, we'll get a nested node. */
7989 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
7990 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7991 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
7992
7993 hr = UiaHUiaNodeFromVariant(&v, &node2);
7994 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7995 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
7996 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
7997
7998 /*
7999 * Even though this is a nested node, without any additional
8000 * providers, it will not have the 'Nested' prefix.
8001 */
8003 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8004 VariantClear(&v);
8005
8006 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8007 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8008 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8009 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8010 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
8011
8012 UiaNodeRelease(node2);
8013
8014 /*
8015 * There is a delay between nested nodes being released and the
8016 * corresponding IRawElementProviderSimple release on newer Windows
8017 * versions.
8018 */
8019 if (Provider_child.ref != 1)
8020 Sleep(50);
8021 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8022
8023 /*
8024 * Returned nested elements with an HWND will have client-side providers
8025 * added to them.
8026 */
8027 Provider_child.hwnd = hwnd;
8028 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8029 /* Only sent on Win7. */
8030 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8031 Provider_child.ignore_hwnd_prop = TRUE;
8032 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8033 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8034 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8035 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8036 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
8037
8038 hr = UiaHUiaNodeFromVariant(&v, &node2);
8039 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8040 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
8041 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8042
8043 memset(buf, 0, sizeof(buf));
8044 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", TRUE, buf), "Failed to get nested provider description\n");
8045
8047 check_node_provider_desc(buf, L"Main", L"Provider_child", TRUE);
8048
8052 VariantClear(&v);
8053
8054 Provider_child.ignore_hwnd_prop = FALSE;
8055 ok_method_sequence(node_from_hwnd7, "node_from_hwnd7");
8056 UiaNodeRelease(node2);
8057
8058 if (Provider_child.ref != 1)
8059 Sleep(50);
8060 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8061
8062 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8063 /* Win10v1809 can be slow to call Release on Provider. */
8064 if (Provider.ref != 1)
8065 Sleep(50);
8066 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8067
8068 /* ProviderOptions_UseComThreading test from a separate thread. */
8069 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8070 /* Only sent on Win7. */
8071 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8075 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
8077 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8078 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8079 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8080 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8081
8082 ok_method_sequence(node_from_hwnd10, "node_from_hwnd10");
8083
8084 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8085 /* Win10v1809 can be slow to call Release on Provider. */
8086 if (Provider.ref != 1)
8087 Sleep(50);
8088 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8089
8090 if (!pUiaDisconnectProvider)
8091 {
8092 win_skip("UiaDisconnectProvider not exported by uiautomationcore.dll\n");
8093 goto exit;
8094 }
8095
8096 /*
8097 * UiaDisconnectProvider tests.
8098 */
8099 /* Only sent twice on Windows 11. */
8100 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
8103 Provider.hwnd = hwnd;
8109 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8110 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
8111 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8112
8113 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8114 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8115
8116 memset(buf, 0, sizeof(buf));
8117 ok(get_nested_provider_desc(V_BSTR(&v), L"Main", FALSE, buf), "Failed to get nested provider description\n");
8119 check_node_provider_desc(buf, L"Main", L"Provider", TRUE);
8123 VariantClear(&v);
8124
8126 ok_method_sequence(node_from_hwnd3, "node_from_hwnd3");
8127
8128 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8129 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8130 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
8131
8132 /* Nodes returned from a nested node will be tracked and disconnectable. */
8134 Provider_child.runtime_id[0] = UiaAppendRuntimeId;
8135 Provider_child.runtime_id[1] = 2;
8136 Provider_child.hwnd = NULL;
8138 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8139 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8140 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
8141
8142 hr = UiaHUiaNodeFromVariant(&v, &node2);
8143 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8144 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
8145 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8147 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8148 VariantClear(&v);
8149
8150 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8151 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8152 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8153 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8154 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
8155
8156 /* Get a new node for the same provider. */
8157 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8158 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8159 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
8160
8161 hr = UiaHUiaNodeFromVariant(&v, &node3);
8162 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8163 hr = UiaGetPropertyValue(node3, UIA_ProviderDescriptionPropertyId, &v);
8164 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8166 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8167 VariantClear(&v);
8168
8169 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
8170 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8171 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8172 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8173 ok_method_sequence(node_from_hwnd6, "node_from_hwnd6");
8174
8175 /*
8176 * Both node2 and node3 represent Provider_child, one call to
8177 * UiaDisconnectProvider disconnects both.
8178 */
8179 hr = pUiaDisconnectProvider(&Provider_child.IRawElementProviderSimple_iface);
8180 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8181 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
8182
8183 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8184 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
8185
8186 hr = UiaGetPropertyValue(node3, UIA_ControlTypePropertyId, &v);
8187 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
8188 ok_method_sequence(disconnect_prov1, "disconnect_prov1");
8189
8190 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8191 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
8192
8193 /*
8194 * Returns same failure code as UiaGetRuntimeId when we fail to get a
8195 * fragment root for AppendRuntimeId.
8196 */
8197 Provider.hwnd = NULL;
8199 Provider.runtime_id[1] = 2;
8201 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8202 ok(hr == E_FAIL, "Unexpected hr %#lx\n", hr);
8203 ok_method_sequence(disconnect_prov2, "disconnect_prov2");
8204
8205 /*
8206 * Comparisons for disconnection are only based on RuntimeId comparisons,
8207 * not interface pointer values. If an interface returns a NULL RuntimeId,
8208 * no disconnection will occur.
8209 */
8211 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8212 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
8213 ok_method_sequence(disconnect_prov3, "disconnect_prov3");
8214
8215 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8216 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8217 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
8218
8219 /* Finally, disconnect node. */
8220 Provider.hwnd = hwnd;
8221 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8222 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8223
8224 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8225 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx\n", hr);
8226 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8227 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
8228
8229exit:
8231
8232 return 0;
8233}
8234
8235static void test_UiaNodeFromHandle(const char *name)
8236{
8237 APTTYPEQUALIFIER apt_qualifier;
8239 char cmdline[MAX_PATH];
8241 HUIANODE node, node2;
8242 APTTYPE apt_type;
8244 WNDCLASSA cls;
8245 HANDLE thread;
8246 HRESULT hr;
8247 HWND hwnd;
8248 VARIANT v;
8249
8250 cls.style = 0;
8252 cls.cbClsExtra = 0;
8253 cls.cbWndExtra = 0;
8255 cls.hIcon = 0;
8256 cls.hCursor = NULL;
8257 cls.hbrBackground = NULL;
8258 cls.lpszMenuName = NULL;
8259 cls.lpszClassName = "UiaNodeFromHandle class";
8260 RegisterClassA(&cls);
8261
8262 hwnd = CreateWindowA("UiaNodeFromHandle class", "Test window", WS_OVERLAPPEDWINDOW,
8263 0, 0, 100, 100, NULL, NULL, NULL, NULL);
8264
8266 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
8267
8269 ok(hr == UIA_E_ELEMENTNOTAVAILABLE, "Unexpected hr %#lx.\n", hr);
8270
8271 /* COM uninitialized, no provider returned by UiaReturnRawElementProvider. */
8272 prov_root = NULL;
8273 node = (void *)0xdeadbeef;
8274 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8275 /* Only sent twice on Win7. */
8276 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8278 /*
8279 * On all versions of Windows prior to Windows 11, this would fail due to
8280 * COM being uninitialized, presumably because it tries to get an MSAA
8281 * proxy. Windows 11 now has the thread end up in an implicit MTA after
8282 * the call to UiaNodeFromHandle, which is probably why this now succeeds.
8283 * I don't know of anything that relies on this behavior, so for now we
8284 * won't match it.
8285 */
8286 todo_wine ok(hr == S_OK || broken(hr == E_FAIL), "Unexpected hr %#lx.\n", hr);
8287 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8288 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8289 if (SUCCEEDED(hr))
8291
8292 /*
8293 * COM initialized, no provider returned by UiaReturnRawElementProvider.
8294 * In this case, we get a default MSAA proxy.
8295 */
8297 prov_root = NULL;
8298 node = (void *)0xdeadbeef;
8299 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8300 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8302 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8303 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8304 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8305
8306 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8307 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8313 VariantClear(&v);
8314
8315 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8316
8317 /*
8318 * COM initialized, but provider passed into UiaReturnRawElementProvider
8319 * returns a failure code on get_ProviderOptions. Same behavior as before.
8320 */
8321 Provider.prov_opts = 0;
8322 Provider.hwnd = hwnd;
8324 node = (void *)0xdeadbeef;
8325 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8326 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8328 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8329 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8330 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8331
8332 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8333 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8339 VariantClear(&v);
8340
8341 ok_method_sequence(node_from_hwnd1, "node_from_hwnd1");
8342
8343 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8344
8345 /*
8346 * COM initialized, but provider passed into UiaReturnRawElementProvider
8347 * on Win8+ will have its RuntimeId queried for UiaDisconnectProvider.
8348 * It will fail due to the lack of a valid fragment root, and we'll fall
8349 * back to an MSAA proxy. On Win7, RuntimeId isn't queried because the
8350 * disconnection functions weren't implemented yet.
8351 */
8353 Provider.hwnd = NULL;
8355 node = (void *)0xdeadbeef;
8356 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8357 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
8360 Provider.runtime_id[1] = 1;
8362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8363 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
8364 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8365 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
8366
8367 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8368 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8369
8371 if (Provider.ref == 1 || get_provider_desc(V_BSTR(&v), L"Annotation:", NULL))
8372 {
8375 }
8376 else
8377 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
8378
8381 VariantClear(&v);
8382
8383 ok_method_sequence(node_from_hwnd9, "node_from_hwnd9");
8384 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8385 /*
8386 * Bug on Windows 8 through Win10v1709 - if we have a RuntimeId failure,
8387 * refcount doesn't get decremented.
8388 */
8389 ok(Provider.ref == 1 || broken(Provider.ref == 2), "Unexpected refcnt %ld\n", Provider.ref);
8390 if (Provider.ref == 2)
8391 IRawElementProviderSimple_Release(&Provider.IRawElementProviderSimple_iface);
8392
8394
8395 /*
8396 * COM uninitialized, return a Provider from UiaReturnRawElementProvider
8397 * with ProviderOptions_ServerSideProvider.
8398 */
8400 Provider.hwnd = hwnd;
8402 node = (void *)0xdeadbeef;
8403 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
8404 /* Only sent on Win7. */
8405 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8406 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
8408 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
8409 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
8410 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8411 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8412
8413 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
8414 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8416 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
8419 VariantClear(&v);
8420
8421 ok_method_sequence(node_from_hwnd2, "node_from_hwnd2");
8422
8423 /* For same-thread HWND nodes, no disconnection will occur. */
8424 if (pUiaDisconnectProvider)
8425 {
8426 hr = pUiaDisconnectProvider(&Provider.IRawElementProviderSimple_iface);
8427 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8428
8429 ok_method_sequence(disconnect_prov4, "disconnect_prov4");
8430 }
8431
8432 /*
8433 * This is relevant too: Since we don't get a 'nested' node, all calls
8434 * will occur on the current thread.
8435 */
8437 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
8438 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8439 check_uia_prop_val(UIA_ControlTypePropertyId, UIAutomationType_Int, &v, FALSE);
8440
8441 /* UIAutomationType_Element properties will return a normal node. */
8443 Provider_child.hwnd = NULL;
8444 hr = UiaGetPropertyValue(node, UIA_LabeledByPropertyId, &v);
8445 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8446
8447 hr = UiaHUiaNodeFromVariant(&v, &node2);
8448 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8449 hr = UiaGetPropertyValue(node2, UIA_ProviderDescriptionPropertyId, &v);
8450 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8452 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
8453 VariantClear(&v);
8454
8455 Provider_child.expected_tid = GetCurrentThreadId();
8456 hr = UiaGetPropertyValue(node2, UIA_ControlTypePropertyId, &v);
8457 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
8458 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
8459 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
8460 ok_method_sequence(node_from_hwnd4, "node_from_hwnd4");
8461
8462 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
8463
8464 Provider.expected_tid = Provider_child.expected_tid = 0;
8465 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
8466
8467 /*
8468 * On Windows 8 and above, after the first successful call to
8469 * UiaReturnRawElementProvider the process ends up in an implicit MTA
8470 * until the process exits.
8471 */
8472 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
8473 /* Wine's provider thread doesn't always terminate immediately. */
8474 if (hr == S_OK && !strcmp(winetest_platform, "wine"))
8475 {
8476 Sleep(10);
8477 hr = CoGetApartmentType(&apt_type, &apt_qualifier);
8478 }
8479 todo_wine ok(hr == S_OK || broken(hr == CO_E_NOTINITIALIZED), "Unexpected hr %#lx\n", hr);
8480 if (SUCCEEDED(hr))
8481 {
8482 ok(apt_type == APTTYPE_MTA, "Unexpected apt_type %#x\n", apt_type);
8483 ok(apt_qualifier == APTTYPEQUALIFIER_IMPLICIT_MTA, "Unexpected apt_qualifier %#x\n", apt_qualifier);
8484 }
8485
8489 {
8490 MSG msg;
8491 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
8492 {
8495 }
8496 }
8498
8499 /* Test behavior from separate process. */
8501 Provider.hwnd = hwnd;
8504 sprintf(cmdline, "\"%s\" uiautomation UiaNodeFromHandle_client_proc", name);
8505 memset(&startup, 0, sizeof(startup));
8506 startup.cb = sizeof(startup);
8507 /* Only called twice on Windows 11. */
8508 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
8509 /* Only sent on Win7. */
8510 SET_EXPECT(winproc_GETOBJECT_CLIENT);
8513 {
8514 MSG msg;
8515 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
8516 {
8519 }
8520 }
8521
8522 GetExitCodeProcess(proc.hProcess, &exit_code);
8523 if (exit_code > 255)
8524 ok(0, "unhandled exception %08x in child process %04x\n", (UINT)exit_code, (UINT)GetProcessId(proc.hProcess));
8525 else if (exit_code)
8526 ok(0, "%u failures in child process\n", (UINT)exit_code);
8527
8528 CloseHandle(proc.hProcess);
8529 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
8530 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
8532 ok_method_sequence(node_from_hwnd8, "node_from_hwnd8");
8533
8535
8537 UnregisterClassA("UiaNodeFromHandle class", NULL);
8538 prov_root = NULL;
8539}
8540
8541static const struct prov_method_sequence reg_prov_cb1[] = {
8542 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8543 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
8544 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8545 { 0 }
8546};
8547
8548static const struct prov_method_sequence reg_prov_cb2[] = {
8549 /* These two are only done on Win10v1809+. */
8551 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8552 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8553 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10+. */
8554 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8555 { 0 }
8556};
8557
8558static const struct prov_method_sequence reg_prov_cb3[] = {
8560 /* These two are only done on Win10v1809+. */
8562 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8563 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8564 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8565 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8566 /* These three only done on Win10+. */
8570 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8571 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8572 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8573 { 0 }
8574};
8575
8576static const struct prov_method_sequence reg_prov_cb4[] = {
8578 /* These two are only done on Win10v1809+. */
8580 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8581 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8582 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8583 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8584 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8585 /* These four only done on Win10+. */
8590 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
8591 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8592 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8593 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8594 { 0 }
8595};
8596
8597static const struct prov_method_sequence reg_prov_cb5[] = {
8598 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8599 { 0 }
8600};
8601
8602static const struct prov_method_sequence reg_prov_cb6[] = {
8603 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8604 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8605 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8606 { 0 }
8607};
8608
8609static const struct prov_method_sequence reg_prov_cb7[] = {
8610 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8611 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8612 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8613 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8614 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8615 { 0 }
8616};
8617
8618static const struct prov_method_sequence reg_prov_cb8[] = {
8619 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8620 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8621 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8622 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8623 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8624 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8625 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8626 { 0 }
8627};
8628
8629static const struct prov_method_sequence reg_prov_cb9[] = {
8630 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ControlTypePropertyId */
8631 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8632 { &Provider_proxy, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8633 { &Provider_proxy, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8634 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8635 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8636 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
8637 { &Provider_hwnd, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win7. */
8638 { 0 }
8639};
8640
8641static const struct prov_method_sequence reg_prov_cb10[] = {
8643 /* These two are only done on Win10v1809+. */
8645 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8646 { &Provider_override, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8647 { &Provider_proxy, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8648 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8649 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8650 /* These four only done on Win10+. */
8655 { 0 }
8656};
8657
8658static const struct prov_method_sequence reg_prov_cb11[] = {
8660 /* Win10v1507 and below call this. */
8661 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8663 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8667 /* These two are only done on Win10v1809+. */
8669 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8670 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8671 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8672 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8673 /* These three only done on Win10+. */
8677 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8678 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8679 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8680 { 0 }
8681};
8682
8683static const struct prov_method_sequence reg_prov_cb12[] = {
8685 /* Win10v1507 and below call this. */
8686 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8688 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8692 /* Win10v1507 and below call this. */
8693 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8695 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8697 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8699 /* These two are only done on Win10v1809+. */
8701 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8702 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8703 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8704 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8705 /* These three only done on Win10+. */
8709 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8710 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8711 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8712 { 0 }
8713};
8714
8715static const struct prov_method_sequence reg_prov_cb13[] = {
8717 /* Win10v1507 and below call this. */
8718 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8720 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8724 /* Win10v1507 and below call this. */
8725 { &Provider2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8727 { &Provider2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
8729 { &Provider2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8730 /* Provider override only retrieved successfully on Win10v1809+ */
8733 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8736 { &Provider_proxy2, HWND_OVERRIDE_GET_OVERRIDE_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1507 and below. */
8737 /* These two are only done on Win10v1809+. */
8739 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
8740 /* Only done on Win10v1809+. */
8741 { &Provider_override, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
8742 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8743 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8744 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
8745 { &Provider_override, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+ */
8746 /* These three only done on Win10+. */
8750 /* Only done on Win10v1809+. */
8751 { &Provider_override, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_ProviderDescriptionPropertyId */
8752 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8753 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8754 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
8755 { 0 }
8756};
8757
8758static SAFEARRAY *get_safearray_for_elprov(IRawElementProviderSimple *elprov)
8759{
8760 SAFEARRAY *sa = NULL;
8761 LONG idx = 0;
8762
8763 if (elprov)
8764 {
8766 if (sa)
8767 SafeArrayPutElement(sa, &idx, (void *)elprov);
8768 }
8769
8770 return sa;
8771}
8772
8773static IRawElementProviderSimple *base_hwnd_prov, *proxy_prov, *parent_proxy_prov, *nc_prov;
8774#ifdef __REACTOS__
8776#else
8778#endif
8779{
8780 IRawElementProviderSimple *elprov = NULL;
8781
8782 switch (prov_type)
8783 {
8785 CHECK_EXPECT(prov_callback_base_hwnd);
8786 if (hwnd == Provider_hwnd3.hwnd)
8787 elprov = &Provider_hwnd3.IRawElementProviderSimple_iface;
8788 else if (hwnd == Provider_hwnd2.hwnd)
8789 elprov = &Provider_hwnd2.IRawElementProviderSimple_iface;
8790 else
8791 elprov = base_hwnd_prov;
8792 break;
8793
8794 case ProviderType_Proxy:
8795 if (Provider_proxy.hwnd == hwnd)
8796 {
8797 CHECK_EXPECT(prov_callback_proxy);
8798 elprov = proxy_prov;
8799 }
8800 else if (hwnd == GetParent(Provider_proxy.hwnd))
8801 {
8802 CHECK_EXPECT(prov_callback_parent_proxy);
8803 elprov = parent_proxy_prov;
8804 }
8805 break;
8806
8808 CHECK_EXPECT(prov_callback_nonclient);
8809 if (hwnd == Provider_nc3.hwnd)
8810 elprov = &Provider_nc3.IRawElementProviderSimple_iface;
8811 else if (hwnd == Provider_nc2.hwnd)
8812 elprov = &Provider_nc2.IRawElementProviderSimple_iface;
8813 else
8814 elprov = nc_prov;
8815 break;
8816
8817 default:
8818 break;
8819 }
8820
8821 return get_safearray_for_elprov(elprov);
8822}
8823
8824/*
8825 * Windows 11 will infinitely loop if a clientside provider isn't returned for
8826 * an HWND in certain circumstances. In order to prevent this, we use these
8827 * temporary clientside providers.
8828 */
8830{
8831 IRawElementProviderSimple IRawElementProviderSimple_iface;
8833
8836};
8837
8838static inline struct ClientSideProvider *impl_from_ClientSideProvider(IRawElementProviderSimple *iface)
8839{
8841}
8842
8843static HRESULT WINAPI ClientSideProvider_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
8844{
8845 *ppv = NULL;
8846 if (IsEqualIID(riid, &IID_IRawElementProviderSimple) || IsEqualIID(riid, &IID_IUnknown))
8847 *ppv = iface;
8848 else
8849 return E_NOINTERFACE;
8850
8851 IRawElementProviderSimple_AddRef(iface);
8852 return S_OK;
8853}
8854
8855static ULONG WINAPI ClientSideProvider_AddRef(IRawElementProviderSimple *iface)
8856{
8858 return InterlockedIncrement(&This->ref);
8859}
8860
8861static ULONG WINAPI ClientSideProvider_Release(IRawElementProviderSimple *iface)
8862{
8865
8866 if (!ref)
8867 free(This);
8868
8869 return ref;
8870}
8871
8872static HRESULT WINAPI ClientSideProvider_get_ProviderOptions(IRawElementProviderSimple *iface,
8873 enum ProviderOptions *ret_val)
8874{
8876
8878 if (This->prov_type == ProviderType_NonClientArea)
8880
8881 return S_OK;
8882}
8883
8884static HRESULT WINAPI ClientSideProvider_GetPatternProvider(IRawElementProviderSimple *iface,
8885 PATTERNID pattern_id, IUnknown **ret_val)
8886{
8887 *ret_val = NULL;
8888 return S_OK;
8889}
8890
8891static HRESULT WINAPI ClientSideProvider_GetPropertyValue(IRawElementProviderSimple *iface, PROPERTYID prop_id,
8892 VARIANT *ret_val)
8893{
8895
8896 VariantInit(ret_val);
8897 switch (prop_id)
8898 {
8899 case UIA_NativeWindowHandlePropertyId:
8900 if (This->prov_type == ProviderType_BaseHwnd)
8901 {
8902 V_VT(ret_val) = VT_I4;
8903 V_I4(ret_val) = HandleToULong(This->hwnd);
8904 }
8905 break;
8906
8907 case UIA_ProviderDescriptionPropertyId:
8908 V_VT(ret_val) = VT_BSTR;
8909 V_BSTR(ret_val) = SysAllocString(L"ClientSideProvider");
8910 break;
8911
8912 default:
8913 break;
8914 }
8915
8916 return S_OK;
8917}
8918
8919static HRESULT WINAPI ClientSideProvider_get_HostRawElementProvider(IRawElementProviderSimple *iface,
8920 IRawElementProviderSimple **ret_val)
8921{
8923
8924 return UiaHostProviderFromHwnd(This->hwnd, ret_val);
8925}
8926
8927static IRawElementProviderSimpleVtbl ClientSideProviderVtbl = {
8935};
8936
8938{
8939 struct ClientSideProvider *prov = malloc(sizeof(*prov));
8940
8941 if (!prov)
8942 {
8943 trace("Failed to allocate memory for temporary clientside provider\n");
8944 return NULL;
8945 }
8946
8948 prov->ref = 1;
8949 prov->prov_type = prov_type;
8950 prov->hwnd = hwnd;
8951
8952 return &prov->IRawElementProviderSimple_iface;
8953}
8954
8957{
8960 0, 0, { (DWORD_PTR)(__FILE__ ": clientside_provider_callback_cs") }
8961};
8963static CONDITION_VARIABLE *clientside_provider_callback_cv;
8964
8965/*
8966 * Same deal as test_uia_provider_callback, except we only return a provider
8967 * if we can match one by HWND. This is necessary due to certain versions of
8968 * Windows 10 unpredictably attempting to create elements in the background.
8969 */
8970#ifdef __REACTOS__
8972#else
8974#endif
8975{
8976 IRawElementProviderSimple *elprov = NULL;
8977 SAFEARRAY *sa = NULL;
8978
8983 switch (prov_type)
8984 {
8986 if (hwnd == Provider_hwnd3.hwnd)
8987 elprov = &Provider_hwnd3.IRawElementProviderSimple_iface;
8988 else if (hwnd == Provider_hwnd2.hwnd)
8989 elprov = &Provider_hwnd2.IRawElementProviderSimple_iface;
8990 else if (hwnd == Provider_hwnd.hwnd)
8991 elprov = &Provider_hwnd.IRawElementProviderSimple_iface;
8992
8993 if (elprov)
8994 CHECK_EXPECT(prov_callback_base_hwnd);
8995 break;
8996
8997 case ProviderType_Proxy:
8998 if (Provider_proxy.hwnd == hwnd)
8999 elprov = proxy_prov;
9000 break;
9001
9003 if (hwnd == Provider_nc3.hwnd)
9004 elprov = &Provider_nc3.IRawElementProviderSimple_iface;
9005 else if (hwnd == Provider_nc2.hwnd)
9006 elprov = &Provider_nc2.IRawElementProviderSimple_iface;
9007 else if (hwnd == Provider_nc.hwnd)
9008 elprov = &Provider_nc.IRawElementProviderSimple_iface;
9009
9010 if (elprov)
9011 CHECK_EXPECT(prov_callback_nonclient);
9012 break;
9013
9014 default:
9015 break;
9016 }
9017
9018 if (!elprov)
9019 {
9021 return NULL;
9022 }
9023 else
9024 IRawElementProviderSimple_AddRef(elprov);
9025
9026 sa = get_safearray_for_elprov(elprov);
9027 IRawElementProviderSimple_Release(elprov);
9028 return sa;
9029}
9030
9031/*
9032 * Some versions of Windows 10 query multiple unrelated HWNDs when
9033 * winevents are fired, this function waits for these to stop before
9034 * continuing to the next test.
9035 */
9036#define TIME_SINCE_LAST_CALLBACK_TIMEOUT 200
9038{
9039 DWORD start_time = GetTickCount();
9040 CONDITION_VARIABLE cv;
9041 BOOL ret = FALSE;
9042
9046 while (1)
9047 {
9049
9050 if ((GetTickCount() - start_time) >= total_timeout)
9051 ret = TRUE;
9052 else if (!ret_val && (GetLastError() == ERROR_TIMEOUT))
9053 ret = FALSE;
9054 else if (!ret_val)
9055 trace("SleepConditionVariableCS failed, last err %ld\n", GetLastError());
9056 else
9057 continue;
9058
9059 break;
9060 }
9061
9064 return ret;
9065}
9066
9068{
9069 HWND hwnd, hwnd2;
9070 WNDCLASSA cls;
9071 HUIANODE node;
9072 HRESULT hr;
9073 VARIANT v;
9074
9075 cls.style = 0;
9077 cls.cbClsExtra = 0;
9078 cls.cbWndExtra = 0;
9080 cls.hIcon = 0;
9081 cls.hCursor = NULL;
9082 cls.hbrBackground = NULL;
9083 cls.lpszMenuName = NULL;
9084 cls.lpszClassName = "UiaRegisterProviderCallback class";
9085
9086 RegisterClassA(&cls);
9087
9089 cls.lpszClassName = "UiaRegisterProviderCallback child class";
9090 RegisterClassA(&cls);
9091
9092 hwnd = CreateWindowA("UiaRegisterProviderCallback class", "Test window", WS_OVERLAPPEDWINDOW,
9093 0, 0, 100, 100, NULL, NULL, NULL, NULL);
9094
9095 hwnd2 = CreateWindowA("UiaRegisterProviderCallback child class", "Test child window", WS_CHILD,
9096 0, 0, 100, 100, hwnd, NULL, NULL, NULL);
9097
9099
9100 /* No providers returned by UiaRootObjectId or the provider callback. */
9101 Provider_proxy.hwnd = hwnd2;
9103 node = (void *)0xdeadbeef;
9104 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9105 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9106 SET_EXPECT(prov_callback_base_hwnd);
9107 SET_EXPECT(prov_callback_nonclient);
9108 SET_EXPECT(prov_callback_proxy);
9109 SET_EXPECT(prov_callback_parent_proxy);
9110 hr = UiaNodeFromHandle(hwnd2, &node);
9111 /* Windows 7 returns S_OK with a NULL HUIANODE. */
9112 ok(hr == E_FAIL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
9113 ok(!node, "node != NULL\n");
9114 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9115 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9116 CHECK_CALLED(prov_callback_base_hwnd);
9117 CHECK_CALLED(prov_callback_nonclient);
9118 CHECK_CALLED(prov_callback_proxy);
9119 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9120
9121 /* Return only nonclient proxy provider. */
9123 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9125 node = (void *)0xdeadbeef;
9126 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9127 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9128 SET_EXPECT(prov_callback_base_hwnd);
9129 SET_EXPECT(prov_callback_nonclient);
9130 SET_EXPECT(prov_callback_proxy);
9131 SET_EXPECT(prov_callback_parent_proxy);
9132 hr = UiaNodeFromHandle(hwnd2, &node);
9133 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9134 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9135 ok(!!node, "node == NULL\n");
9136 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9137 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9138 CHECK_CALLED(prov_callback_base_hwnd);
9139 CHECK_CALLED(prov_callback_nonclient);
9140 CHECK_CALLED(prov_callback_proxy);
9141 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9142
9143 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9144 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9146 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
9147 VariantClear(&v);
9148
9149 ok_method_sequence(reg_prov_cb1, "reg_prov_cb1");
9150
9152 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
9153
9154 /* Return only base_hwnd provider. */
9156 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9158 node = (void *)0xdeadbeef;
9159 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9160 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9161 SET_EXPECT(prov_callback_base_hwnd);
9162 SET_EXPECT(prov_callback_nonclient);
9163 SET_EXPECT(prov_callback_proxy);
9164 SET_EXPECT(prov_callback_parent_proxy);
9165 hr = UiaNodeFromHandle(hwnd2, &node);
9166 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9167 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9168 ok(!!node, "node == NULL\n");
9169 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9170 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9171 CHECK_CALLED(prov_callback_base_hwnd);
9172 CHECK_CALLED(prov_callback_nonclient);
9173 CHECK_CALLED(prov_callback_proxy);
9174 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9175
9176 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9177 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9179 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", TRUE);
9180 VariantClear(&v);
9181
9182 ok_method_sequence(reg_prov_cb2, "reg_prov_cb2");
9183
9185 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9186
9187 /* Return providers for all ProviderTypes. */
9188 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9189 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
9190 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
9191 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9192 Provider_proxy.hwnd = hwnd2;
9194 node = (void *)0xdeadbeef;
9195 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9196 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9197 SET_EXPECT(prov_callback_base_hwnd);
9198 SET_EXPECT(prov_callback_nonclient);
9199 SET_EXPECT(prov_callback_proxy);
9200 SET_EXPECT(prov_callback_parent_proxy);
9201 hr = UiaNodeFromHandle(hwnd2, &node);
9202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9203 ok(!!node, "node == NULL\n");
9204 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9205 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
9206 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9207 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9208 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9209 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9210 CHECK_CALLED(prov_callback_base_hwnd);
9211 CHECK_CALLED(prov_callback_nonclient);
9212 CHECK_CALLED(prov_callback_proxy);
9213 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9214
9215 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9216 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9218 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
9219 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9220 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9221 VariantClear(&v);
9222
9223 ok_method_sequence(reg_prov_cb3, "reg_prov_cb3");
9224
9226 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9227 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
9228 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9229
9230 /* Return an override provider from Provider_proxy2. */
9231 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
9232 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
9233 parent_proxy_prov = &Provider_proxy2.IRawElementProviderSimple_iface;
9234 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
9235 Provider_proxy2.override_hwnd = hwnd2;
9237 node = (void *)0xdeadbeef;
9238 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9239 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9240 SET_EXPECT(prov_callback_base_hwnd);
9241 SET_EXPECT(prov_callback_nonclient);
9242 SET_EXPECT(prov_callback_proxy);
9243 SET_EXPECT(prov_callback_parent_proxy);
9244 hr = UiaNodeFromHandle(hwnd2, &node);
9245 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9246 ok(!!node, "node == NULL\n");
9247 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9248 ok(Provider_proxy2.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy2.ref);
9249 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
9250 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9251 todo_wine ok(Provider_override.ref == 2, "Unexpected refcnt %ld\n", Provider_override.ref);
9252 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9253 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9254 CHECK_CALLED(prov_callback_base_hwnd);
9255 CHECK_CALLED(prov_callback_nonclient);
9256 CHECK_CALLED(prov_callback_proxy);
9257 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9258
9259 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9260 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9262 check_node_provider_desc_todo(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
9263 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider_proxy", FALSE);
9264 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9265 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9266 VariantClear(&v);
9267
9268 ok_method_sequence(reg_prov_cb4, "reg_prov_cb4");
9269
9270 /*
9271 * Test the order that Providers are queried for properties. The order is:
9272 * Override provider.
9273 * Main provider.
9274 * Nonclient provider.
9275 * Hwnd provider.
9276 *
9277 * UI Automation tries to get a property from each in this order until one
9278 * returns a value. If none do, the property isn't supported.
9279 */
9280 if (Provider_override.ref == 2)
9281 {
9282 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9283 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9284 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9285 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9286 ok_method_sequence(reg_prov_cb5, "reg_prov_cb5");
9287 }
9288
9289 /* Property retrieved from Provider_proxy (Main) */
9290 Provider_override.ret_invalid_prop_type = TRUE;
9291 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9292 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9293 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9294 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9295 ok_method_sequence(reg_prov_cb6, "reg_prov_cb6");
9296
9297 /* Property retrieved from Provider_nc (Nonclient) */
9298 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
9299 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9300 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9301 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9302 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9303 ok_method_sequence(reg_prov_cb7, "reg_prov_cb7");
9304
9305 /* Property retrieved from Provider_hwnd (Hwnd) */
9306 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
9307 Provider_nc.ret_invalid_prop_type = TRUE;
9308 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9309 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9310 ok(V_VT(&v) == VT_I4, "Unexpected vt %d\n", V_VT(&v));
9311 ok(V_I4(&v) == uia_i4_prop_val, "Unexpected I4 %#lx\n", V_I4(&v));
9312 ok_method_sequence(reg_prov_cb8, "reg_prov_cb8");
9313
9314 /* Property retrieved from none of the providers. */
9315 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = TRUE;
9316 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = TRUE;
9317 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
9318 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9319 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
9320 ok_method_sequence(reg_prov_cb9, "reg_prov_cb9");
9321
9323 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
9324 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
9325 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
9326 ok(Provider_override.ref == 1, "Unexpected refcnt %ld\n", Provider_override.ref);
9327 Provider_override.ret_invalid_prop_type = Provider_proxy.ret_invalid_prop_type = FALSE;
9328 Provider_nc.ret_invalid_prop_type = Provider_hwnd.ret_invalid_prop_type = FALSE;
9329
9330 /*
9331 * Provider_hwnd has ProviderOptions_UseComThreading, and COM hasn't been
9332 * initialized. One provider failing will cause the entire node to fail
9333 * creation on Win10+.
9334 */
9336 node = (void *)0xdeadbeef;
9337 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9338 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9339 SET_EXPECT(prov_callback_base_hwnd);
9340 SET_EXPECT(prov_callback_nonclient);
9341 SET_EXPECT(prov_callback_proxy);
9342 SET_EXPECT(prov_callback_parent_proxy);
9343 hr = UiaNodeFromHandle(hwnd2, &node);
9344 ok(hr == CO_E_NOTINITIALIZED || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
9345 ok(!node || broken(!!node), "node != NULL\n");
9346 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9347 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9348 CHECK_CALLED(prov_callback_base_hwnd);
9349 CHECK_CALLED(prov_callback_nonclient);
9350 CHECK_CALLED(prov_callback_proxy);
9351 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9352 ok_method_sequence(reg_prov_cb10, "reg_prov_cb10");
9355
9356 /*
9357 * Provider returned by UiaRootObjectId on hwnd2. No ProviderType_Proxy
9358 * callback for hwnd2.
9359 */
9360 Provider.hwnd = hwnd2;
9363 Provider_proxy2.override_hwnd = NULL;
9364 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9365 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9366 SET_EXPECT(prov_callback_base_hwnd);
9367 SET_EXPECT(prov_callback_nonclient);
9368 SET_EXPECT(prov_callback_parent_proxy);
9369 hr = UiaNodeFromHandle(hwnd2, &node);
9370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9371 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9372 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9373 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9374 CHECK_CALLED(prov_callback_base_hwnd);
9375 CHECK_CALLED(prov_callback_nonclient);
9376 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9377
9378 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9379 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9381 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9382 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9383 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9384 VariantClear(&v);
9385
9386 ok_method_sequence(reg_prov_cb11, "reg_prov_cb11");
9387
9389
9390 /*
9391 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
9392 * doesn't give an HWND override provider, UIA will attempt to get a proxy
9393 * provider to check it for an HWND override provider.
9394 */
9395 Provider.hwnd = hwnd2;
9396 Provider2.hwnd = hwnd;
9399 prov_root = &Provider2.IRawElementProviderSimple_iface;
9400 Provider_proxy2.override_hwnd = NULL;
9401 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9402 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9403 SET_EXPECT(prov_callback_base_hwnd);
9404 SET_EXPECT(prov_callback_nonclient);
9405 SET_EXPECT(prov_callback_parent_proxy);
9406 hr = UiaNodeFromHandle(hwnd2, &node);
9407 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9408 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9409 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9410 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9411 CHECK_CALLED(prov_callback_base_hwnd);
9412 CHECK_CALLED(prov_callback_nonclient);
9413 todo_wine CHECK_CALLED(prov_callback_parent_proxy);
9414
9415 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9416 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9418 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9419 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9420 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9421 VariantClear(&v);
9422
9423 ok_method_sequence(reg_prov_cb12, "reg_prov_cb12");
9424
9426
9427 /*
9428 * Provider returned by UiaRootObjectId on both HWNDs. Since Provider2
9429 * returns an HWND override, no ProviderType_Proxy callback for hwnd.
9430 */
9431 Provider.hwnd = hwnd2;
9432 Provider2.hwnd = hwnd;
9433 Provider2.override_hwnd = Provider_override.hwnd = hwnd2;
9434 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = TRUE;
9437 prov_root = &Provider2.IRawElementProviderSimple_iface;
9438 Provider_proxy2.override_hwnd = NULL;
9439 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
9440 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
9441 SET_EXPECT(prov_callback_base_hwnd);
9442 SET_EXPECT(prov_callback_nonclient);
9443 SET_EXPECT(prov_callback_parent_proxy);
9444 hr = UiaNodeFromHandle(hwnd2, &node);
9445 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9446 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9447 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
9448 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
9449 CHECK_CALLED(prov_callback_base_hwnd);
9450 CHECK_CALLED(prov_callback_nonclient);
9451
9452 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9453 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9455 check_node_provider_desc_todo(V_BSTR(&v), L"Override", L"Provider_override", TRUE);
9456 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
9457 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
9458 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
9459 VariantClear(&v);
9460
9461 ok_method_sequence(reg_prov_cb13, "reg_prov_cb13");
9462
9464
9465 Provider2.ignore_hwnd_prop = Provider_override.ignore_hwnd_prop = FALSE;
9467
9469 UnregisterClassA("UiaRegisterProviderCallback class", NULL);
9470 UnregisterClassA("UiaRegisterProviderCallback child class", NULL);
9471}
9472
9473static void set_cache_request(struct UiaCacheRequest *req, struct UiaCondition *view_cond, int scope,
9474 PROPERTYID *prop_ids, int prop_ids_count, PATTERNID *pattern_ids, int pattern_ids_count, int elem_mode)
9475{
9476 req->pViewCondition = view_cond;
9477 req->Scope = scope;
9478
9479 req->pProperties = prop_ids;
9480 req->cProperties = prop_ids_count;
9481 req->pPatterns = pattern_ids;
9482 req->cPatterns = pattern_ids_count;
9483
9484 req->automationElementMode = elem_mode;
9485}
9486
9487static void set_property_condition(struct UiaPropertyCondition *cond, int prop_id, VARIANT *val, int flags)
9488{
9490 cond->PropertyId = prop_id;
9491 cond->Value = *val;
9492 cond->Flags = flags;
9493}
9494
9495static void set_and_or_condition(struct UiaAndOrCondition *cond, int cond_type,
9496 struct UiaCondition **conds, int cond_count)
9497{
9498 cond->ConditionType = cond_type;
9499 cond->ppConditions = conds;
9500 cond->cConditions = cond_count;
9501}
9502
9503static void set_not_condition(struct UiaNotCondition *cond, struct UiaCondition *not_cond)
9504{
9506 cond->pConditions = not_cond;
9507}
9508
9509#define MAX_NODE_PROVIDERS 4
9513
9519};
9520
9522{
9523 memset(desc, 0, sizeof(*desc));
9524 desc->pid = pid;
9525 desc->hwnd = hwnd;
9526}
9527
9530{
9531 desc->prov_type[desc->prov_count] = prov_type;
9532 desc->prov_name[desc->prov_count] = prov_name;
9533 desc->parent_link[desc->prov_count] = parent_link;
9534 desc->nested_desc[desc->prov_count] = nested_desc;
9535 desc->prov_count++;
9536}
9537
9540{
9542}
9543
9544#define test_node_provider_desc( desc, desc_str ) \
9545 test_node_provider_desc_( (desc), (desc_str), __FILE__, __LINE__)
9546static void test_node_provider_desc_(struct node_provider_desc *desc, BSTR desc_str, const char *file, int line)
9547{
9548 int i;
9549
9550 check_node_provider_desc_prefix_(desc_str, desc->pid, desc->hwnd, file, line);
9551 for (i = 0; i < desc->prov_count; i++)
9552 {
9553 if (desc->nested_desc[i])
9554 {
9555 WCHAR buf[2048];
9556
9557 ok_(file, line)(get_nested_provider_desc(desc_str, desc->prov_type[i], desc->parent_link[i], buf),
9558 "Failed to get nested provider description\n");
9559 test_node_provider_desc_(desc->nested_desc[i], buf, file, line);
9560 }
9561 else
9562 check_node_provider_desc_(desc_str, desc->prov_type[i], desc->prov_name[i], desc->parent_link[i], FALSE, file, line);
9563 }
9564}
9565
9566/*
9567 * Cache requests are returned as a two dimensional safearray, with the first
9568 * dimension being the element index, and the second index being the
9569 * node/property/pattern value index for the element. The first element value is
9570 * always an HUIANODE, followed by requested property values, and finally
9571 * requested pattern handles.
9572 */
9573#define test_cache_req_sa( sa, exp_lbound, exp_elems, exp_node_desc ) \
9574 test_cache_req_sa_( (sa), (exp_lbound), (exp_elems), (exp_node_desc), __FILE__, __LINE__)
9575static void test_cache_req_sa_(SAFEARRAY *sa, LONG exp_lbound[2], LONG exp_elems[2],
9576 struct node_provider_desc *exp_node_desc, const char *file, int line)
9577{
9578 HUIANODE node;
9579 HRESULT hr;
9580 VARTYPE vt;
9581 VARIANT v;
9582 UINT dims;
9583 int i;
9584
9586 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9587 ok_(file, line)(vt == VT_VARIANT, "Unexpected vt %d\n", vt);
9588
9589 dims = SafeArrayGetDim(sa);
9590 ok_(file, line)(dims == 2, "Unexpected dims %d\n", dims);
9591
9592 for (i = 0; i < 2; i++)
9593 {
9594 LONG lbound, ubound, elems;
9595
9596 lbound = ubound = elems = 0;
9597 hr = SafeArrayGetLBound(sa, 1 + i, &lbound);
9598 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
9599 ok_(file, line)(exp_lbound[i] == lbound, "Unexpected lbound[%d] %ld\n", i, lbound);
9600
9601 hr = SafeArrayGetUBound(sa, 1 + i, &ubound);
9602 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
9603
9604 elems = (ubound - lbound) + 1;
9605 ok_(file, line)(exp_elems[i] == elems, "Unexpected elems[%d] %ld\n", i, elems);
9606 }
9607
9608 for (i = 0; i < exp_elems[0]; i++)
9609 {
9610 LONG idx[2] = { (exp_lbound[0] + i), exp_lbound[1] };
9611
9613 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9614
9616 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9617 VariantClear(&v);
9618
9619 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9620 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9621 test_node_provider_desc_(&exp_node_desc[i], V_BSTR(&v), file, line);
9622 VariantClear(&v);
9623
9625 }
9626}
9627
9628#define test_provider_event_advise_added( prov, event_id, todo) \
9629 test_provider_event_advise_added_( (prov), (event_id), (todo), __FILE__, __LINE__)
9630static void test_provider_event_advise_added_(struct Provider *prov, int event_id, BOOL todo, const char *file, int line)
9631{
9632 todo_wine_if (todo) ok_(file, line)(prov->advise_events_added_event_id == event_id, "%s: Unexpected advise event added, event ID %d.\n",
9634}
9635
9636static const struct prov_method_sequence cache_req_seq1[] = {
9637 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9638 { 0 }
9639};
9640
9641/*
9642 * Win10v1507 and below will attempt to do parent navigation if the
9643 * conditional check fails.
9644 */
9645static const struct prov_method_sequence cache_req_seq2[] = {
9646 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9647 { 0 }
9648};
9649
9650static const struct prov_method_sequence cache_req_seq3[] = {
9651 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
9653 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9655 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
9656 /* Navigates towards parent to check for clientside provider siblings. */
9657 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9659 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9660 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9661 { 0 }
9662};
9663
9664static const struct prov_method_sequence cache_req_seq4[] = {
9665 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
9666 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9667 { 0 }
9668};
9669
9670/* Sequence for non-matching property condition. */
9671static const struct prov_method_sequence cache_req_seq5[] = {
9672 { &Provider, PROV_GET_PROPERTY_VALUE }, /* Dependent upon property condition. */
9673 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* Dependent upon property condition. */
9674 /* Only done on Win10v1507 and below. */
9675 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9676 { 0 }
9677};
9678
9679static const struct prov_method_sequence cache_req_seq6[] = {
9681 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9682 /* Only done on Win10v1507 and below. */
9683 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9684 { 0 }
9685};
9686
9687static const struct prov_method_sequence cache_req_seq7[] = {
9689 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId. */
9690 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9691 { 0 }
9692};
9693
9694static const struct prov_method_sequence cache_req_seq8[] = {
9696 { 0 }
9697};
9698
9699static const struct prov_method_sequence cache_req_seq9[] = {
9700 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9701 /* Done twice on Windows, but we shouldn't need to replicate this. */
9702 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_IsControlElementPropertyId */
9703 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9705 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9706 /* Only done on Win10v1507 and below. */
9707 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
9708 { 0 }
9709};
9710
9711static const struct prov_method_sequence cache_req_seq10[] = {
9712 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9713 /* Done twice on Windows, but we shouldn't need to replicate this. */
9714 { &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_IsControlElementPropertyId */
9715 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
9717 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
9718 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId. */
9719 { 0 }
9720};
9721
9725{
9726 LONG exp_lbound[2], exp_elems[2], idx[2], i;
9727 struct Provider_prop_override prop_override;
9728 struct node_provider_desc exp_node_desc[2];
9729 struct UiaPropertyCondition prop_cond;
9730 struct UiaAndOrCondition and_or_cond;
9731 struct UiaCacheRequest cache_req;
9732 struct UiaCondition *cond_arr[2];
9733 struct UiaNotCondition not_cond;
9734 VARIANT v, v_arr[2];
9735 SAFEARRAY *out_req;
9736 IUnknown *unk_ns;
9737 BSTR tree_struct;
9738 int prop_ids[2];
9739 HUIANODE node;
9740 HRESULT hr;
9741
9743
9745 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9746
9747 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9749
9751 Provider.hwnd = NULL;
9753 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9754 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
9755
9756 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
9757 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
9759 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
9760 VariantClear(&v);
9761
9763
9764 /* NULL arg tests. */
9766 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, NULL);
9767 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9768
9769 hr = UiaGetUpdatedCache(node, NULL, NormalizeState_None, NULL, &out_req, &tree_struct);
9770 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9771
9772 hr = UiaGetUpdatedCache(NULL, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9773 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
9774
9775 /*
9776 * Cache request with NULL view condition, doesn't matter with
9777 * NormalizeState_None as passed in HUIANODE isn't evaluated against any
9778 * condition.
9779 */
9780 tree_struct = NULL; out_req = NULL;
9781 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9783 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9784 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9785 ok(!!out_req, "out_req == NULL\n");
9786 ok(!!tree_struct, "tree_struct == NULL\n");
9787
9788 exp_lbound[0] = exp_lbound[1] = 0;
9789 exp_elems[0] = exp_elems[1] = 1;
9790 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9791 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9792 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
9793
9794 SafeArrayDestroy(out_req);
9795 SysFreeString(tree_struct);
9796
9797 /*
9798 * NormalizeState_View, HUIANODE gets checked against the ConditionType_False
9799 * condition within the cache request structure, nothing is returned.
9800 */
9801 tree_struct = NULL; out_req = NULL;
9803 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9804 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9805 ok(!out_req, "out_req != NULL\n");
9806
9807 /* Empty tree structure string. */
9808 ok(!!tree_struct, "tree_struct == NULL\n");
9809 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9810 SysFreeString(tree_struct);
9811 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
9812
9813 /*
9814 * NormalizeState_View, HUIANODE gets checked against the ConditionType_True
9815 * condition within the cache request structure, returns this HUIANODE.
9816 */
9817 tree_struct = NULL; out_req = NULL;
9819 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9820 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9821 ok(!!out_req, "out_req == NULL\n");
9822 ok(!!tree_struct, "tree_struct == NULL\n");
9823
9824 exp_lbound[0] = exp_lbound[1] = 0;
9825 exp_elems[0] = exp_elems[1] = 1;
9826 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9827 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9828 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
9829
9830 SafeArrayDestroy(out_req);
9831 SysFreeString(tree_struct);
9832
9833 /*
9834 * NormalizeState_Custom, HUIANODE gets checked against our passed in
9835 * ConditionType_False condition.
9836 */
9838 tree_struct = NULL; out_req = NULL;
9839 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaFalseCondition, &out_req, &tree_struct);
9840 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9841 ok(!out_req, "out_req != NULL\n");
9842
9843 /* Empty tree structure string. */
9844 ok(!!tree_struct, "tree_struct == NULL\n");
9845 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9846 SysFreeString(tree_struct);
9847
9848 ok_method_sequence(cache_req_seq2, "cache_req_seq2");
9849
9850 /*
9851 * NormalizeState_Custom, HUIANODE gets checked against the ConditionType_True
9852 * condition we pass in, returns this HUIANODE.
9853 */
9854 tree_struct = NULL; out_req = NULL;
9856 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_Custom, (struct UiaCondition *)&UiaTrueCondition, &out_req, &tree_struct);
9857 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9858 ok(!!out_req, "out_req == NULL\n");
9859 ok(!!tree_struct, "tree_struct == NULL\n");
9860
9861 exp_lbound[0] = exp_lbound[1] = 0;
9862 exp_elems[0] = exp_elems[1] = 1;
9863 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9864 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9865 ok_method_sequence(cache_req_seq1, "cache_req_seq1");
9866
9867 SafeArrayDestroy(out_req);
9868 SysFreeString(tree_struct);
9869
9870 /*
9871 * CacheRequest with TreeScope_Children.
9872 */
9873 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9875 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
9876 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
9877 tree_struct = NULL; out_req = NULL;
9879 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
9880 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9881 todo_wine ok(!!out_req, "out_req == NULL\n");
9882 todo_wine ok(!!tree_struct, "tree_struct == NULL\n");
9883 todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
9884 todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
9885 if (out_req)
9886 {
9887 exp_elems[0] = 2;
9888 exp_elems[1] = 1;
9889 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9890
9891 ok(!wcscmp(tree_struct, L"(P)P))"), "tree structure %s\n", debugstr_w(tree_struct));
9892 ok_method_sequence(cache_req_seq3, "cache_req_seq3");
9893 }
9894
9895 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
9896 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
9897 SafeArrayDestroy(out_req);
9898 SysFreeString(tree_struct);
9899
9900 /*
9901 * ConditionType_And tests.
9902 */
9903 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
9905 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
9906 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9907 cond_arr[1] = (struct UiaCondition *)&UiaTrueCondition;
9908 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
9909 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9911 tree_struct = NULL; out_req = NULL;
9912
9913 /* Equivalent to: if (1 && 1) */
9914 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9916 ok(!!out_req, "out_req == NULL\n");
9917 ok(!!tree_struct, "tree_struct == NULL\n");
9918
9919 exp_lbound[0] = exp_lbound[1] = 0;
9920 exp_elems[0] = exp_elems[1] = 1;
9921 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9922 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9924
9925 SafeArrayDestroy(out_req);
9926 SysFreeString(tree_struct);
9927
9928 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9929 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9930 set_and_or_condition(&and_or_cond, ConditionType_And, cond_arr, ARRAY_SIZE(cond_arr));
9931 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9933 tree_struct = NULL; out_req = NULL;
9934
9935 /* Equivalent to: if (1 && 0) */
9936 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9937 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9939 ok(!out_req, "out_req != NULL\n");
9940 ok(!!tree_struct, "tree_struct == NULL\n");
9941 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9942
9943 SysFreeString(tree_struct);
9944
9945 /*
9946 * ConditionType_Or tests.
9947 */
9948 cond_arr[0] = (struct UiaCondition *)&UiaTrueCondition;
9949 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9950 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
9951 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9953 tree_struct = NULL; out_req = NULL;
9954
9955 /* Equivalent to: if (1 || 0) */
9956 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9957 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9958 ok(!!out_req, "out_req == NULL\n");
9959 ok(!!tree_struct, "tree_struct == NULL\n");
9960
9961 exp_lbound[0] = exp_lbound[1] = 0;
9962 exp_elems[0] = exp_elems[1] = 1;
9963 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
9964 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
9966
9967 SafeArrayDestroy(out_req);
9968 SysFreeString(tree_struct);
9969
9970 cond_arr[0] = (struct UiaCondition *)&UiaFalseCondition;
9971 cond_arr[1] = (struct UiaCondition *)&UiaFalseCondition;
9972 set_and_or_condition(&and_or_cond, ConditionType_Or, cond_arr, ARRAY_SIZE(cond_arr));
9973 set_cache_request(&cache_req, (struct UiaCondition *)&and_or_cond, TreeScope_Element, NULL, 0, NULL, 0,
9975 tree_struct = NULL; out_req = NULL;
9976
9977 /* Equivalent to: if (0 || 0) */
9978 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9979 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9981 ok(!out_req, "out_req != NULL\n");
9982 ok(!!tree_struct, "tree_struct == NULL\n");
9983 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
9984
9985 SysFreeString(tree_struct);
9986
9987 /*
9988 * ConditionType_Not tests.
9989 */
9990 set_not_condition(&not_cond, (struct UiaCondition *)&UiaFalseCondition);
9991 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
9993 tree_struct = NULL; out_req = NULL;
9994
9995 /* Equivalent to: if (!0) */
9996 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
9997 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
9998 ok(!!out_req, "out_req == NULL\n");
9999 ok(!!tree_struct, "tree_struct == NULL\n");
10000
10001 exp_lbound[0] = exp_lbound[1] = 0;
10002 exp_elems[0] = exp_elems[1] = 1;
10003 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10004 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10006
10007 SafeArrayDestroy(out_req);
10008 SysFreeString(tree_struct);
10009
10010 set_not_condition(&not_cond, (struct UiaCondition *)&UiaTrueCondition);
10011 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, NULL, 0, NULL, 0,
10013 tree_struct = NULL; out_req = NULL;
10014
10015 /* Equivalent to: if (!1) */
10016 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10018 ok(!out_req, "out_req != NULL\n");
10019 ok(!!tree_struct, "tree_struct == NULL\n");
10020 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10021 SysFreeString(tree_struct);
10023
10024 /*
10025 * ConditionType_Property tests.
10026 */
10028
10029 /* Test UIAutomationType_IntArray property conditions. */
10030 if (UiaLookupId(AutomationIdentifierType_Property, &OutlineColor_Property_GUID))
10031 {
10032 V_VT(&v) = VT_I4 | VT_ARRAY;
10034 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
10035 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10037 tree_struct = NULL; out_req = NULL;
10038
10039 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10040 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10041 ok(!!out_req, "out_req == NULL\n");
10042 ok(!!tree_struct, "tree_struct == NULL\n");
10043
10044 exp_lbound[0] = exp_lbound[1] = 0;
10045 exp_elems[0] = exp_elems[1] = 1;
10046 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10047 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10049
10050 SafeArrayDestroy(out_req);
10051 SysFreeString(tree_struct);
10052 VariantClear(&v);
10053
10054 /* Same values, except we're short by one element. */
10055 V_VT(&v) = VT_I4 | VT_ARRAY;
10057
10058 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val) - 1; i++)
10059 SafeArrayPutElement(V_ARRAY(&prop_cond.Value), &i, (void *)&uia_i4_arr_prop_val[i]);
10060
10061 set_property_condition(&prop_cond, UIA_OutlineColorPropertyId, &v, PropertyConditionFlags_None);
10062 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10064 tree_struct = NULL; out_req = NULL;
10065
10066 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10067 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10069 ok(!out_req, "out_req != NULL\n");
10070 ok(!!tree_struct, "tree_struct == NULL\n");
10071 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10072
10073 SysFreeString(tree_struct);
10074 VariantClear(&v);
10075 }
10076 else
10077 win_skip("UIA_OutlineColorPropertyId unavailable, skipping property condition tests for it.\n");
10078
10079 /* UIA_RuntimeIdPropertyId comparison. */
10080 Provider.runtime_id[0] = 0xdeadbeef; Provider.runtime_id[1] = 0xfeedbeef;
10081 V_VT(&v) = VT_I4 | VT_ARRAY;
10083 for (i = 0; i < ARRAY_SIZE(Provider.runtime_id); i++)
10085
10086 set_property_condition(&prop_cond, UIA_RuntimeIdPropertyId, &v, PropertyConditionFlags_None);
10087 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10089 tree_struct = NULL; out_req = NULL;
10090
10091 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10092 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10093 ok(!!out_req, "out_req == NULL\n");
10094 ok(!!tree_struct, "tree_struct == NULL\n");
10095
10096 exp_lbound[0] = exp_lbound[1] = 0;
10097 exp_elems[0] = exp_elems[1] = 1;
10098 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10099 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10101
10102 SafeArrayDestroy(out_req);
10103 SysFreeString(tree_struct);
10104 VariantClear(&prop_cond.Value);
10105
10106 /* UIAutomationType_Bool property condition tests. */
10107 prop_override.prop_id = UIA_IsControlElementPropertyId;
10108 V_VT(&prop_override.val) = VT_BOOL;
10109 V_BOOL(&prop_override.val) = VARIANT_FALSE;
10110 Provider.prop_override = &prop_override;
10112
10113 V_VT(&v) = VT_BOOL;
10114 V_BOOL(&v) = VARIANT_FALSE;
10115 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10116 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10118 tree_struct = NULL; out_req = NULL;
10119
10120 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10121 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10122 ok(!!out_req, "out_req == NULL\n");
10123 ok(!!tree_struct, "tree_struct == NULL\n");
10124
10125 exp_lbound[0] = exp_lbound[1] = 0;
10126 exp_elems[0] = exp_elems[1] = 1;
10127 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10128 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10130
10131 SafeArrayDestroy(out_req);
10132 SysFreeString(tree_struct);
10133 VariantClear(&v);
10134
10135 /*
10136 * Provider now returns VARIANT_TRUE for UIA_IsControlElementPropertyId,
10137 * conditional check will fail.
10138 */
10139 prop_override.prop_id = UIA_IsControlElementPropertyId;
10140 V_VT(&prop_override.val) = VT_BOOL;
10141 V_BOOL(&prop_override.val) = VARIANT_TRUE;
10142 Provider.prop_override = &prop_override;
10144
10145 V_VT(&v) = VT_BOOL;
10146 V_BOOL(&v) = VARIANT_FALSE;
10147 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10148 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
10150 tree_struct = NULL; out_req = NULL;
10151
10152 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10153 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10155 ok(!out_req, "out_req != NULL\n");
10156 ok(!!tree_struct, "tree_struct == NULL\n");
10157 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10158
10159 SysFreeString(tree_struct);
10160 VariantClear(&v);
10161
10164
10165 /*
10166 * Tests for property value caching.
10167 */
10168 prop_ids[0] = UIA_RuntimeIdPropertyId;
10169 /* Invalid property ID, no work will be done. */
10170 prop_ids[1] = 1;
10171 tree_struct = NULL; out_req = NULL;
10172 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
10173 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
10174 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
10175 ok(!out_req, "out_req != NULL\n");
10176 ok(!tree_struct, "tree_struct != NULL\n");
10177
10178 /*
10179 * Retrieve values for UIA_RuntimeIdPropertyId and
10180 * UIA_IsControlElementPropertyId in the returned cache.
10181 */
10182 prop_ids[0] = UIA_RuntimeIdPropertyId;
10183 prop_ids[1] = UIA_IsControlElementPropertyId;
10185 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10186 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10187
10188 tree_struct = NULL; out_req = NULL;
10189 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
10190 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
10191 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10192 ok(!!out_req, "out_req == NULL\n");
10193 ok(!!tree_struct, "tree_struct == NULL\n");
10194
10195 exp_lbound[0] = exp_lbound[1] = 0;
10196 exp_elems[0] = 1;
10197 exp_elems[1] = 3;
10198 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10199 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10200
10201 idx[0] = 0;
10202 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
10203 {
10204 idx[1] = 1 + i;
10205 VariantInit(&v_arr[i]);
10206 hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
10207 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10208 }
10209
10210 ok(V_VT(&v_arr[0]) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
10211 ok(V_UNKNOWN(&v_arr[0]) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v_arr[0]));
10212 VariantClear(&v_arr[0]);
10213
10214 ok(check_variant_bool(&v_arr[1], TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
10215 VariantClear(&v_arr[1]);
10216
10217 ok_method_sequence(cache_req_seq7, "cache_req_seq7");
10218 SafeArrayDestroy(out_req);
10219 SysFreeString(tree_struct);
10220
10221 /*
10222 * Again, but return a valid runtime ID and a different value for
10223 * UIA_IsControlElementPropertyId.
10224 */
10225 V_VT(&v) = VT_BOOL;
10226 V_BOOL(&v) = VARIANT_FALSE;
10227 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
10228 set_provider_prop_override(&Provider, &prop_override, 1);
10229 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
10230 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10231 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10232
10233 tree_struct = NULL; out_req = NULL;
10234 set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
10235 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
10236 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10237 ok(!!out_req, "out_req == NULL\n");
10238 ok(!!tree_struct, "tree_struct == NULL\n");
10239
10240 exp_lbound[0] = exp_lbound[1] = 0;
10241 exp_elems[0] = 1;
10242 exp_elems[1] = 3;
10243 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10244 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10245
10246 idx[0] = 0;
10247 for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
10248 {
10249 idx[1] = 1 + i;
10250 VariantInit(&v_arr[i]);
10251 hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
10252 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10253 }
10254
10255 ok(V_VT(&v_arr[0]) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v_arr[0]));
10257 VariantClear(&v_arr[0]);
10258
10259 ok(check_variant_bool(&v_arr[1], FALSE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
10260 VariantClear(&v_arr[1]);
10261
10262 ok_method_sequence(cache_req_seq7, "cache_req_seq7");
10263 SafeArrayDestroy(out_req);
10264 SysFreeString(tree_struct);
10265
10266 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10267 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10268
10269 /* Normalization navigation tests. */
10272
10273 hr = UiaNodeFromProvider(&Provider_child.IRawElementProviderSimple_iface, &node);
10274 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10275 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10276 ok_method_sequence(cache_req_seq8, "cache_req_seq8");
10277
10278 /*
10279 * Neither Provider_child or Provider match this condition, return
10280 * nothing.
10281 */
10283 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
10284 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10285 tree_struct = NULL; out_req = NULL;
10286 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10287 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10288 ok(!out_req, "out_req != NULL\n");
10289 ok(!!tree_struct, "tree_struct == NULL\n");
10290 ok(!wcscmp(tree_struct, L""), "tree structure %s\n", debugstr_w(tree_struct));
10291 SysFreeString(tree_struct);
10292 ok_method_sequence(cache_req_seq9, "cache_req_seq9");
10293
10294 /*
10295 * Provider now matches our condition, we'll get Provider in the cache
10296 * request.
10297 */
10299 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
10300 set_provider_prop_override(&Provider, &prop_override, 1);
10301 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10302 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
10303
10304 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0, AutomationElementMode_Full);
10305 tree_struct = NULL; out_req = NULL;
10306 hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_View, NULL, &out_req, &tree_struct);
10307 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10308 ok(!!out_req, "out_req == NULL\n");
10309 ok(!!tree_struct, "tree_struct == NULL\n");
10310 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10311
10312 exp_lbound[0] = exp_lbound[1] = 0;
10313 exp_elems[0] = exp_elems[1] = 1;
10314 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10315 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10316 ok_method_sequence(cache_req_seq10, "cache_req_seq10");
10317
10318 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
10319 SafeArrayDestroy(out_req);
10320 SysFreeString(tree_struct);
10321 VariantClear(&v);
10322
10323 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
10324 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10327
10328 IUnknown_Release(unk_ns);
10330}
10331
10332static const struct prov_method_sequence nav_seq1[] = {
10335 /* Only done on Win10v1809+ */
10337 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10338 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10339 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10340 /* Windows 10+ calls these. */
10344 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10345 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10346 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10347 { 0 }
10348};
10349
10350static const struct prov_method_sequence nav_seq2[] = {
10351 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10352 NODE_CREATE_SEQ(&Provider_hwnd_child),
10353 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10354 { 0 }
10355};
10356
10357static const struct prov_method_sequence nav_seq3[] = {
10358 { &Provider_hwnd_child, FRAG_NAVIGATE}, /* NavigateDirection_NextSibling */
10359 NODE_CREATE_SEQ(&Provider_hwnd_child2),
10360 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10361 { 0 }
10362};
10363
10364static const struct prov_method_sequence nav_seq4[] = {
10365 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10366 { &Provider_hwnd_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10368 /* All Windows versions use the NativeWindowHandle provider type check here. */
10369 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
10373 /* Only done on Win10v1809+ */
10375 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10376 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10377 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10378 /* Windows 10+ calls these. */
10382 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10383 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS },
10384 /* Win10v1507 and below call this. */
10385 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10386 { &Provider_nc_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
10387 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
10388 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10389 /* Only called on Windows versions past Win10v1507. */
10390 { &Provider_nc_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
10391 { &Provider_nc_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10392 { 0 }
10393};
10394
10395static const struct prov_method_sequence nav_seq5[] = {
10396 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
10397 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10402 /* Only done on Win10v1809+ */
10404 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10405 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10406 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10407 /* Windows 10+ calls these. */
10411 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
10412 NODE_CREATE_SEQ(&Provider_hwnd_child2),
10413 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10414 { 0 }
10415};
10416
10417static const struct prov_method_sequence nav_seq6[] = {
10418 { &Provider_nc_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10419 NODE_CREATE_SEQ(&Provider_nc_child2),
10420 { &Provider_nc_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10421 { 0 }
10422};
10423
10424static const struct prov_method_sequence nav_seq7[] = {
10425 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10426 { &Provider_nc_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10431 /* Only done on Win10v1809+ */
10433 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10434 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10435 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10436 /* Windows 10+ calls these. */
10440 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10442 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10443 { 0 }
10444};
10445
10446static const struct prov_method_sequence nav_seq8[] = {
10447 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10449 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10450 { 0 }
10451};
10452
10453static const struct prov_method_sequence nav_seq9[] = {
10454 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10455 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10457 /* Win10v1507 and below call this. */
10458 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10462 /* Only done on Win10v1809+ */
10464 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10465 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10466 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10467 /* Windows 10+ calls these. */
10471 /* Navigates to parent a second time. */
10472 { &Provider_child2, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10474 /* Win10v1507 and below call this. */
10475 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10478 /* Win10v1507 and below call this. */
10479 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10481 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10484 /* Only done on Win10v1809+ */
10486 { &Provider, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10487 { &Provider_nc, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10488 { &Provider_hwnd, FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */
10489 /* Windows 10+ calls these. */
10493};
10494
10495static const struct prov_method_sequence nav_seq10[] = {
10496 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
10498 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10499 { 0 }
10500};
10501
10502static const struct prov_method_sequence nav_seq11[] = {
10503 { &Provider_hwnd, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
10504 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS },
10505 /* All Windows versions use the NativeWindowHandle provider type check here. */
10506 { &Provider_hwnd_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_NativeWindowHandlePropertyId */
10507 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER },
10510 /* Only done on Win10v1809+ */
10511 { &Provider_hwnd_child, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
10512 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10513 /* Windows 10+ calls these. */
10516 { &Provider_hwnd_child, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
10517 { &Provider_hwnd_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
10518 NODE_CREATE_SEQ(&Provider_hwnd_child2),
10519 { &Provider_hwnd_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10520 { 0 }
10521};
10522
10523static const struct prov_method_sequence nav_seq12[] = {
10524 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
10526 { &Provider_child2, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
10530 /* Only done on Win10v1809+ */
10532 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10533 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10534 /* Windows 10+ calls these. */
10538 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
10540 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10541 { 0 }
10542};
10543
10544static const struct prov_method_sequence nav_seq13[] = {
10547 /* Only done on Win10v1809+ */
10549 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10550 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10551 /* Windows 10+ calls these. */
10555 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10556 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10557 { &Provider_hwnd, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10558 { 0 }
10559};
10560
10561static const struct prov_method_sequence nav_seq14[] = {
10562 { &Provider_nc, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10564 { &Provider2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10565 { 0 }
10566};
10567
10568static const struct prov_method_sequence nav_seq15[] = {
10569 NODE_CREATE_SEQ(&Provider_child2_child_child),
10570 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10571};
10572
10573static const struct prov_method_sequence nav_seq16[] = {
10574 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10575 NODE_CREATE_SEQ(&Provider_child2_child),
10576 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10577 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10579 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10580 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10582 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10583 /* Only done on Win10v1507 and below. */
10584 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
10585 { 0 }
10586};
10587
10588static const struct prov_method_sequence nav_seq17[] = {
10589 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10590 NODE_CREATE_SEQ(&Provider_child2_child),
10591 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10592 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10594 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10595 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
10597 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
10598 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
10599 { 0 }
10600};
10601
10602static void set_provider_nav_ifaces(struct Provider *prov, struct Provider *parent, struct Provider *frag_root,
10603 struct Provider *prev_sibling, struct Provider *next_sibling, struct Provider *first_child,
10604 struct Provider *last_child)
10605{
10606 prov->parent = NULL;
10607 prov->frag_root = NULL;
10608 prov->prev_sibling = NULL;
10609 prov->next_sibling = NULL;
10610 prov->first_child = NULL;
10611 prov->last_child = NULL;
10612
10613 if (parent)
10614 prov->parent = &parent->IRawElementProviderFragment_iface;
10615 if (frag_root)
10616 prov->frag_root = &frag_root->IRawElementProviderFragmentRoot_iface;
10617 if (prev_sibling)
10618 prov->prev_sibling = &prev_sibling->IRawElementProviderFragment_iface;
10619 if (next_sibling)
10620 prov->next_sibling = &next_sibling->IRawElementProviderFragment_iface;
10621 if (first_child)
10622 prov->first_child = &first_child->IRawElementProviderFragment_iface;
10623 if (last_child)
10624 prov->last_child = &last_child->IRawElementProviderFragment_iface;
10625}
10626
10627static void test_UiaNavigate(void)
10628{
10629 struct Provider_prop_override prop_override;
10630 LONG exp_lbound[2], exp_elems[2], idx[2], i;
10631 struct node_provider_desc exp_node_desc[4];
10632 struct UiaPropertyCondition prop_cond;
10633 struct UiaCacheRequest cache_req;
10634 HUIANODE node, node2, node3;
10635 SAFEARRAY *out_req;
10636 BSTR tree_struct;
10637 WNDCLASSA cls;
10638 HRESULT hr;
10639 VARIANT v;
10640 HWND hwnd;
10641
10643 cls.style = 0;
10645 cls.cbClsExtra = 0;
10646 cls.cbWndExtra = 0;
10648 cls.hIcon = 0;
10649 cls.hCursor = NULL;
10650 cls.hbrBackground = NULL;
10651 cls.lpszMenuName = NULL;
10652 cls.lpszClassName = "UiaNavigate class";
10653
10654 RegisterClassA(&cls);
10655
10656 hwnd = CreateWindowA("UiaNavigate class", "Test window", WS_OVERLAPPEDWINDOW,
10657 0, 0, 100, 100, NULL, NULL, NULL, NULL);
10658
10660 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
10661 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
10662
10663 set_provider_nav_ifaces(&Provider_nc, NULL, NULL, NULL, NULL, &Provider_nc_child, &Provider_nc_child2);
10664 set_provider_nav_ifaces(&Provider_nc_child, &Provider_nc, &Provider_nc, NULL,
10665 &Provider_nc_child2, NULL, NULL);
10666 set_provider_nav_ifaces(&Provider_nc_child2, &Provider_nc, &Provider_nc, &Provider_nc_child,
10667 NULL, NULL, NULL);
10668
10669 set_provider_nav_ifaces(&Provider_hwnd, NULL, NULL, NULL, NULL, &Provider_hwnd_child, &Provider_hwnd_child2);
10670 set_provider_nav_ifaces(&Provider_hwnd_child, &Provider_hwnd, &Provider_hwnd, NULL,
10671 &Provider_hwnd_child2, NULL, NULL);
10672 set_provider_nav_ifaces(&Provider_hwnd_child2, &Provider_hwnd, &Provider_hwnd, &Provider_hwnd_child,
10673 NULL, NULL, NULL);
10674
10675 /*
10676 * Show navigation behavior for multi-provider nodes. Navigation order is:
10677 * HWND provider children.
10678 * Non-Client provider children.
10679 * Main provider children.
10680 * Override provider children.
10681 */
10683 Provider.hwnd = Provider_hwnd.hwnd = Provider_nc.hwnd = hwnd;
10684 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = TRUE;
10686 node = (void *)0xdeadbeef;
10687 /* Only sent on Win7. */
10688 SET_EXPECT(winproc_GETOBJECT_CLIENT);
10689 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10690 SET_EXPECT(prov_callback_base_hwnd);
10691 SET_EXPECT(prov_callback_nonclient);
10693 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
10694 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
10695 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
10696 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
10697 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10698 CHECK_CALLED(prov_callback_base_hwnd);
10699 CHECK_CALLED(prov_callback_nonclient);
10700 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
10701
10702 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
10703 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10705 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
10706 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
10707 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
10708 VariantClear(&v);
10709
10710 ok_method_sequence(nav_seq1, "nav_seq1");
10711
10712 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
10714 idx[0] = idx[1] = 0;
10715
10716 /* Navigate to Provider_hwnd_child. */
10717 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child", TRUE);
10719 tree_struct = NULL; out_req = NULL;
10720 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10721 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10722 ok(!!out_req, "out_req == NULL\n");
10723 ok(!!tree_struct, "tree_struct == NULL\n");
10724 ok(Provider_hwnd_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10725
10726 node2 = node3 = NULL;
10727 hr = SafeArrayGetElement(out_req, idx, &v);
10728 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10729
10730 hr = UiaHUiaNodeFromVariant(&v, &node2);
10731 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10732 IUnknown_AddRef((IUnknown *)node2);
10733
10734 exp_lbound[0] = exp_lbound[1] = 0;
10735 exp_elems[0] = exp_elems[1] = 1;
10736 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10737
10738 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10739 ok_method_sequence(nav_seq2, "nav_seq2");
10740
10741 SafeArrayDestroy(out_req);
10742 SysFreeString(tree_struct);
10743
10744 /* Navigate to Provider_hwnd_child2. */
10745 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10746 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10747 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10748 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10749 ok(!!out_req, "out_req == NULL\n");
10750 ok(!!tree_struct, "tree_struct == NULL\n");
10751 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10752
10753 hr = SafeArrayGetElement(out_req, idx, &v);
10754 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10755
10756 hr = UiaHUiaNodeFromVariant(&v, &node3);
10757 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10758 IUnknown_AddRef((IUnknown *)node3);
10759
10760 exp_lbound[0] = exp_lbound[1] = 0;
10761 exp_elems[0] = exp_elems[1] = 1;
10762 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10763
10764 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10765 ok_method_sequence(nav_seq3, "nav_seq3");
10766
10767 SafeArrayDestroy(out_req);
10768 SysFreeString(tree_struct);
10769
10770 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10771 ok(Provider_hwnd_child.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10772 node2 = node3;
10773
10774 /* Navigate to Provider_nc_child. */
10775 SET_EXPECT(prov_callback_nonclient);
10776 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10777 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10778 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child", TRUE);
10779 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10780 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10781 ok(!!out_req, "out_req == NULL\n");
10782 ok(!!tree_struct, "tree_struct == NULL\n");
10783 ok(Provider_nc_child.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
10784 CHECK_CALLED(prov_callback_nonclient);
10785 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10786
10787 hr = SafeArrayGetElement(out_req, idx, &v);
10788 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10789
10790 hr = UiaHUiaNodeFromVariant(&v, &node3);
10791 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10792 IUnknown_AddRef((IUnknown *)node3);
10793
10794 exp_lbound[0] = exp_lbound[1] = 0;
10795 exp_elems[0] = exp_elems[1] = 1;
10796 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10797
10798 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10799 ok_method_sequence(nav_seq4, "nav_seq4");
10800
10801 SafeArrayDestroy(out_req);
10802 SysFreeString(tree_struct);
10803
10804 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10805 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10806 node2 = node3;
10807
10808 /* Navigate back to Provider_hwnd_child2. */
10809 SET_EXPECT(prov_callback_base_hwnd);
10810 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10811 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10812 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10813 hr = UiaNavigate(node2, NavigateDirection_PreviousSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10814 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10815 ok(!!out_req, "out_req == NULL\n");
10816 ok(!!tree_struct, "tree_struct == NULL\n");
10817 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10818 CHECK_CALLED(prov_callback_base_hwnd);
10819 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10820
10821 hr = SafeArrayGetElement(out_req, idx, &v);
10822 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10823
10824 hr = UiaHUiaNodeFromVariant(&v, &node3);
10825 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10826 IUnknown_AddRef((IUnknown *)node3);
10827
10828 exp_lbound[0] = exp_lbound[1] = 0;
10829 exp_elems[0] = exp_elems[1] = 1;
10830 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10831
10832 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10833 ok_method_sequence(nav_seq5, "nav_seq5");
10834
10835 SafeArrayDestroy(out_req);
10836 SysFreeString(tree_struct);
10837
10838 ok(UiaNodeRelease(node3), "UiaNodeRelease returned FALSE\n");
10839 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10840
10841 /* Navigate to Provider_nc_child2. */
10842 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10843 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_nc_child2", TRUE);
10844 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10845 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10846 ok(!!out_req, "out_req == NULL\n");
10847 ok(!!tree_struct, "tree_struct == NULL\n");
10848 ok(Provider_nc_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
10849
10850 hr = SafeArrayGetElement(out_req, idx, &v);
10851 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10852
10853 hr = UiaHUiaNodeFromVariant(&v, &node3);
10854 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10855 IUnknown_AddRef((IUnknown *)node3);
10856
10857 exp_lbound[0] = exp_lbound[1] = 0;
10858 exp_elems[0] = exp_elems[1] = 1;
10859 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10860
10861 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10862 ok_method_sequence(nav_seq6, "nav_seq6");
10863
10864 SafeArrayDestroy(out_req);
10865 SysFreeString(tree_struct);
10866
10867 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10868 ok(Provider_nc_child.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child.ref);
10869 node2 = node3;
10870
10871 /* Navigate to Provider_child. */
10872 SET_EXPECT(prov_callback_base_hwnd);
10873 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10874 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10875 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
10876 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10877 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10878 ok(!!out_req, "out_req == NULL\n");
10879 ok(!!tree_struct, "tree_struct == NULL\n");
10880 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
10881 CHECK_CALLED(prov_callback_base_hwnd);
10882 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10883
10884 hr = SafeArrayGetElement(out_req, idx, &v);
10885 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10886
10887 hr = UiaHUiaNodeFromVariant(&v, &node3);
10888 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10889 IUnknown_AddRef((IUnknown *)node3);
10890
10891 exp_lbound[0] = exp_lbound[1] = 0;
10892 exp_elems[0] = exp_elems[1] = 1;
10893 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10894
10895 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10896 ok_method_sequence(nav_seq7, "nav_seq7");
10897
10898 SafeArrayDestroy(out_req);
10899 SysFreeString(tree_struct);
10900
10901 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10902 ok(Provider_nc_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_nc_child2.ref);
10903 node2 = node3;
10904
10905 /* Navigate to Provider_child2. */
10906 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10907 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
10908 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10909 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10910 ok(!!out_req, "out_req == NULL\n");
10911 ok(!!tree_struct, "tree_struct == NULL\n");
10912 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
10913
10914 hr = SafeArrayGetElement(out_req, idx, &v);
10915 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10916
10917 hr = UiaHUiaNodeFromVariant(&v, &node3);
10918 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10919 IUnknown_AddRef((IUnknown *)node3);
10920
10921 exp_lbound[0] = exp_lbound[1] = 0;
10922 exp_elems[0] = exp_elems[1] = 1;
10923 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10924
10925 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10926 ok_method_sequence(nav_seq8, "nav_seq8");
10927
10928 SafeArrayDestroy(out_req);
10929 SysFreeString(tree_struct);
10930
10931 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10932 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
10933 node2 = node3;
10934
10935 /* Try navigating to next sibling on the final child of the node. */
10936 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
10937 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
10938 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
10939 hr = UiaNavigate(node2, NavigateDirection_NextSibling, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10940 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10941 ok_method_sequence(nav_seq9, "nav_seq9");
10942 ok(!out_req, "out_req != NULL\n");
10943 ok(!tree_struct, "tree_struct != NULL\n");
10944 todo_wine CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
10945 todo_wine CHECK_CALLED_MULTI(prov_callback_base_hwnd, 2);
10946 todo_wine CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, 2);
10947
10948 SafeArrayDestroy(out_req);
10949 SysFreeString(tree_struct);
10950 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
10951 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
10952
10953 /* Navigate to Provider_child2, last child. */
10954 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10955 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
10957 tree_struct = NULL;
10958 out_req = NULL;
10959 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10960 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10961 ok(!!out_req, "out_req == NULL\n");
10962 ok(!!tree_struct, "tree_struct == NULL\n");
10963 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child.ref);
10964
10965 exp_lbound[0] = exp_lbound[1] = 0;
10966 exp_elems[0] = exp_elems[1] = 1;
10967 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
10968
10969 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
10970 ok_method_sequence(nav_seq10, "nav_seq10");
10971
10972 SafeArrayDestroy(out_req);
10973 SysFreeString(tree_struct);
10974
10975 /*
10976 * If the child we navigate to from a parent isn't considered the "parent
10977 * link" of it's HUIANODE, it is skipped. Here, we set Provider_hwnd_child
10978 * to an HWND provider, and set its main provider as Provider, which is
10979 * the parent link of the node.
10980 */
10981 Provider_hwnd_child.hwnd = hwnd;
10982 Provider_hwnd_child.prov_opts = ProviderOptions_ClientSideProvider;
10983 Provider.parent = &Provider2.IRawElementProviderFragment_iface;
10984 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
10985 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_hwnd_child2", TRUE);
10986 tree_struct = NULL;
10987 out_req = NULL;
10988 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
10989 SET_EXPECT(prov_callback_nonclient);
10990 hr = UiaNavigate(node, NavigateDirection_FirstChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
10991 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
10992 ok(!!out_req, "out_req == NULL\n");
10993 ok(!!tree_struct, "tree_struct == NULL\n");
10994 ok(Provider_hwnd_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
10995 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
10996 CHECK_CALLED(prov_callback_nonclient);
10997
10998 hr = SafeArrayGetElement(out_req, idx, &v);
10999 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11000
11001 hr = UiaHUiaNodeFromVariant(&v, &node2);
11002 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11003 IUnknown_AddRef((IUnknown *)node2);
11004
11005 exp_lbound[0] = exp_lbound[1] = 0;
11006 exp_elems[0] = exp_elems[1] = 1;
11007 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11008
11009 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11010 ok_method_sequence(nav_seq11, "nav_seq11");
11011
11012 SafeArrayDestroy(out_req);
11013 SysFreeString(tree_struct);
11014
11015 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11016 ok(Provider_hwnd_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
11017
11018 /*
11019 * Same test as before, except with NavigateDirection_LastChild. This will
11020 * end up with Provider_nc as the parent link for the node instead of
11021 * Provider_child2.
11022 */
11023 Provider_child2.hwnd = hwnd;
11024 Provider_child2.ignore_hwnd_prop = TRUE;
11025 Provider_child2.parent = NULL;
11026 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
11028 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11029 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11030 tree_struct = NULL;
11031 out_req = NULL;
11032 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
11033 SET_EXPECT(prov_callback_nonclient);
11034 SET_EXPECT(prov_callback_base_hwnd);
11035 hr = UiaNavigate(node, NavigateDirection_LastChild, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
11036 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11037 ok(!!out_req, "out_req == NULL\n");
11038 ok(!!tree_struct, "tree_struct == NULL\n");
11039 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd_child2.ref);
11040 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
11041 CHECK_CALLED(prov_callback_nonclient);
11042 CHECK_CALLED(prov_callback_base_hwnd);
11043
11044 hr = SafeArrayGetElement(out_req, idx, &v);
11045 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11046
11047 hr = UiaHUiaNodeFromVariant(&v, &node2);
11048 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11049 IUnknown_AddRef((IUnknown *)node2);
11050
11051 exp_lbound[0] = exp_lbound[1] = 0;
11052 exp_elems[0] = exp_elems[1] = 1;
11053 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11054
11055 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11056 ok_method_sequence(nav_seq12, "nav_seq12");
11057
11058 SafeArrayDestroy(out_req);
11059 SysFreeString(tree_struct);
11060
11061 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11062 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
11063
11064 Provider_child2.hwnd = NULL;
11065 Provider_child2.ignore_hwnd_prop = FALSE;
11067
11068 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11069 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11070 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
11071 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
11072
11073 /* Create a node with Provider_nc as the parent link. */
11074 Provider.parent = Provider_hwnd.parent = NULL;
11075 Provider_nc.parent = &Provider2.IRawElementProviderFragment_iface;
11077 Provider2.hwnd = NULL;
11078
11079 node = (void *)0xdeadbeef;
11080 /* Only sent on Win7. */
11081 SET_EXPECT(winproc_GETOBJECT_CLIENT);
11082 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
11083 SET_EXPECT(prov_callback_base_hwnd);
11084 SET_EXPECT(prov_callback_nonclient);
11086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11087 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11088 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
11089 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
11090 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
11091 CHECK_CALLED(prov_callback_base_hwnd);
11092 CHECK_CALLED(prov_callback_nonclient);
11093 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
11094
11095 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
11096 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11098 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", FALSE);
11099 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", TRUE);
11100 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
11101 VariantClear(&v);
11102
11103 ok_method_sequence(nav_seq13, "nav_seq13");
11104
11105 /* Navigate to Provider2, parent of Provider_nc. */
11106 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11107 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider2", TRUE);
11109 tree_struct = NULL;
11110 out_req = NULL;
11111 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
11112 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11113 ok(!!out_req, "out_req == NULL\n");
11114 ok(!!tree_struct, "tree_struct == NULL\n");
11115 ok(Provider2.ref == 2, "Unexpected refcnt %ld\n", Provider2.ref);
11116
11117 exp_lbound[0] = exp_lbound[1] = 0;
11118 exp_elems[0] = exp_elems[1] = 1;
11119 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11120
11121 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11122
11123 SafeArrayDestroy(out_req);
11124 SysFreeString(tree_struct);
11125 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
11126 ok_method_sequence(nav_seq14, "nav_seq14");
11127
11128 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11129 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
11130 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
11131 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
11132
11133 Provider_hwnd_child.hwnd = NULL;
11134 Provider_hwnd_child.prov_opts = ProviderOptions_ServerSideProvider;
11135 Provider.ignore_hwnd_prop = Provider_nc.ignore_hwnd_prop = FALSE;
11137 prov_root = NULL;
11139
11140 /*
11141 * Conditional navigation for conditions other than ConditionType_True.
11142 */
11146 provider_add_child(&Provider_child2, &Provider_child2_child);
11147 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
11148
11149 hr = UiaNodeFromProvider(&Provider_child2_child_child.IRawElementProviderSimple_iface, &node);
11150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11151 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
11152
11153 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
11154 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11156 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child2_child_child", TRUE);
11157 VariantClear(&v);
11158
11159 ok_method_sequence(nav_seq15, "nav_seq15");
11160
11161 /*
11162 * Navigate from Provider_child2_child_child to a parent that has
11163 * UIA_IsControlElementPropertyId set to FALSE.
11164 */
11165 V_VT(&v) = VT_BOOL;
11166 V_BOOL(&v) = VARIANT_FALSE;
11167 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
11168
11169 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11170 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11172 tree_struct = NULL;
11173 out_req = NULL;
11174 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&prop_cond, &cache_req, &out_req, &tree_struct);
11175 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11176 ok(!out_req, "out_req != NULL\n");
11177 ok(!tree_struct, "tree_struct != NULL\n");
11178 ok_method_sequence(nav_seq16, "nav_seq16");
11179
11180 /* Provider will now return FALSE for UIA_IsControlElementPropertyId. */
11181 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
11182 set_provider_prop_override(&Provider, &prop_override, 1);
11183
11184 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
11185 init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
11186 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11188 tree_struct = NULL;
11189 out_req = NULL;
11190 hr = UiaNavigate(node, NavigateDirection_Parent, (struct UiaCondition *)&prop_cond, &cache_req, &out_req, &tree_struct);
11191 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11192 ok(!!out_req, "out_req == NULL\n");
11193 ok(!!tree_struct, "tree_struct == NULL\n");
11194 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11195
11196 exp_lbound[0] = exp_lbound[1] = 0;
11197 exp_elems[0] = exp_elems[1] = 1;
11198 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11199
11200 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
11201 ok_method_sequence(nav_seq17, "nav_seq17");
11202 SafeArrayDestroy(out_req);
11203 SysFreeString(tree_struct);
11204
11205 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
11206 ok(Provider_child2_child_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
11207
11210 UnregisterClassA("UiaNavigate class", NULL);
11211}
11212
11213static void set_find_params(struct UiaFindParams *params, int max_depth, BOOL find_first, BOOL exclude_root,
11214 struct UiaCondition *find_cond)
11215{
11216 params->MaxDepth = max_depth;
11217 params->FindFirst = find_first;
11218 params->ExcludeRoot = exclude_root;
11219 params->pFindCondition = find_cond;
11220}
11221
11222static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count)
11223{
11224 prov->prop_override = override;
11225 prov->prop_override_count = count;
11226}
11227
11228static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val)
11229{
11230 override->prop_id = prop_id;
11231 override->val = *val;
11232}
11233
11234static void set_provider_win_event_handler_respond_prov(struct Provider *prov, IRawElementProviderSimple *responder_prov,
11235 int responder_event)
11236{
11238
11239 data->responder_prov = responder_prov;
11240 data->responder_event = responder_event;
11241}
11242
11245{
11247
11248 data->exp_win_event_id = exp_win_event_id;
11249 data->exp_win_event_hwnd = exp_win_event_hwnd;
11250 data->exp_win_event_obj_id = exp_win_event_obj_id;
11251 data->exp_win_event_child_id = exp_win_event_child_id;
11252}
11253
11254static void set_provider_runtime_id(struct Provider *prov, int val, int val2)
11255{
11256 prov->runtime_id[0] = val;
11257 prov->runtime_id[1] = val2;
11258}
11259
11260static void set_provider_method_event_data(struct Provider *prov, HANDLE event_handle, int method_id)
11261{
11263 prov->method_call_event_method_id = method_id;
11264}
11265
11267{
11269}
11270
11271static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links)
11272{
11273 prov->prov_opts = prov_opts;
11274 prov->hwnd = hwnd;
11276 prov->expected_tid = 0;
11277 prov->runtime_id[0] = prov->runtime_id[1] = 0;
11278 prov->last_call_tid = 0;
11279 prov->ignore_hwnd_prop = FALSE;
11280 prov->override_hwnd = NULL;
11281 prov->prop_override = NULL;
11282 prov->prop_override_count = 0;
11283 memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect));
11284 memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data));
11285 memset(&prov->legacy_acc_pattern_data, 0, sizeof(prov->legacy_acc_pattern_data));
11286 prov->focus_prov = NULL;
11287 prov->embedded_frag_roots = NULL;
11288 prov->embedded_frag_roots_count = 0;
11290 memset(&prov->win_event_handler_data, 0, sizeof(prov->win_event_handler_data));
11292 prov->method_call_event_method_id = -1;
11293 if (initialize_nav_links)
11294 {
11295 prov->frag_root = NULL;
11296 prov->parent = prov->prev_sibling = prov->next_sibling = prov->first_child = prov->last_child = NULL;
11297 }
11298}
11299
11300static void initialize_provider_tree(BOOL initialize_nav_links)
11301{
11304 initialize_provider(&Provider_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11305 initialize_provider(&Provider_child_child2, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11307 initialize_provider(&Provider_child2_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11308 initialize_provider(&Provider_child2_child_child, ProviderOptions_ServerSideProvider, NULL, initialize_nav_links);
11309}
11310
11311static void provider_add_child(struct Provider *prov, struct Provider *child)
11312{
11313 if (!prov->first_child)
11314 {
11315 prov->first_child = prov->last_child = &child->IRawElementProviderFragment_iface;
11316 child->next_sibling = child->prev_sibling = NULL;
11317 }
11318 else
11319 {
11320 struct Provider *tmp = impl_from_ProviderFragment(prov->last_child);
11321
11322 tmp->next_sibling = &child->IRawElementProviderFragment_iface;
11323 child->prev_sibling = prov->last_child;
11324 prov->last_child = &child->IRawElementProviderFragment_iface;
11325 }
11326
11328 child->frag_root = prov->frag_root;
11329}
11330
11331#define test_find_sa_results( tree_structs, offsets, exp_elems, exp_tree_struct, exp_offsets ) \
11332 test_find_sa_results_( (tree_structs), (offsets), (exp_elems), (exp_tree_struct), (exp_offsets), __FILE__, __LINE__)
11333static void test_find_sa_results_(SAFEARRAY *tree_structs, SAFEARRAY *offsets, LONG exp_elems,
11334 const WCHAR **exp_tree_struct, int *exp_offset, const char *file, int line)
11335{
11336 LONG lbound, ubound, elems;
11337 HRESULT hr;
11338 VARTYPE vt;
11339 UINT dims;
11340 LONG i;
11341
11342 /* Tree structures SA. */
11343 hr = SafeArrayGetVartype(tree_structs, &vt);
11344 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11345 ok_(file, line)(vt == VT_BSTR, "Unexpected tree structures sa vt %d\n", vt);
11346 dims = SafeArrayGetDim(tree_structs);
11347 ok_(file, line)(dims == 1, "Unexpected tree structures sa dims %d\n", dims);
11348
11349 lbound = ubound = elems = 0;
11350 hr = SafeArrayGetLBound(tree_structs, 1, &lbound);
11351 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
11352 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
11353
11354 hr = SafeArrayGetUBound(tree_structs, 1, &ubound);
11355 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
11356
11357 elems = (ubound - lbound) + 1;
11358 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
11359
11360 /* Offsets SA. */
11362 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11363 ok_(file, line)(vt == VT_I4, "Unexpected offsets sa vt %d\n", vt);
11364 dims = SafeArrayGetDim(offsets);
11365 ok_(file, line)(dims == 1, "Unexpected offsets sa dims %d\n", dims);
11366
11367 lbound = ubound = elems = 0;
11368 hr = SafeArrayGetLBound(offsets, 1, &lbound);
11369 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetLBound\n", hr);
11370 ok_(file, line)(!lbound, "Unexpected lbound %ld\n", lbound);
11371
11372 hr = SafeArrayGetUBound(offsets, 1, &ubound);
11373 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx for SafeArrayGetUBound\n", hr);
11374
11375 elems = (ubound - lbound) + 1;
11376 ok_(file, line)(exp_elems == elems, "Unexpected elems %ld\n", elems);
11377
11378 for (i = 0; i < exp_elems; i++)
11379 {
11380 BSTR tree_struct;
11381 int offset;
11382
11383 hr = SafeArrayGetElement(tree_structs, &i, &tree_struct);
11384 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
11385 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct[i]), "Unexpected tree structure %s\n", debugstr_w(tree_struct));
11386 SysFreeString(tree_struct);
11387
11389 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
11390 ok_(file, line)(exp_offset[i] == offset, "Unexpected offset %d\n", offset);
11391 }
11392}
11393
11394static const struct prov_method_sequence find_seq1[] = {
11396 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11398 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11399 NODE_CREATE_SEQ(&Provider_child_child),
11400 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11401 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11402 NODE_CREATE_SEQ(&Provider_child_child2),
11403 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11404 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11405 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11407 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11409 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11410 NODE_CREATE_SEQ(&Provider_child2_child),
11411 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11412 NODE_CREATE_SEQ(&Provider_child2_child_child),
11413 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11414 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11415 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11416 NODE_CREATE_SEQ(&Provider_child2_child),
11417 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11418 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11420 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11421 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11423 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11424 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11425 /* Only done on Win10v1507 and below. */
11426 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11429 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11430 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11432 { &Provider_child2_child, FRAG_GET_RUNTIME_ID },
11433 { &Provider_child2_child_child, FRAG_GET_RUNTIME_ID },
11434 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11435 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11436 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11437 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11438 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11439 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11440 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11441 { 0 },
11442};
11443
11444static const struct prov_method_sequence find_seq2[] = {
11446 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11448 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11450 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11451 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11453 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11454 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11455 /* Only done on Win10v1507 and below. */
11456 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11460 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11461 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11462 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11463 { 0 },
11464};
11465
11466static const struct prov_method_sequence find_seq3[] = {
11468 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11470 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11472 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11473 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11475 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11476 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11477 /* Only done on Win10v1507 and below. */
11478 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11481 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11482 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11483 { 0 },
11484};
11485
11486static const struct prov_method_sequence find_seq4[] = {
11488 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11491 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11492 { 0 },
11493};
11494
11495static const struct prov_method_sequence find_seq5[] = {
11497 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11499 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11500 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11502 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11506 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11507 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11508 { 0 },
11509};
11510
11511static const struct prov_method_sequence find_seq6[] = {
11515 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11516 { 0 },
11517};
11518
11519static const struct prov_method_sequence find_seq7[] = {
11521 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11522 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11523 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11525 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11526 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11527 NODE_CREATE_SEQ(&Provider_child_child),
11528 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11529 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11530 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11531 NODE_CREATE_SEQ(&Provider_child_child2),
11532 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11533 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11534 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11535 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11537 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11539 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11540 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11541 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11542 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11544 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11545 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11546 /* Only done on Win10v1507 and below. */
11547 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11549 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11550 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11552 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11553 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11554 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11555 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11556 { 0 },
11557};
11558
11559static const struct prov_method_sequence find_seq8[] = {
11561 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11562 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11563 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11565 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11566 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11567 NODE_CREATE_SEQ(&Provider_child_child),
11568 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11569 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11570 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11571 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11572 NODE_CREATE_SEQ(&Provider_child_child2),
11573 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11574 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11575 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11576 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11577 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11580 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11582 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11583 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11585 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11586 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11590 { &Provider_child_child, FRAG_GET_RUNTIME_ID },
11591 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11593 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11594 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11595 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11596 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11597 { 0 },
11598};
11599
11600static const struct prov_method_sequence find_seq9[] = {
11601 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11602 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11603 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11604 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11605 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11606 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11608 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11610 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11611 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11613 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11614 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11615 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11616 NODE_CREATE_SEQ(&Provider_child2_child),
11617 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11618 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11619 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11620 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11622 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11623 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11625 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11627 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11628 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11629 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11630 /* Only done on Win10v1507 and below. */
11631 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11632 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11634 { &Provider_child2_child, FRAG_GET_RUNTIME_ID },
11635 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11636 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11637 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11638 { 0 },
11639};
11640
11641static const struct prov_method_sequence find_seq10[] = {
11643 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11644 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11646 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11647 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11648 NODE_CREATE_SEQ(&Provider_child_child),
11649 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11650 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11651 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11652 NODE_CREATE_SEQ(&Provider_child_child2),
11653 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11654 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11655 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11656 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11658 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11660 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11661 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11662 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11663 NODE_CREATE_SEQ(&Provider_child2_child),
11664 { &Provider_child2_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11665 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11666 NODE_CREATE_SEQ(&Provider_child2_child_child),
11667 { &Provider_child2_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11668 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11669 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11670 { &Provider_child2_child_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11671 NODE_CREATE_SEQ(&Provider_child2_child),
11672 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11673 { &Provider_child2_child, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11675 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11676 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11678 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11679 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
11680 /* Only done on Win10v1507 and below. */
11681 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
11683 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11684 { 0 },
11685};
11686
11687static const struct prov_method_sequence find_seq11[] = {
11689 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11690 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11692 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11693 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11694 NODE_CREATE_SEQ(&Provider_child_child),
11695 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11696 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
11697 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
11698 NODE_CREATE_SEQ(&Provider_child_child2),
11699 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
11700 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
11701 { &Provider_child_child2, FRAG_GET_RUNTIME_ID },
11702 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
11703 { 0 },
11704};
11705
11706static void test_UiaFind(void)
11707{
11708 struct Provider_prop_override prop_override;
11709 LONG exp_lbound[2], exp_elems[2], idx[2], i;
11710 SAFEARRAY *out_req, *offsets, *tree_structs;
11711 struct node_provider_desc exp_node_desc[7];
11712 struct UiaPropertyCondition prop_cond[2];
11713 struct UiaCacheRequest cache_req;
11714 struct UiaFindParams find_params;
11715 const WCHAR *exp_tree_struct[7];
11716 int exp_offset[7], cache_prop;
11717 HUIANODE node, node2;
11718 HRESULT hr;
11719 VARIANT v;
11720
11722
11727 provider_add_child(&Provider_child, &Provider_child_child);
11728 provider_add_child(&Provider_child, &Provider_child_child2);
11729 provider_add_child(&Provider_child2, &Provider_child2_child);
11730 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
11731
11732 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11734
11736 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11737 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
11738
11739 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
11740 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11742 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
11743 VariantClear(&v);
11744
11746
11747 /*
11748 * Maximum find depth of -1, find first is FALSE, exclude root is FALSE. A
11749 * maximum depth of -1 will search the entire tree.
11750 */
11751 out_req = offsets = tree_structs = NULL;
11752 cache_prop = UIA_RuntimeIdPropertyId;
11753 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11755 set_find_params(&find_params, -1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11756 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11757 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11758 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11759 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
11760 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
11761 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11762 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
11763 ok(Provider_child2_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child_child.ref);
11764
11765 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11766 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
11767 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child", TRUE);
11768 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child_child2", TRUE);
11769 add_provider_desc(&exp_node_desc[4], L"Main", L"Provider_child2", TRUE);
11770 add_provider_desc(&exp_node_desc[5], L"Main", L"Provider_child2_child", TRUE);
11771 add_provider_desc(&exp_node_desc[6], L"Main", L"Provider_child2_child_child", TRUE);
11772 exp_lbound[0] = exp_lbound[1] = 0;
11773 exp_elems[0] = 7;
11774 exp_elems[1] = 2;
11775
11776 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11777
11778 for (i = 0; i < exp_elems[0]; i++)
11779 {
11780 exp_offset[i] = i;
11781 exp_tree_struct[i] = L"P)";
11782 }
11783 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11784 ok_method_sequence(find_seq1, "find_seq1");
11785
11786 SafeArrayDestroy(out_req);
11788 SafeArrayDestroy(tree_structs);
11789
11790 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11792
11793 /*
11794 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
11795 */
11796 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11798 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11799 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11800 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11801 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11802 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11803
11804 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
11805 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child", TRUE);
11806 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2", TRUE);
11807 exp_lbound[0] = exp_lbound[1] = 0;
11808 exp_elems[0] = 3;
11809 exp_elems[1] = 2;
11810
11811 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11812
11813 for (i = 0; i < exp_elems[0]; i++)
11814 {
11815 exp_offset[i] = i;
11816 exp_tree_struct[i] = L"P)";
11817 }
11818
11819 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11820 ok_method_sequence(find_seq2, "find_seq2");
11821
11822 SafeArrayDestroy(out_req);
11824 SafeArrayDestroy(tree_structs);
11825
11826 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11828
11829 /*
11830 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
11831 */
11832 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11834 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
11835 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11836 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11837 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11838 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11839
11840 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11841 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
11842 exp_lbound[0] = exp_lbound[1] = 0;
11843 exp_elems[0] = 2;
11844 exp_elems[1] = 2;
11845
11846 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11847
11848 for (i = 0; i < exp_elems[0]; i++)
11849 {
11850 exp_offset[i] = i;
11851 exp_tree_struct[i] = L"P)";
11852 }
11853 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11854 ok_method_sequence(find_seq3, "find_seq3");
11855
11856 SafeArrayDestroy(out_req);
11858 SafeArrayDestroy(tree_structs);
11859
11860 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11862
11863 /*
11864 * Maximum find depth of 1, find first is TRUE, exclude root is TRUE. Will
11865 * retrieve only Provider_child.
11866 */
11867 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11869 set_find_params(&find_params, 1, TRUE, TRUE, (struct UiaCondition *)&UiaTrueCondition);
11870 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11871 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11872 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
11873
11874 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11875 exp_lbound[0] = exp_lbound[1] = 0;
11876 exp_elems[0] = 1;
11877 exp_elems[1] = 2;
11878
11879 idx[0] = idx[1] = 0;
11880 hr = SafeArrayGetElement(out_req, idx, &v);
11881 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11882
11883 /* node2 is now set as Provider_child. */
11884 hr = UiaHUiaNodeFromVariant(&v, &node2);
11885 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
11886 IUnknown_AddRef((IUnknown *)node2);
11887
11888 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11889
11890 for (i = 0; i < exp_elems[0]; i++)
11891 {
11892 exp_offset[i] = i;
11893 exp_tree_struct[i] = L"P)";
11894 }
11895 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11896 ok_method_sequence(find_seq4, "find_seq4");
11897
11898 SafeArrayDestroy(out_req);
11900 SafeArrayDestroy(tree_structs);
11901
11902 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11904
11905 /*
11906 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
11907 * Provider_child doesn't have a runtime id for UI Automation to use as a
11908 * way to check if it has navigated back to the node that began the
11909 * search, so it will get siblings.
11910 */
11911 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11913 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11914 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11915 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11916 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
11917
11918 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11919 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
11920 exp_lbound[0] = exp_lbound[1] = 0;
11921 exp_elems[0] = 2;
11922 exp_elems[1] = 2;
11923
11924 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11925
11926 for (i = 0; i < exp_elems[0]; i++)
11927 {
11928 exp_offset[i] = i;
11929 exp_tree_struct[i] = L"P)";
11930 }
11931 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11932 ok_method_sequence(find_seq5, "find_seq5");
11933
11934 SafeArrayDestroy(out_req);
11936 SafeArrayDestroy(tree_structs);
11937
11938 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11940
11941 /*
11942 * Maximum find depth of 0, find first is FALSE, exclude root is FALSE.
11943 * Provider_child has a runtime id for UI Automation to use as a
11944 * way to check if it has navigated back to the node that began the
11945 * search, so it will stop at Provider_child.
11946 */
11947 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
11948 set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, &cache_prop, 1, NULL, 0,
11950 set_find_params(&find_params, 0, FALSE, FALSE, (struct UiaCondition *)&UiaTrueCondition);
11951 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
11952 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
11953
11954 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child", TRUE);
11955 exp_lbound[0] = exp_lbound[1] = 0;
11956 exp_elems[0] = 1;
11957 exp_elems[1] = 2;
11958
11959 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
11960
11961 for (i = 0; i < exp_elems[0]; i++)
11962 {
11963 exp_offset[i] = i;
11964 exp_tree_struct[i] = L"P)";
11965 }
11966 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
11967 ok_method_sequence(find_seq6, "find_seq6");
11968
11969 SafeArrayDestroy(out_req);
11971 SafeArrayDestroy(tree_structs);
11972
11973 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
11974 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
11975
11977 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
11979
11980 /*
11981 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
11982 * The cache request view condition is used to determine tree depth, if an
11983 * element matches the cache request view condition, depth is incremented.
11984 * Since Provider_child does not, Provider_child_child, Provider_child_child2,
11985 * and Provider_child2 are all considered to be at depth 1.
11986 */
11987 V_VT(&v) = VT_BOOL;
11988 V_BOOL(&v) = VARIANT_FALSE;
11989 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
11990 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
11991
11992 V_VT(&v) = VT_BOOL;
11993 V_BOOL(&v) = VARIANT_TRUE;
11994 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
11995
11996 set_provider_prop_override(&Provider, &prop_override, 1);
11997 set_provider_prop_override(&Provider_child2, &prop_override, 1);
11998 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
11999 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12000
12001 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12003 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12004 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12005 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12006 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
12007 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12008 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12009
12010 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
12011 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
12012 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
12013 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
12014 exp_lbound[0] = exp_lbound[1] = 0;
12015 exp_elems[0] = 4;
12016 exp_elems[1] = 2;
12017
12018 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12019
12020 for (i = 0; i < exp_elems[0]; i++)
12021 {
12022 exp_offset[i] = i;
12023 exp_tree_struct[i] = L"P)";
12024 }
12025 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12026 ok_method_sequence(find_seq7, "find_seq7");
12027
12028 SafeArrayDestroy(out_req);
12030 SafeArrayDestroy(tree_structs);
12031
12033 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12035
12036 /*
12037 * Same test as before, except Provider has a runtime id.
12038 */
12039 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
12040 V_VT(&v) = VT_BOOL;
12041 V_BOOL(&v) = VARIANT_FALSE;
12042 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12043 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12044
12045 V_VT(&v) = VT_BOOL;
12046 V_BOOL(&v) = VARIANT_TRUE;
12047 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12048
12049 set_provider_prop_override(&Provider, &prop_override, 1);
12050 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12051 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
12052 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12053
12054 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12056 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12057 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12058 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12059 ok(Provider_child_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child.ref);
12060 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12061 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12062
12063 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
12064 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child_child", TRUE);
12065 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child_child2", TRUE);
12066 add_provider_desc(&exp_node_desc[3], L"Main", L"Provider_child2", TRUE);
12067 exp_lbound[0] = exp_lbound[1] = 0;
12068 exp_elems[0] = 4;
12069 exp_elems[1] = 2;
12070
12071 idx[0] = 2;
12072 idx[1] = 0;
12073 hr = SafeArrayGetElement(out_req, idx, &v);
12074 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12075
12076 /* node2 is now set as Provider_child_child2. */
12077 hr = UiaHUiaNodeFromVariant(&v, &node2);
12078 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12079 IUnknown_AddRef((IUnknown *)node2);
12080
12081 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12082
12083 for (i = 0; i < exp_elems[0]; i++)
12084 {
12085 exp_offset[i] = i;
12086 exp_tree_struct[i] = L"P)";
12087 }
12088 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12089 ok_method_sequence(find_seq8, "find_seq8");
12090
12091 SafeArrayDestroy(out_req);
12093 SafeArrayDestroy(tree_structs);
12094
12096 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12098
12099 /*
12100 * Maximum find depth of 1, find first is FALSE, exclude root is FALSE.
12101 * Starting at Provider_child_child2, find will be able to traverse the
12102 * tree in the same order as it would if we had started at the tree root
12103 * Provider, retrieving Provider_child2 as a sibling and
12104 * Provider_child2_child as a node at depth 1.
12105 */
12106 V_VT(&v) = VT_BOOL;
12107 V_BOOL(&v) = VARIANT_FALSE;
12108 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12109
12110 V_VT(&v) = VT_BOOL;
12111 V_BOOL(&v) = VARIANT_TRUE;
12112 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12113
12114 prop_override.prop_id = UIA_IsContentElementPropertyId;
12115 V_VT(&prop_override.val) = VT_BOOL;
12116 V_BOOL(&prop_override.val) = VARIANT_FALSE;
12117 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12118 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12119 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
12120
12121 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12123 set_find_params(&find_params, 1, FALSE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12124 hr = UiaFind(node2, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12125 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12126 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12127 ok(Provider_child2_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child2_child.ref);
12128
12129 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
12130 add_provider_desc(&exp_node_desc[1], L"Main", L"Provider_child2", TRUE);
12131 add_provider_desc(&exp_node_desc[2], L"Main", L"Provider_child2_child", TRUE);
12132 exp_lbound[0] = exp_lbound[1] = 0;
12133 exp_elems[0] = 3;
12134 exp_elems[1] = 2;
12135
12136 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12137
12138 for (i = 0; i < exp_elems[0]; i++)
12139 {
12140 exp_offset[i] = i;
12141 exp_tree_struct[i] = L"P)";
12142 }
12143 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12144 ok_method_sequence(find_seq9, "find_seq9");
12145
12146 SafeArrayDestroy(out_req);
12148 SafeArrayDestroy(tree_structs);
12149
12151 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12153
12154 ok(UiaNodeRelease(node2), "UiaNodeRelease returned FALSE\n");
12155 ok(Provider_child_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12156
12157 /*
12158 * Maximum find depth of 1, find first is FALSE, exclude root is TRUE.
12159 * Exclude root applies to the first node that matches the view
12160 * condition, and not the node that is passed into UiaFind(). Since
12161 * Provider doesn't match our view condition here, Provider_child will be
12162 * excluded.
12163 */
12164 V_VT(&v) = VT_BOOL;
12165 V_BOOL(&v) = VARIANT_FALSE;
12166 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12167 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12168
12169 V_VT(&v) = VT_BOOL;
12170 V_BOOL(&v) = VARIANT_TRUE;
12171 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12172
12173 set_provider_prop_override(&Provider_child, &prop_override, 1);
12174 set_provider_prop_override(&Provider_child2, &prop_override, 1);
12175
12176 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12178 set_find_params(&find_params, 1, FALSE, TRUE, (struct UiaCondition *)&prop_cond[1]);
12179 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12180 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12181 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12182
12183 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child2", TRUE);
12184 exp_lbound[0] = exp_lbound[1] = 0;
12185 exp_elems[0] = 1;
12186 exp_elems[1] = 2;
12187
12188 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12189
12190 for (i = 0; i < exp_elems[0]; i++)
12191 {
12192 exp_offset[i] = i;
12193 exp_tree_struct[i] = L"P)";
12194 }
12195 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12196
12197 ok_method_sequence(find_seq10, "find_seq10");
12198
12199 SafeArrayDestroy(out_req);
12201 SafeArrayDestroy(tree_structs);
12202
12204 for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
12206
12207 /*
12208 * Maximum find depth of -1, find first is TRUE, exclude root is FALSE.
12209 * Provider_child_child2 is the only element in the tree to match our
12210 * condition.
12211 */
12212 V_VT(&v) = VT_BOOL;
12213 V_BOOL(&v) = VARIANT_FALSE;
12214 set_property_condition(&prop_cond[0], UIA_IsContentElementPropertyId, &v, 0);
12215 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
12216
12217 V_VT(&v) = VT_BOOL;
12218 V_BOOL(&v) = VARIANT_TRUE;
12219 set_property_condition(&prop_cond[1], UIA_IsControlElementPropertyId, &v, 0);
12220
12221 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
12222
12223 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond[0], TreeScope_Element, &cache_prop, 1, NULL, 0,
12225 set_find_params(&find_params, -1, TRUE, FALSE, (struct UiaCondition *)&prop_cond[1]);
12226 hr = UiaFind(node, &find_params, &cache_req, &out_req, &offsets, &tree_structs);
12227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12228 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
12229
12230 add_provider_desc(&exp_node_desc[0], L"Main", L"Provider_child_child2", TRUE);
12231 exp_lbound[0] = exp_lbound[1] = 0;
12232 exp_elems[0] = 1;
12233 exp_elems[1] = 2;
12234
12235 test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
12236
12237 for (i = 0; i < exp_elems[0]; i++)
12238 {
12239 exp_offset[i] = i;
12240 exp_tree_struct[i] = L"P)";
12241 }
12242 test_find_sa_results(tree_structs, offsets, exp_elems[0], exp_tree_struct, exp_offset);
12243 ok_method_sequence(find_seq11, "find_seq11");
12244
12245 SafeArrayDestroy(out_req);
12247 SafeArrayDestroy(tree_structs);
12248
12250
12251 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
12252 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12253
12255}
12256
12261 const char *file;
12262 int line;
12263
12265};
12266
12268{
12270 IUnknown *proxy_iface, *unk, *unk2;
12271 HRESULT hr;
12272
12274
12275 proxy_iface = unk = unk2 = NULL;
12276 hr = CoGetInterfaceAndReleaseStream(data->marshal_stream, data->iface_iid, (void **)&proxy_iface);
12277 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12278
12279 hr = IUnknown_QueryInterface(data->iface, &IID_IUnknown, (void **)&unk);
12280 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12281 ok_(data->file, data->line)(!!unk, "unk == NULL\n");
12282
12283 hr = IUnknown_QueryInterface(proxy_iface, &IID_IUnknown, (void **)&unk2);
12284 ok_(data->file, data->line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12285 ok_(data->file, data->line)(!!unk2, "unk2 == NULL\n");
12286
12287 if (data->expect_proxy)
12288 ok_(data->file, data->line)(unk != unk2, "unk == unk2\n");
12289 else
12290 ok_(data->file, data->line)(unk == unk2, "unk != unk2\n");
12291
12292 IUnknown_Release(proxy_iface);
12293 IUnknown_Release(unk);
12294 IUnknown_Release(unk2);
12295
12297 return 0;
12298}
12299
12301 int line)
12302{
12303 struct marshal_thread_data data = { NULL, iid, expect_proxy, file, line };
12304 HANDLE thread;
12305 HRESULT hr;
12306
12307 hr = IUnknown_QueryInterface(iface, data.iface_iid, (void **)&data.iface);
12308 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12309
12310 hr = CoMarshalInterThreadInterfaceInStream(data.iface_iid, data.iface, &data.marshal_stream);
12311 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12312
12315 {
12316 MSG msg;
12317 while(PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
12318 {
12321 }
12322 }
12324
12325 IUnknown_Release(data.iface);
12326}
12327
12328static HWND create_test_hwnd(const char *class_name)
12329{
12330 WNDCLASSA cls = { 0 };
12331
12334 cls.lpszClassName = class_name;
12335 RegisterClassA(&cls);
12336
12337 return CreateWindowA(class_name, "Test window", WS_OVERLAPPEDWINDOW,
12338 0, 0, 100, 100, NULL, NULL, NULL, NULL);
12339}
12340
12341static HWND create_child_test_hwnd(const char *class_name, HWND parent)
12342{
12343 WNDCLASSA cls = { 0 };
12344
12347 cls.lpszClassName = class_name;
12348 RegisterClassA(&cls);
12349
12350 return CreateWindowA(class_name, "Test child window", WS_CHILD,
12351 0, 0, 50, 50, parent, NULL, NULL, NULL);
12352}
12353
12354static void destroy_test_hwnd(HWND hwnd, const char *class_name, const char *child_class_name)
12355{
12357 UnregisterClassA(class_name, NULL);
12358 if (child_class_name)
12359 UnregisterClassA(child_class_name, NULL);
12360}
12361
12362static IUIAutomationElement *create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd, BOOL block_hwnd_provs)
12363{
12364 IUIAutomationElement *element;
12365 HRESULT hr;
12366 VARIANT v;
12367
12368 if (block_hwnd_provs)
12369 {
12370 SET_EXPECT(prov_callback_base_hwnd);
12371 SET_EXPECT(prov_callback_nonclient);
12374 }
12375 else
12377
12380 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
12381 /* Only sent on Win7. */
12382 SET_EXPECT(winproc_GETOBJECT_CLIENT);
12383 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &element);
12384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12385 ok(!!element, "element == NULL\n");
12386 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
12387 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
12388 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
12389 if (block_hwnd_provs)
12390 {
12391 CHECK_CALLED(prov_callback_base_hwnd);
12392 CHECK_CALLED(prov_callback_nonclient);
12393 }
12394
12395 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
12396 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12397
12399 if (!block_hwnd_provs)
12400 {
12401 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
12404 }
12405 else
12406 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
12407
12408 VariantClear(&v);
12409 ok_method_sequence(node_from_hwnd2, "create_test_element");
12411
12412 return element;
12413}
12414
12415static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8)
12416{
12417 HWND hwnd = create_test_hwnd("test_ElementFromHandle class");
12418 IUIAutomationElement2 *element_2;
12419 IUIAutomationElement *element;
12420 HRESULT hr;
12421
12423 hr = IUIAutomationElement_QueryInterface(element, &IID_IUIAutomationElement2, (void **)&element_2);
12424 if (is_cui8)
12425 {
12426 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12427 ok(!!element_2, "element_2 == NULL\n");
12428 IUIAutomationElement2_Release(element_2);
12429 }
12430 else
12431 ok(hr == E_NOINTERFACE, "Unexpected hr %#lx.\n", hr);
12432
12433 /*
12434 * The IUIAutomationElement interface uses the free threaded marshaler, so
12435 * no actual proxy interface will be created.
12436 */
12437 check_interface_marshal_proxy_creation((IUnknown *)element, &IID_IUIAutomationElement, FALSE);
12438
12439 IUIAutomationElement_Release(element);
12440 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12441
12443 UnregisterClassA("test_ElementFromHandle class", NULL);
12444 prov_root = NULL;
12445}
12446
12447static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
12448{
12449 HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class");
12450 const struct uia_element_property *elem_prop;
12451 struct Provider_prop_override prop_override;
12452 IUIAutomationElement *element, *element2;
12453 IUIAutomationElementArray *element_arr;
12454 int i, len, prop_id, tmp_int;
12455 struct UiaRect uia_rect;
12456 IUnknown *unk_ns;
12457 BSTR tmp_bstr;
12458 HRESULT hr;
12459 RECT rect;
12460 VARIANT v;
12461
12466
12468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12469
12470 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ControlTypePropertyId, TRUE, NULL);
12471 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12472
12473 VariantInit(&v);
12474 V_VT(&v) = VT_BOOL;
12475 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, 1, TRUE, &v);
12476 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12477 ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
12478
12479 for (i = 0; i < ARRAY_SIZE(element_properties); i++)
12480 {
12481 elem_prop = &element_properties[i];
12482
12484 VariantClear(&v);
12485 if (!(prop_id = UiaLookupId(AutomationIdentifierType_Property, elem_prop->prop_guid)))
12486 {
12487 win_skip("No propertyId for GUID %s, skipping further tests.\n", debugstr_guid(elem_prop->prop_guid));
12488 break;
12489 }
12490
12491 winetest_push_context("Element prop_id %d", prop_id);
12492 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
12493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12494 check_uia_prop_val(prop_id, elem_prop->type, &v, TRUE);
12495
12496 /*
12497 * Some properties have special behavior if an invalid value is
12498 * returned, skip them here.
12499 */
12500 if (!elem_prop->skip_invalid)
12501 {
12503 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, prop_id, TRUE, &v);
12504 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12505 if (SUCCEEDED(hr))
12506 {
12508 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12509 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
12510 VariantClear(&v);
12511 }
12512 }
12513
12515 }
12516
12517 /* Test IUIAutomationElementArray interface behavior. */
12519 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ControllerForPropertyId, TRUE, &v);
12520 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12521 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12522 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
12523 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
12524
12525 element_arr = NULL;
12526 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&element_arr);
12527 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12528 ok(!!element_arr, "element_arr == NULL\n");
12529 VariantClear(&v);
12530
12531 hr = IUIAutomationElementArray_get_Length(element_arr, &len);
12532 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12533 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
12534
12535 /* Invalid argument tests. */
12536 hr = IUIAutomationElementArray_get_Length(element_arr, NULL);
12537 ok(hr == E_POINTER, "Unexpected hr %#lx\n", hr);
12538
12539 element2 = (void *)0xdeadbeef;
12540 hr = IUIAutomationElementArray_GetElement(element_arr, len, &element2);
12541 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
12542 /* Pointer isn't cleared. */
12543 ok(!!element2, "element2 == NULL\n");
12544
12545 hr = IUIAutomationElementArray_GetElement(element_arr, -1, &element2);
12546 ok(hr == E_INVALIDARG, "Unexpected hr %#lx\n", hr);
12547 /* Pointer isn't cleared. */
12548 ok(!!element2, "element2 == NULL\n");
12549
12550 hr = IUIAutomationElementArray_GetElement(element_arr, 0, NULL);
12551 ok(hr == E_POINTER, "Unexpected hr %#lx\n", hr);
12552
12553 for (i = 0; i < len; i++)
12554 {
12555 element2 = NULL;
12556 hr = IUIAutomationElementArray_GetElement(element_arr, i, &element2);
12557 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
12558 ok(!!element2, "element2 == NULL\n");
12559
12560 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ControlTypePropertyId, TRUE, &v);
12561 ok(hr == S_OK, "element[%d] Unexpected hr %#lx\n", i, hr);
12562 ok(V_VT(&v) == VT_I4, "element[%d] Unexpected VT %d\n", i, V_VT(&v));
12563 ok(V_I4(&v) == uia_i4_prop_val, "element[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
12564
12565 IUIAutomationElement_Release(element2);
12566 VariantClear(&v);
12567 }
12568
12569 IUIAutomationElementArray_Release(element_arr);
12570 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
12571 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
12573
12574 /*
12575 * IUIAutomationElement_get_CurrentControlType tests. If the value
12576 * returned for UIA_ControlTypePropertyId is not a registered control
12577 * type ID, we'll get back UIA_CustomControlTypeId.
12578 */
12579 tmp_int = 0xdeadb33f;
12580 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
12581 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12582
12583 /*
12584 * Win10v1507 and below don't check whether or not the returned control
12585 * type ID is valid.
12586 */
12587 ok(tmp_int == UIA_CustomControlTypeId || broken(tmp_int == 0xdeadbeef), "Unexpected control type %#x\n", tmp_int);
12589
12591 tmp_int = 0xdeadbeef;
12592 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
12593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12594 ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
12597
12598 /* Finally, a valid control type. */
12599 V_VT(&v) = VT_I4;
12600 V_I4(&v) = UIA_HyperlinkControlTypeId;
12601 set_property_override(&prop_override, UIA_ControlTypePropertyId, &v);
12602 set_provider_prop_override(&Provider, &prop_override, 1);
12603 hr = IUIAutomationElement_get_CurrentControlType(element, &tmp_int);
12604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12605 ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
12608
12609 /*
12610 * IUIAutomationElement_get_CurrentName tests.
12611 */
12612 tmp_bstr = NULL;
12613 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
12614 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12615 ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
12616 SysFreeString(tmp_bstr);
12618
12619 tmp_bstr = NULL;
12621 hr = IUIAutomationElement_get_CurrentName(element, &tmp_bstr);
12622 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12623 ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
12624 SysFreeString(tmp_bstr);
12627
12628 /*
12629 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
12630 * It's the only version with this behavior.
12631 */
12632 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
12633 {
12634 win_skip("Skipping UIA_BoundingRectanglePropertyId tests for Win7\n");
12635 goto exit;
12636 }
12637
12638 /*
12639 * IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests.
12640 */
12641 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
12642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12643 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12644 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
12645
12646 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
12647 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12648 ok(!!element2, "element2 == NULL\n");
12649 VariantClear(&v);
12650
12651 /* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
12652 set_uia_rect(&uia_rect, 0, 0, 50, 50);
12653 Provider_child.bounds_rect = uia_rect;
12654 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
12655 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12656 check_uia_rect_val(&v, &uia_rect);
12657 VariantClear(&v);
12658 ok_method_sequence(get_bounding_rect_seq2, "get_bounding_rect_seq2");
12659
12660 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
12661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12662 check_uia_rect_rect_val(&rect, &uia_rect);
12663 memset(&rect, 0, sizeof(rect));
12664 ok_method_sequence(get_bounding_rect_seq3, "get_bounding_rect_seq3");
12665
12666 /* Empty bounding rectangle will return ReservedNotSupportedValue. */
12667 set_uia_rect(&uia_rect, 0, 0, 0, 0);
12668 Provider_child.bounds_rect = uia_rect;
12669 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
12670 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12671 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
12672 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
12673 VariantClear(&v);
12674 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
12675
12676 /* Returns an all 0 rect. */
12677 hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
12678 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12679 check_uia_rect_rect_val(&rect, &uia_rect);
12680 ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
12681
12682 IUIAutomationElement_Release(element2);
12683 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
12685
12686exit:
12687 IUIAutomationElement_Release(element);
12688 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
12689
12691 UnregisterClassA("test_Element_GetPropertyValue class", NULL);
12692}
12693
12695{
12696 static const VARTYPE invalid_int_vts[] = { VT_I8, VT_INT };
12697 int in_arr[3] = { 0xdeadbeef, 0xfeedbeef, 0x1337b33f };
12698 int *out_arr, out_arr_count, i;
12699 LONG lbound, ubound;
12700 SAFEARRAY *sa;
12701 VARTYPE vt;
12702 HRESULT hr;
12703 UINT dims;
12704
12705 /*
12706 * Conversion from VT_I4 SAFEARRAY to native int array.
12707 */
12708 for (i = 0; i < ARRAY_SIZE(invalid_int_vts); i++)
12709 {
12710 vt = invalid_int_vts[i];
12711 sa = SafeArrayCreateVector(vt, 0, 2);
12712 ok(!!sa, "sa == NULL\n");
12713
12714 out_arr_count = 0xdeadbeef;
12715 out_arr = (int *)0xdeadbeef;
12716 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
12717 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12718 ok(!out_arr, "out_arr != NULL\n");
12719 ok(out_arr_count == 0xdeadbeef, "Unexpected out_arr_count %#x\n", out_arr_count);
12721 }
12722
12723 /* Only accepts VT_I4 as an input array type. */
12725 hr = IUIAutomation_IntSafeArrayToNativeArray(uia_iface, sa, &out_arr, &out_arr_count);
12726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12727 ok(out_arr_count == ARRAY_SIZE(uia_i4_arr_prop_val), "Unexpected out_arr_count %#x\n", out_arr_count);
12728 for (i = 0; i < ARRAY_SIZE(uia_i4_arr_prop_val); i++)
12729 ok(out_arr[i] == uia_i4_arr_prop_val[i], "out_arr[%d]: Expected %ld, got %d\n", i, uia_i4_arr_prop_val[i], out_arr[i]);
12730
12732 CoTaskMemFree(out_arr);
12733
12734 /*
12735 * Conversion from native int array to VT_I4 SAFEARRAY.
12736 */
12737 sa = NULL;
12738 hr = IUIAutomation_IntNativeArrayToSafeArray(uia_iface, in_arr, ARRAY_SIZE(in_arr), &sa);
12739 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12740
12742 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12743 ok(vt == VT_I4, "Unexpected vt %d.\n", vt);
12744
12745 dims = SafeArrayGetDim(sa);
12746 ok(dims == 1, "Unexpected array dims %d\n", dims);
12747
12748 hr = SafeArrayGetLBound(sa, 1, &lbound);
12749 ok(hr == S_OK, "Failed to get LBound with hr %#lx\n", hr);
12750 ok(lbound == 0, "Unexpected LBound %#lx\n", lbound);
12751
12752 hr = SafeArrayGetUBound(sa, 1, &ubound);
12753 ok(hr == S_OK, "Failed to get UBound with hr %#lx\n", hr);
12754 ok(((ubound - lbound) + 1) == ARRAY_SIZE(in_arr), "Unexpected array size %#lx\n", ((ubound - lbound) + 1));
12755
12756 for (i = 0; i < ARRAY_SIZE(in_arr); i++)
12757 {
12758 LONG idx = lbound + i;
12759 int tmp_val;
12760
12761 hr = SafeArrayGetElement(sa, &idx, &tmp_val);
12762 ok(hr == S_OK, "Failed to get element at idx %ld, hr %#lx\n", idx, hr);
12763 ok(tmp_val == in_arr[i], "Expected %d at idx %d, got %d\n", in_arr[i], i, tmp_val);
12764 }
12765
12767}
12768
12770{
12771 *ppv = NULL;
12773 *ppv = iface;
12774 else
12775 return E_NOINTERFACE;
12776
12777 return S_OK;
12778}
12779
12781{
12782 return 2;
12783}
12784
12786{
12787 return 1;
12788}
12789
12790static IUnknownVtbl ObjectVtbl = {
12794};
12796
12798{
12799 IUIAutomationPropertyCondition *prop_cond, *prop_cond2;
12800 IUIAutomationCondition *cond, **cond_arr;
12801 enum PropertyConditionFlags prop_flags;
12802 IUIAutomationBoolCondition *bool_cond;
12803 IUIAutomationNotCondition *not_cond;
12804 IUIAutomationOrCondition *or_cond;
12805 PROPERTYID prop_id;
12806 int child_count;
12807 BOOL tmp_b;
12808 HRESULT hr;
12809 VARIANT v;
12810 ULONG ref;
12811
12812 hr = IUIAutomation_CreateTrueCondition(uia_iface, NULL);
12813 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12814
12815 cond = NULL;
12816 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
12817 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12818 ok(!!cond, "cond == NULL\n");
12819
12820 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
12821 IUIAutomationCondition_Release(cond);
12822 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12823 ok(!!bool_cond, "bool_cond == NULL\n");
12824
12825 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, NULL);
12826 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12827
12828 tmp_b = FALSE;
12829 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
12830 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12831 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
12832 IUIAutomationBoolCondition_Release(bool_cond);
12833
12834 hr = IUIAutomation_CreateFalseCondition(uia_iface, NULL);
12835 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12836
12837 cond = NULL;
12838 hr = IUIAutomation_CreateFalseCondition(uia_iface, &cond);
12839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12840 ok(!!cond, "cond == NULL\n");
12841
12842 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
12843 IUIAutomationCondition_Release(cond);
12844 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12845 ok(!!bool_cond, "bool_cond == NULL\n");
12846
12847 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, NULL);
12848 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12849
12850 tmp_b = TRUE;
12851 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
12852 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12853 ok(tmp_b == FALSE, "tmp_b != FALSE\n");
12854 IUIAutomationBoolCondition_Release(bool_cond);
12855
12856 /*
12857 * IUIAutomationPropertyCondition tests.
12858 */
12859 cond = (void *)0xdeadbeef;
12860 VariantInit(&v);
12861 /* Invalid property ID. */
12862 hr = IUIAutomation_CreatePropertyCondition(uia_iface, 0, v, &cond);
12863 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12864 ok(!cond, "cond != NULL\n");
12865
12866 /* Invalid variant type for property ID. */
12867 cond = (void *)0xdeadbeef;
12868 VariantInit(&v);
12869 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond);
12870 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
12871 ok(!cond, "cond != NULL\n");
12872
12873 /* NULL Condition argument. */
12874 V_VT(&v) = VT_I4 | VT_ARRAY;
12876 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, NULL);
12877 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12878
12879 /* Finally, create property condition interface. */
12880 cond = NULL;
12881 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_RuntimeIdPropertyId, v, &cond);
12882 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12883 ok(!!cond, "cond == NULL\n");
12884
12885 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
12886 IUIAutomationCondition_Release(cond);
12887 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12888 ok(!!prop_cond, "prop_cond == NULL\n");
12889
12890 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, NULL);
12891 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12892
12893 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
12894 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12895 ok(prop_id == UIA_RuntimeIdPropertyId, "Unexpected prop_id %d.\n", prop_id);
12896
12897 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, NULL);
12898 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12899
12900 VariantClear(&v);
12901 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
12902 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12903 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d.\n", V_VT(&v));
12904 ok(!!V_ARRAY(&v), "V_ARRAY(&v) == NULL\n");
12905 VariantClear(&v);
12906
12907 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, NULL);
12908 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12909
12910 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
12911 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12912 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
12913
12914 /*
12915 * IUIAutomationNotCondition tests.
12916 */
12917 cond = (void *)0xdeadbeef;
12918
12919 /*
12920 * Passing in an interface that isn't a valid IUIAutomationCondition
12921 * interface.
12922 */
12923 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)&Object, &cond);
12924 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
12925 ok(!cond, "cond != NULL\n");
12926
12927 /* NULL input argument tests. */
12928 cond = (void *)0xdeadbeef;
12929 hr = IUIAutomation_CreateNotCondition(uia_iface, NULL, &cond);
12930 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12931 ok(!cond, "cond != NULL\n");
12932
12933 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)prop_cond, NULL);
12934 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12935
12936 /* Create the IUIAutomationNotCondition with our property condition. */
12937 cond = NULL;
12938 hr = IUIAutomation_CreateNotCondition(uia_iface, (IUIAutomationCondition *)prop_cond, &cond);
12939 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12940 ok(!!cond, "cond == NULL\n");
12941
12942 /* IUIAutomationNotCondition holds a reference to the passed in condition. */
12943 ref = IUIAutomationPropertyCondition_Release(prop_cond);
12944 ok(ref == 1, "Unexpected ref %ld\n", ref);
12945
12946 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
12947 IUIAutomationCondition_Release(cond);
12948 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12949 ok(!!not_cond, "not_cond == NULL\n");
12950
12951 hr = IUIAutomationNotCondition_GetChild(not_cond, NULL);
12952 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12953
12954 cond = NULL;
12955 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
12956 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12957 ok(iface_cmp((IUnknown *)cond, (IUnknown *)prop_cond), "cond != prop_cond\n");
12958 IUIAutomationCondition_Release(cond);
12959
12960 IUIAutomationNotCondition_Release(not_cond);
12961
12962 /*
12963 * IUIAutomationOrCondition tests.
12964 */
12965 cond = NULL;
12966 VariantInit(&v);
12967 V_VT(&v) = VT_BOOL;
12968 V_BOOL(&v) = VARIANT_FALSE;
12969 /* Create two condition interfaces to use for our IUIAutomationOrCondition. */
12970 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsControlElementPropertyId, v, &cond);
12971 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12972 ok(!!cond, "cond == NULL\n");
12973
12974 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
12975 IUIAutomationCondition_Release(cond);
12976 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12977 ok(!!prop_cond, "prop_cond == NULL\n");
12978
12979 cond = NULL;
12980 VariantInit(&v);
12981 V_VT(&v) = VT_BOOL;
12982 V_BOOL(&v) = VARIANT_TRUE;
12983 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &cond);
12984 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12985 ok(!!cond, "cond == NULL\n");
12986
12987 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond2);
12988 IUIAutomationCondition_Release(cond);
12989 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
12990 ok(!!prop_cond2, "prop_cond2 == NULL\n");
12991
12992 /* NULL input argument tests. */
12993 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
12994 (IUIAutomationCondition *)prop_cond2, NULL);
12995 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
12996
12997 cond = (void *)0xdeadbeef;
12998 hr = IUIAutomation_CreateOrCondition(uia_iface, NULL, (IUIAutomationCondition *)prop_cond2, &cond);
12999 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13000 ok(!cond, "cond != NULL\n");
13001
13002 cond = (void *)0xdeadbeef;
13003 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond, NULL, &cond);
13004 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13005 ok(!cond, "cond != NULL\n");
13006
13007 /* One of the IUIAutomationCondition interfaces are invalid. */
13008 cond = (void *)0xdeadbeef;
13009 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
13010 (IUIAutomationCondition *)&Object, &cond);
13011 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
13012 ok(!cond, "cond != NULL\n");
13013
13014 cond = NULL;
13015 hr = IUIAutomation_CreateOrCondition(uia_iface, (IUIAutomationCondition *)prop_cond,
13016 (IUIAutomationCondition *)prop_cond2, &cond);
13017 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13018 ok(!!cond, "cond == NULL\n");
13019
13020 or_cond = NULL;
13021 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationOrCondition, (void **)&or_cond);
13022 IUIAutomationCondition_Release(cond);
13023 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13024 ok(!!or_cond, "or_cond == NULL\n");
13025
13026 /* References held to both passed in interfaces. */
13027 ref = IUIAutomationPropertyCondition_Release(prop_cond);
13028 ok(ref == 1, "Unexpected ref %ld\n", ref);
13029
13030 ref = IUIAutomationPropertyCondition_Release(prop_cond2);
13031 ok(ref == 1, "Unexpected ref %ld\n", ref);
13032
13033 hr = IUIAutomationOrCondition_get_ChildCount(or_cond, NULL);
13034 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13035
13036 child_count = 0;
13037 hr = IUIAutomationOrCondition_get_ChildCount(or_cond, &child_count);
13038 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13039 ok(child_count == 2, "Unexpected child_count %d.\n", child_count);
13040
13041 child_count = 10;
13042 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, NULL, &child_count);
13043 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13044 ok(child_count == 10, "Unexpected child_count %d.\n", child_count);
13045
13046 cond_arr = (void *)0xdeadbeef;
13047 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, &cond_arr, NULL);
13048 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13049 ok(!cond_arr, "cond_arr != NULL\n");
13050
13051 child_count = 0;
13052 cond_arr = NULL;
13053 hr = IUIAutomationOrCondition_GetChildrenAsNativeArray(or_cond, &cond_arr, &child_count);
13054 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13055 ok(child_count == 2, "Unexpected child_count %d.\n", child_count);
13056 ok(!!cond_arr, "cond_arr == NULL\n");
13057
13058 ok(iface_cmp((IUnknown *)cond_arr[0], (IUnknown *)prop_cond), "cond_arr[0] != prop_cond\n");
13059 IUIAutomationCondition_Release(cond_arr[0]);
13060
13061 ok(iface_cmp((IUnknown *)cond_arr[1], (IUnknown *)prop_cond2), "cond_arr[1] != prop_cond2\n");
13062 IUIAutomationCondition_Release(cond_arr[1]);
13063
13064 CoTaskMemFree(cond_arr);
13065 IUIAutomationOrCondition_Release(or_cond);
13066
13067 /*
13068 * Condition used to get the control TreeView. Equivalent to:
13069 * if (!(UIA_IsControlElementPropertyId == VARIANT_FALSE))
13070 */
13071 hr = IUIAutomation_get_ControlViewCondition(uia_iface, NULL);
13072 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13073
13074 cond = NULL;
13075 hr = IUIAutomation_get_ControlViewCondition(uia_iface, &cond);
13076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13077 ok(!!cond, "cond == NULL\n");
13078
13079 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
13080 IUIAutomationCondition_Release(cond);
13081 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13082 ok(!!not_cond, "not_cond == NULL\n");
13083
13084 cond = NULL;
13085 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
13086 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13087 ok(!!cond, "cond == NULL\n");
13088
13089 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
13090 IUIAutomationCondition_Release(cond);
13091 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13092 ok(!!prop_cond, "prop_cond == NULL\n");
13093
13094 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
13095 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13096 ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
13097
13098 VariantInit(&v);
13099 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
13100 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13101 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
13102 VariantClear(&v);
13103
13104 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
13105 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13106 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
13107
13108 IUIAutomationPropertyCondition_Release(prop_cond);
13109 IUIAutomationNotCondition_Release(not_cond);
13110
13111 /*
13112 * Condition used to get the raw TreeView. Equivalent to:
13113 * if (1)
13114 */
13115 hr = IUIAutomation_get_RawViewCondition(uia_iface, NULL);
13116 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13117
13118 cond = NULL;
13119 hr = IUIAutomation_get_RawViewCondition(uia_iface, &cond);
13120 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13121 ok(!!cond, "cond == NULL\n");
13122
13123 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationBoolCondition, (void **)&bool_cond);
13124 IUIAutomationCondition_Release(cond);
13125 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13126 ok(!!bool_cond, "bool_cond == NULL\n");
13127
13128 tmp_b = FALSE;
13129 hr = IUIAutomationBoolCondition_get_BooleanValue(bool_cond, &tmp_b);
13130 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13131 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
13132 IUIAutomationBoolCondition_Release(bool_cond);
13133}
13134
13136{
13137 IUIAutomationPropertyCondition *prop_cond;
13138 enum PropertyConditionFlags prop_flags;
13139 IUIAutomationCacheRequest *cache_req;
13140 enum AutomationElementMode elem_mode;
13141 IUIAutomationCondition *cond, *cond2;
13142 IUIAutomationNotCondition *not_cond;
13143 enum TreeScope scope;
13144 PROPERTYID prop_id;
13145 HRESULT hr;
13146 VARIANT v;
13147
13148 hr = IUIAutomation_CreateCacheRequest(uia_iface, NULL);
13149 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13150
13151 /*
13152 * CreateCacheRequest returns an IUIAutomationCacheRequest with the
13153 * default cache request values set.
13154 */
13155 cache_req = NULL;
13156 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13157 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13158 ok(!!cache_req, "cache_req == NULL\n");
13159
13160 /*
13161 * TreeScope tests.
13162 */
13163 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, NULL);
13164 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13165
13166 scope = 0;
13167 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
13168 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13169 ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
13170
13171 /* Set it to something invalid. */
13172 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, 0);
13173 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13174
13175 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent);
13176 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13177
13178 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors);
13179 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13180
13181 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Parent | TreeScope_Element);
13182 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13183
13184 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Ancestors | TreeScope_Element);
13185 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13186
13187 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, ~(TreeScope_Subtree | TreeScope_Parent | TreeScope_Ancestors));
13188 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13189
13190 /* Invalid values don't change anything. */
13191 scope = 0;
13192 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
13193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13194 ok(scope == TreeScope_Element, "Unexpected scope %#x\n", scope);
13195
13196 /* Now set it to TreeScope_Children. */
13197 hr = IUIAutomationCacheRequest_put_TreeScope(cache_req, TreeScope_Children);
13198 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13199
13200 scope = 0;
13201 hr = IUIAutomationCacheRequest_get_TreeScope(cache_req, &scope);
13202 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13203 todo_wine ok(scope == TreeScope_Children, "Unexpected scope %#x\n", scope);
13204
13205 /*
13206 * TreeFilter tests.
13207 */
13208 cond = NULL;
13209 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, NULL);
13210 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13211
13212 cond = NULL;
13213 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, NULL);
13214 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13215
13216 cond = NULL;
13217 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, (IUIAutomationCondition *)&Object);
13218 ok(hr == E_FAIL, "Unexpected hr %#lx.\n", hr);
13219
13220 /* Default IUIAutomationCacheRequest has the ControlView condition. */
13221 cond = NULL;
13222 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond);
13223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13224 ok(!!cond, "cond == NULL\n");
13225
13226 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationNotCondition, (void **)&not_cond);
13227 IUIAutomationCondition_Release(cond);
13228 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13229 ok(!!not_cond, "not_cond == NULL\n");
13230
13231 cond = NULL;
13232 hr = IUIAutomationNotCondition_GetChild(not_cond, &cond);
13233 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13234 ok(!!cond, "cond == NULL\n");
13235
13236 hr = IUIAutomationCondition_QueryInterface(cond, &IID_IUIAutomationPropertyCondition, (void **)&prop_cond);
13237 IUIAutomationCondition_Release(cond);
13238 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13239 ok(!!prop_cond, "prop_cond == NULL\n");
13240
13241 hr = IUIAutomationPropertyCondition_get_PropertyId(prop_cond, &prop_id);
13242 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13243 ok(prop_id == UIA_IsControlElementPropertyId, "Unexpected prop_id %d.\n", prop_id);
13244
13245 VariantInit(&v);
13246 hr = IUIAutomationPropertyCondition_get_PropertyValue(prop_cond, &v);
13247 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13248 ok(check_variant_bool(&v, FALSE), "Unexpected BOOL %#x\n", V_BOOL(&v));
13249 VariantClear(&v);
13250
13251 hr = IUIAutomationPropertyCondition_get_PropertyConditionFlags(prop_cond, &prop_flags);
13252 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13253 ok(prop_flags == PropertyConditionFlags_None, "Unexpected flags %#x.\n", prop_flags);
13254
13255 IUIAutomationPropertyCondition_Release(prop_cond);
13256 IUIAutomationNotCondition_Release(not_cond);
13257
13258 /* Set a new TreeFilter condition. */
13259 cond = NULL;
13260 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
13261 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13262 ok(!!cond, "cond == NULL\n");
13263
13264 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, cond);
13265 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13266
13267 hr = IUIAutomationCacheRequest_get_TreeFilter(cache_req, &cond2);
13268 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13269 ok(!!cond2, "cond2 == NULL\n");
13270 ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
13271 IUIAutomationCondition_Release(cond);
13272 IUIAutomationCondition_Release(cond2);
13273
13274 /*
13275 * AutomationElementMode tests.
13276 */
13277 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, NULL);
13278 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13279
13280 elem_mode = 0;
13281 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
13282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13283 ok(elem_mode == AutomationElementMode_Full, "Unexpected element mode %#x\n", elem_mode);
13284
13285 /* Invalid value - maximum is AutomationElementMode_Full, 0x01. */
13286 hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, 0x02);
13287 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13288
13289 hr = IUIAutomationCacheRequest_put_AutomationElementMode(cache_req, AutomationElementMode_None);
13290 todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13291
13292 elem_mode = 0;
13293 hr = IUIAutomationCacheRequest_get_AutomationElementMode(cache_req, &elem_mode);
13294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13295 todo_wine ok(elem_mode == AutomationElementMode_None, "Unexpected element mode %#x\n", elem_mode);
13296
13297 /*
13298 * AddProperty tests.
13299 */
13300 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_IsContentElementPropertyId);
13301 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13302
13303 /* Invalid property ID. */
13304 hr = IUIAutomationCacheRequest_AddProperty(cache_req, 1);
13305 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13306
13307 IUIAutomationCacheRequest_Release(cache_req);
13308}
13309
13313 { 0 },
13314};
13315
13318 { 0 },
13319};
13320
13323 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13324 { 0 },
13325};
13326
13333 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13334 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
13335 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ControlTypePropertyId */
13336 { 0 },
13337};
13338
13339static void test_Element_cache_methods(IUIAutomation *uia_iface)
13340{
13341 static const int cache_test_props[] = { UIA_IsKeyboardFocusablePropertyId, UIA_NamePropertyId, UIA_ControlTypePropertyId,
13342 UIA_BoundingRectanglePropertyId, UIA_HasKeyboardFocusPropertyId, };
13343 HWND hwnd = create_test_hwnd("test_Element_cache_methods class");
13344 IUIAutomationElement *element, *element2, *element3;
13345 struct Provider_prop_override prop_override;
13346 IUIAutomationCacheRequest *cache_req;
13347 IUIAutomationElementArray *elem_arr;
13348 int tmp_rt_id[2], i, len, tmp_int;
13349 IUnknown *unk_ns;
13350 BSTR tmp_bstr;
13351 BOOL tmp_bool;
13352 HRESULT hr;
13353 RECT rect;
13354 VARIANT v;
13355
13360
13362 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13363
13364 cache_req = NULL;
13365 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13366 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13367 ok(!!cache_req, "cache_req == NULL\n");
13368
13369 /*
13370 * Run these tests on Provider_child, it doesn't have an HWND so it will
13371 * get UIA_RuntimeIdPropertyId from GetRuntimeId.
13372 */
13373 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
13374 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13375 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13376 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
13377 ok_method_sequence(get_elem_cache_seq, "get_elem_cache_seq");
13378
13379 IUIAutomationElement_Release(element);
13380 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
13381
13382 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element);
13383 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13384 ok(!!element, "element == NULL\n");
13385 VariantClear(&v);
13386
13387 /*
13388 * Passing in an invalid COM interface for IUIAutomationCacheRequest will
13389 * cause an access violation on Windows.
13390 */
13391 if (0)
13392 {
13393 IUIAutomationElement_BuildUpdatedCache(element, (IUIAutomationCacheRequest *)&Object, &element2);
13394 }
13395
13396 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, NULL);
13397 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13398
13399 element2 = (void *)0xdeadbeef;
13400 hr = IUIAutomationElement_BuildUpdatedCache(element, NULL, &element2);
13401 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13402 ok(!element2, "element2 != NULL\n");
13403
13404 /*
13405 * Test cached property values. The default IUIAutomationCacheRequest
13406 * always caches UIA_RuntimeIdPropertyId.
13407 */
13408 element2 = NULL;
13409 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13410 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13411 ok(!!element2, "element2 == NULL\n");
13412 ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
13413
13414 /* RuntimeId is currently unset, so we'll get the NotSupported value. */
13415 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13416 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13417 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13418 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
13419 VariantClear(&v);
13420
13421 /* Attempting to get a cached value for a non-cached property. */
13422 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
13423 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13424 ok(V_VT(&v) == VT_EMPTY, "Unexpected vt %d\n", V_VT(&v));
13425 VariantClear(&v);
13426
13427 IUIAutomationElement_Release(element2);
13428
13429 /* RuntimeId is now set. */
13430 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
13431 element2 = NULL;
13432 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13434 ok(!!element2, "element2 == NULL\n");
13435 ok_method_sequence(get_cached_prop_val_seq, "get_cached_prop_val_seq");
13436
13437 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13438 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13439 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
13441 VariantClear(&v);
13442 IUIAutomationElement_Release(element2);
13443
13444 /*
13445 * Add UIA_IsControlElementPropertyId to the list of cached property
13446 * values.
13447 */
13448 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_IsControlElementPropertyId);
13449 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13450
13451 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadb33f;
13452 element2 = NULL;
13453 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13454 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13455 ok(!!element2, "element2 == NULL\n");
13456 ok_method_sequence(get_cached_prop_val_seq2, "get_cached_prop_val_seq2");
13457
13458 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13459 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13460 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
13462 VariantClear(&v);
13463
13464 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_IsControlElementPropertyId, TRUE, &v);
13465 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13466 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
13467 VariantClear(&v);
13468
13469 IUIAutomationElement_Release(element2);
13470 IUIAutomationCacheRequest_Release(cache_req);
13471
13472 IUIAutomationElement_Release(element);
13473 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13474
13475 /* Test cached UIAutomationType_Element properties. */
13477
13478 cache_req = NULL;
13479 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13480 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13481 ok(!!cache_req, "cache_req == NULL\n");
13482
13483 /* UIAutomationType_Element property. */
13484 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_LabeledByPropertyId);
13485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13486
13487 /* UIAutomationType_ElementArray property. */
13488 hr = IUIAutomationCacheRequest_AddProperty(cache_req, UIA_ControllerForPropertyId);
13489 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13490
13491 element2 = NULL;
13492 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13494 ok(!!element2, "element2 == NULL\n");
13495 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
13496 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13497
13498 tmp_rt_id[0] = UIA_RUNTIME_ID_PREFIX;
13499 tmp_rt_id[1] = HandleToULong(hwnd);
13500 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_RuntimeIdPropertyId, TRUE, &v);
13501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13502 ok(V_VT(&v) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v));
13503 check_runtime_id(tmp_rt_id, ARRAY_SIZE(tmp_rt_id), V_ARRAY(&v));
13504 VariantClear(&v);
13505
13506 /* Cached IUIAutomationElement. */
13507 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_LabeledByPropertyId, TRUE, &v);
13508 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13509 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13510
13511 element3 = NULL;
13512 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element3);
13513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13514 ok(!!element3, "element3 == NULL\n");
13515 VariantClear(&v);
13516
13517 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_IsControlElementPropertyId, TRUE, &v);
13518 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13519 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
13520 IUIAutomationElement_Release(element3);
13521 VariantClear(&v);
13522
13523 /* Cached IUIAutomationElementArray. */
13524 hr = IUIAutomationElement_GetCachedPropertyValueEx(element2, UIA_ControllerForPropertyId, TRUE, &v);
13525 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13526 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13527
13528 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElementArray, (void **)&elem_arr);
13529 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13530 ok(!!elem_arr, "elem_arr == NULL\n");
13531 VariantClear(&v);
13532
13533 hr = IUIAutomationElementArray_get_Length(elem_arr, &len);
13534 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13535 ok(len == ARRAY_SIZE(uia_unk_arr_prop_val), "Unexpected length %d\n", len);
13536
13537 for (i = 0; i < ARRAY_SIZE(uia_unk_arr_prop_val); i++)
13538 {
13539 hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element3);
13540 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
13541 ok(!!element3, "element3 == NULL\n");
13542
13543 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element3, UIA_ControlTypePropertyId, TRUE, &v);
13544 ok(hr == S_OK, "elem[%d] Unexpected hr %#lx\n", i, hr);
13545 ok(V_VT(&v) == VT_I4, "elem[%d] Unexpected VT %d\n", i, V_VT(&v));
13546 ok(V_I4(&v) == uia_i4_prop_val, "elem[%d] Unexpected I4 %#lx\n", i, V_I4(&v));
13547
13548 IUIAutomationElement_Release(element3);
13549 VariantClear(&v);
13550 }
13551
13552 IUIAutomationElementArray_Release(elem_arr);
13553 IUIAutomationCacheRequest_Release(cache_req);
13554
13555 /*
13556 * Reference isn't released until the element holding the cache is
13557 * destroyed.
13558 */
13559 ok(Provider_child.ref == 3, "Unexpected refcnt %ld\n", Provider_child.ref);
13560 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
13561
13562 IUIAutomationElement_Release(element2);
13563 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
13564 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
13565 ok_method_sequence(get_cached_prop_val_seq3, "get_cached_prop_val_seq3");
13566
13567 IUIAutomationElement_Release(element);
13568 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
13569 IUnknown_Release(unk_ns);
13570
13571 /*
13572 * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND.
13573 * It's the only version with this behavior.
13574 */
13575 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
13576 {
13577 win_skip("Skipping cached UIA_BoundingRectanglePropertyId tests for Win7\n");
13578 goto exit;
13579 }
13580
13581 /*
13582 * Cached property value helper function tests.
13583 */
13586
13587 /*
13588 * element has no cached values, element2 has cached values but they're
13589 * all the equivalent of VT_EMPTY, element3 has valid cached values.
13590 */
13591 cache_req = NULL;
13592 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13593 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13594 ok(!!cache_req, "cache_req == NULL\n");
13595
13596 for (i = 0; i < ARRAY_SIZE(cache_test_props); i++)
13597 {
13598 hr = IUIAutomationCacheRequest_AddProperty(cache_req, cache_test_props[i]);
13599 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13600 }
13601
13602 /* element2, invalid values for all cached properties. */
13603 element2 = NULL;
13605 set_uia_rect(&Provider.bounds_rect, 0, 0, 0, 0);
13606 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2);
13607 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13608 ok(!!element2, "element2 == NULL\n");
13610
13611 /* element3, valid values for all cached properties. */
13612 V_VT(&v) = VT_I4;
13613 V_I4(&v) = UIA_HyperlinkControlTypeId;
13614 set_property_override(&prop_override, UIA_ControlTypePropertyId, &v);
13615 set_provider_prop_override(&Provider, &prop_override, 1);
13616 set_uia_rect(&Provider.bounds_rect, 0, 0, 50, 50);
13617
13618 element3 = NULL;
13619 hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element3);
13620 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13621 ok(!!element3, "element3 == NULL\n");
13623
13624 IUIAutomationCacheRequest_Release(cache_req);
13625
13626 /* Cached UIA_HasKeyboardFocusPropertyId helper. */
13627 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, NULL);
13628 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13629
13630 tmp_bool = 0xdeadbeef;
13631 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, &tmp_bool);
13632 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13633 ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool);
13634
13635 tmp_bool = 0xdeadbeef;
13636 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element2, &tmp_bool);
13637 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13638 ok(!tmp_bool, "tmp_bool != FALSE\n");
13639
13640 tmp_bool = FALSE;
13641 hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element3, &tmp_bool);
13642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13643 ok(!!tmp_bool, "tmp_bool == FALSE\n");
13644
13645 /* Cached UIA_IsKeyboardFocusablePropertyId helper. */
13646 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, NULL);
13647 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13648
13649 tmp_bool = 0xdeadbeef;
13650 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, &tmp_bool);
13651 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13652 ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool);
13653
13654 tmp_bool = 0xdeadbeef;
13655 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element2, &tmp_bool);
13656 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13657 ok(!tmp_bool, "tmp_bool != FALSE\n");
13658
13659 tmp_bool = FALSE;
13660 hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element3, &tmp_bool);
13661 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13662 ok(!!tmp_bool, "tmp_bool == FALSE\n");
13663
13664 /* Cached UIA_NamePropertyId helper. */
13665 hr = IUIAutomationElement_get_CachedName(element, NULL);
13666 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13667
13668 tmp_bstr = (void *)0xdeadbeef;
13669 hr = IUIAutomationElement_get_CachedName(element, &tmp_bstr);
13670 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13671 ok(tmp_bstr == (void *)0xdeadbeef, "Unexpected BSTR ptr %p\n", tmp_bstr);
13672
13673 tmp_bstr = NULL;
13674 hr = IUIAutomationElement_get_CachedName(element2, &tmp_bstr);
13675 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13676 ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
13677 SysFreeString(tmp_bstr);
13678
13679 tmp_bstr = NULL;
13680 hr = IUIAutomationElement_get_CachedName(element3, &tmp_bstr);
13681 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13682 ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr));
13683 SysFreeString(tmp_bstr);
13684
13685 /* Cached UIA_ControlTypePropertyId. */
13686 hr = IUIAutomationElement_get_CachedControlType(element, NULL);
13687 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13688
13689 tmp_int = 0xdeadbeef;
13690 hr = IUIAutomationElement_get_CachedControlType(element, &tmp_int);
13691 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13692 ok(tmp_int == 0xdeadbeef, "Unexpected control type %#x\n", tmp_int);
13693
13694 tmp_int = 0;
13695 hr = IUIAutomationElement_get_CachedControlType(element2, &tmp_int);
13696 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13697 ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
13698
13699 tmp_int = 0;
13700 hr = IUIAutomationElement_get_CachedControlType(element3, &tmp_int);
13701 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13702 ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
13703
13704 /* Cached UIA_BoundingRectanglePropertyId helper. */
13705 hr = IUIAutomationElement_get_CachedBoundingRectangle(element, NULL);
13706 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
13707
13708 rect.left = rect.top = rect.bottom = rect.right = 1;
13709 hr = IUIAutomationElement_get_CachedBoundingRectangle(element, &rect);
13710 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
13711 ok(rect.left == 1, "Unexpected rect left %ld\n", rect.left);
13712 ok(rect.top == 1, "Unexpected rect top %ld\n", rect.top);
13713 ok(rect.right == 1, "Unexpected rect right %ld\n", rect.right);
13714 ok(rect.bottom == 1, "Unexpected rect bottom %ld\n", rect.bottom);
13715
13716 rect.left = rect.top = rect.bottom = rect.right = 1;
13717 hr = IUIAutomationElement_get_CachedBoundingRectangle(element2, &rect);
13718 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13719 ok(!rect.left, "Unexpected rect left %ld\n", rect.left);
13720 ok(!rect.top, "Unexpected rect top %ld\n", rect.top);
13721 ok(!rect.right, "Unexpected rect right %ld\n", rect.right);
13722 ok(!rect.bottom, "Unexpected rect bottom %ld\n", rect.bottom);
13723
13724 memset(&rect, 0, sizeof(rect));
13725 hr = IUIAutomationElement_get_CachedBoundingRectangle(element3, &rect);
13726 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13728
13729 IUIAutomationElement_Release(element3);
13730 IUIAutomationElement_Release(element2);
13731 IUIAutomationElement_Release(element);
13732
13733 set_uia_rect(&Provider.bounds_rect, 0, 0, 0, 0);
13735
13736exit:
13738 UnregisterClassA("test_Element_cache_methods class", NULL);
13739}
13740
13742 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_LabeledByPropertyId */
13744 { 0 }
13745};
13746
13747/*
13748 * Identical to find_seq7, except default cache request used by FindAll
13749 * doesn't cache UIA_RuntimeIdPropertyId.
13750 */
13753 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13754 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13755 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13757 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13758 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13759 NODE_CREATE_SEQ(&Provider_child_child),
13760 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13761 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13762 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13763 NODE_CREATE_SEQ(&Provider_child_child2),
13764 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13765 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13766 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13767 { &Provider_child_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13769 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13771 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13772 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13773 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13774 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13776 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13777 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
13778 /* Only done on Win10v1507 and below. */
13779 { &Provider, FRAG_NAVIGATE, METHOD_OPTIONAL }, /* NavigateDirection_Parent */
13780 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13781 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13782 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13783 { &Provider_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13784 { 0 },
13785};
13786
13787/*
13788 * Identical to find_seq11, except default cache request used by FindFirst
13789 * doesn't cache UIA_RuntimeIdPropertyId.
13790 */
13793 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13794 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13796 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13797 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13798 NODE_CREATE_SEQ(&Provider_child_child),
13799 { &Provider_child_child, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13800 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
13801 { &Provider_child_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
13802 NODE_CREATE_SEQ(&Provider_child_child2),
13803 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsContentElementPropertyId */
13804 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId */
13805 { &Provider_child_child2, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
13806 { 0 },
13807};
13808
13814};
13815
13816static void set_elem_desc(struct exp_elem_desc *desc, struct Provider *prov, HWND hwnd, DWORD pid, ULONG exp_refcnt,
13817 ULONG exp_release_refcnt)
13818{
13819 desc->elem_prov = prov;
13820 init_node_provider_desc(&desc->prov_desc, pid, hwnd);
13821 desc->exp_refcnt = exp_refcnt;
13822 desc->exp_release_refcnt = exp_release_refcnt;
13823}
13824
13825#define test_uia_element_arr( elem_arr, exp_elems, exp_elems_count ) \
13826 test_uia_element_arr_( (elem_arr), (exp_elems), (exp_elems_count), __FILE__, __LINE__)
13827static void test_uia_element_arr_(IUIAutomationElementArray *elem_arr, struct exp_elem_desc *exp_elems, int exp_elems_count,
13828 const char *file, int line)
13829{
13830 int i, arr_length;
13831 HRESULT hr;
13832
13833 hr = IUIAutomationElementArray_get_Length(elem_arr, &arr_length);
13834 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13835 ok_(file, line)(hr == S_OK, "IUIAutomationElementArray_get_Length: Unexpected hr %#lx\n", hr);
13836 ok_(file, line)(arr_length == exp_elems_count, "Unexpected arr_length %d.\n", arr_length);
13837
13838 for (i = 0; i < arr_length; i++)
13839 {
13840 struct exp_elem_desc *desc = &exp_elems[i];
13841 IUIAutomationElement *element;
13842 VARIANT v;
13843
13844 ok_(file, line)(desc->elem_prov->ref == desc->exp_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
13845
13846 VariantInit(&v);
13847 element = NULL;
13848 hr = IUIAutomationElementArray_GetElement(elem_arr, i, &element);
13849 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13850 ok(!!element, "element == NULL\n");
13851
13852 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
13853 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
13855 VariantClear(&v);
13856 IUIAutomationElement_Release(element);
13857 }
13858
13859 IUIAutomationElementArray_Release(elem_arr);
13860
13861 for (i = 0; i < arr_length; i++)
13862 {
13863 struct exp_elem_desc *desc = &exp_elems[i];
13864
13865 ok_(file, line)(desc->elem_prov->ref == desc->exp_release_refcnt, "elem[%d]: Unexpected refcnt %ld\n", i, exp_elems[i].elem_prov->ref);
13866 }
13867}
13868
13869static void test_Element_Find(IUIAutomation *uia_iface)
13870{
13871 HWND hwnd = create_test_hwnd("test_Element_Find class");
13872 IUIAutomationCondition *condition, *condition2;
13873 struct Provider_prop_override prop_override;
13874 struct exp_elem_desc exp_elems[7] = { 0 };
13875 IUIAutomationElement *element, *element2;
13876 IUIAutomationElementArray *element_arr;
13877 IUIAutomationCacheRequest *cache_req;
13878 HRESULT hr;
13879 VARIANT v;
13880
13882
13883 /*
13884 * The COM API has no equivalent to UiaNodeFromProvider, so the only way
13885 * we can get an initial element is with ElementFromHandle. This means our
13886 * element representing Provider will have an HWND associated, which
13887 * doesn't match our old UiaFind tests. To work around this, make Provider
13888 * return itself for the UIA_LabeledByPropertyId to get an element without
13889 * an HWND associated.
13890 */
13891 VariantInit(&v);
13892 V_VT(&v) = VT_UNKNOWN;
13894 set_property_override(&prop_override, UIA_LabeledByPropertyId, &v);
13895 set_provider_prop_override(&Provider, &prop_override, 1);
13896 Provider.hwnd = NULL;
13897
13898 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
13899 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13900 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
13901 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
13902
13903 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
13904 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13905 ok(!!element2, "element2 == NULL\n");
13906 VariantClear(&v);
13907 ok_method_sequence(element_find_start_seq, "element_find_start_seq");
13909
13910 IUIAutomationElement_Release(element);
13911 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
13912
13913 element = element2;
13914 element2 = NULL;
13915
13920 provider_add_child(&Provider_child, &Provider_child_child);
13921 provider_add_child(&Provider_child, &Provider_child_child2);
13922 provider_add_child(&Provider_child2, &Provider_child2_child);
13923 provider_add_child(&Provider_child2_child, &Provider_child2_child_child);
13924
13925 /*
13926 * In order to match the tests from test_UiaFind(), we need to create a
13927 * custom IUIAutomationCacheRequest with a ConditionType_True treeview.
13928 * The default cache request also caches the RuntimeId property.
13929 */
13930 cache_req = NULL;
13931 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
13932 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13933 ok(!!cache_req, "cache_req == NULL\n");
13934
13935 /* Set view condition to ConditionType_True. */
13936 condition = NULL;
13937 hr = IUIAutomation_CreateTrueCondition(uia_iface, &condition);
13938 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13939 ok(!!condition, "condition == NULL\n");
13940
13941 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, condition);
13942 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13943
13944 /*
13945 * Equivalent to: Maximum find depth of -1, find first is FALSE, exclude
13946 * root is FALSE.
13947 */
13948 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Subtree, condition, cache_req, &element_arr);
13949 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13950
13951 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
13952 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
13953 set_elem_desc(&exp_elems[1], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
13954 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child", TRUE);
13955 set_elem_desc(&exp_elems[2], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
13956 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child", TRUE);
13957 set_elem_desc(&exp_elems[3], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
13958 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child_child2", TRUE);
13959 set_elem_desc(&exp_elems[4], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13960 add_provider_desc(&exp_elems[4].prov_desc, L"Main", L"Provider_child2", TRUE);
13961 set_elem_desc(&exp_elems[5], &Provider_child2_child, NULL, GetCurrentProcessId(), 2, 1);
13962 add_provider_desc(&exp_elems[5].prov_desc, L"Main", L"Provider_child2_child", TRUE);
13963 set_elem_desc(&exp_elems[6], &Provider_child2_child_child, NULL, GetCurrentProcessId(), 2, 1);
13964 add_provider_desc(&exp_elems[6].prov_desc, L"Main", L"Provider_child2_child_child", TRUE);
13965
13966 test_uia_element_arr(element_arr, exp_elems, 7);
13967 ok_method_sequence(find_seq1, "find_seq1");
13968
13969 /*
13970 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
13971 * is FALSE.
13972 */
13973 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition, cache_req, &element_arr);
13974 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13975
13976 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
13977 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
13978 set_elem_desc(&exp_elems[1], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
13979 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child", TRUE);
13980 set_elem_desc(&exp_elems[2], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13981 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child2", TRUE);
13982
13983 test_uia_element_arr(element_arr, exp_elems, 3);
13984 ok_method_sequence(find_seq2, "find_seq2");
13985
13986 /*
13987 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude root
13988 * is TRUE.
13989 */
13990 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Children, condition, cache_req, &element_arr);
13991 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
13992
13993 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
13994 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
13995 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
13996 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
13997
13998 test_uia_element_arr(element_arr, exp_elems, 2);
13999 ok_method_sequence(find_seq3, "find_seq3");
14000
14001 /*
14002 * Equivalent to: Maximum find depth of 1, find first is TRUE, exclude
14003 * root is TRUE. element2 now represents Provider_child.
14004 */
14005 hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Children, condition, cache_req, &element2);
14006 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14007 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14008
14009 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14010 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14012 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
14013 VariantClear(&v);
14014
14015 ok_method_sequence(find_seq4, "find_seq4");
14016
14017 /*
14018 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
14019 * root is FALSE. Provider_child doesn't have a runtime id for UI
14020 * Automation to use as a way to check if it has navigated back to the
14021 * node that began the search, so it will get siblings.
14022 */
14023 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
14024 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14025
14026 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 2);
14027 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
14028 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14029 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
14030
14031 test_uia_element_arr(element_arr, exp_elems, 2);
14032 ok_method_sequence(find_seq5, "find_seq5");
14033
14034 /*
14035 * Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
14036 * root is FALSE. Provider_child now has a runtime ID, so we don't get
14037 * its sibling.
14038 */
14039 Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
14040 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
14041 IUIAutomationElement_Release(element2);
14042 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14043
14044 set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
14045 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
14046
14047 test_uia_element_arr(element_arr, exp_elems, 1);
14048 ok_method_sequence(find_seq6, "find_seq6");
14050
14051 IUIAutomationCondition_Release(condition);
14052
14053 /* condition is now UIA_IsContentElementPropertyId == FALSE. */
14054 condition = NULL;
14056 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &condition);
14057 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14058 ok(!!condition, "condition == NULL\n");
14059
14060 /* Set view condition to this property condition. */
14061 hr = IUIAutomationCacheRequest_put_TreeFilter(cache_req, condition);
14062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14063
14064 /* condition2 is UIA_IsControlElementPropertyId == TRUE. */
14065 condition2 = NULL;
14067 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsControlElementPropertyId, v, &condition2);
14068 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14069 ok(!!condition2, "condition2 == NULL\n");
14070
14071 /* Override UIA_IsContentElementPropertyId, set it to FALSE. */
14073 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14074 set_provider_prop_override(&Provider, &prop_override, 1);
14075 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14076 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14077 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14078
14079 /*
14080 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
14081 * root is FALSE. The cache request view condition is used to determine
14082 * tree depth, if an element matches the cache request view condition,
14083 * depth is incremented. Since Provider_child does not, Provider_child_child,
14084 * Provider_child_child2, and Provider_child2 are all considered to be at
14085 * depth 1.
14086 */
14087 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
14088 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14089
14090 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
14091 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
14092 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
14093 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
14094 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
14095 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14096 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14097 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
14098
14099 test_uia_element_arr(element_arr, exp_elems, 4);
14100 ok_method_sequence(find_seq7, "find_seq7");
14102
14103 /*
14104 * Same test as before, except now Provider has a runtime ID.
14105 */
14106 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
14108 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14109 set_provider_prop_override(&Provider, &prop_override, 1);
14110 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14111 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14112 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14113
14114 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
14115 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14116
14117 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
14118 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
14119 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
14120 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
14121 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 2);
14122 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14123 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14124 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
14125
14126 /* element2 now represents Provider_child_child2. */
14127 hr = IUIAutomationElementArray_GetElement(element_arr, 2, &element2);
14128 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14129
14130 test_uia_element_arr(element_arr, exp_elems, 4);
14131 ok_method_sequence(find_seq8, "find_seq8");
14133
14135 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14136 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14137 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14138 set_provider_prop_override(&Provider_child2_child, &prop_override, 1);
14139
14140 /*
14141 * Equivalent to: Maximum find depth of 1, find first is FALSE,
14142 * exclude root is FALSE. Starting at Provider_child_child2, find
14143 * will be able to traverse the tree in the same order as it would
14144 * if we had started at the tree root Provider, retrieving
14145 * Provider_child2 as a sibling and Provider_child2_child as a node
14146 * at depth 1.
14147 */
14148 hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element | TreeScope_Children, condition2, cache_req, &element_arr);
14149 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14150 IUIAutomationElement_Release(element2);
14151
14152 set_elem_desc(&exp_elems[0], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
14153 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14154 set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14155 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
14156 set_elem_desc(&exp_elems[2], &Provider_child2_child, NULL, GetCurrentProcessId(), 2, 1);
14157 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child2_child", TRUE);
14158
14159 test_uia_element_arr(element_arr, exp_elems, 3);
14160 ok_method_sequence(find_seq9, "find_seq9");
14162
14163 /*
14164 * Equivalent to: Maximum find depth of 1, find first is FALSE, exclude
14165 * root is TRUE. Exclude root applies to the first node that matches the
14166 * view condition, and not the node that is passed into UiaFind(). Since
14167 * Provider doesn't match our view condition here, Provider_child will be
14168 * excluded.
14169 */
14171 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14172 set_provider_prop_override(&Provider_child, &prop_override, 1);
14173 set_provider_prop_override(&Provider_child2, &prop_override, 1);
14174 hr = IUIAutomationElement_FindAllBuildCache(element, TreeScope_Children, condition2, cache_req, &element_arr);
14175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14176
14177 set_elem_desc(&exp_elems[0], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14178 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child2", TRUE);
14179
14180 test_uia_element_arr(element_arr, exp_elems, 1);
14181 ok_method_sequence(find_seq10, "find_seq10");
14183
14185 set_property_override(&prop_override, UIA_IsContentElementPropertyId, &v);
14186 set_provider_prop_override(&Provider_child_child2, &prop_override, 1);
14187
14188 /*
14189 * Equivalent to: Maximum find depth of -1, find first is TRUE, exclude
14190 * root is FALSE. Provider_child_child2 is the only element in the tree
14191 * to match our condition.
14192 */
14193 hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Subtree, condition, cache_req, &element2);
14194 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14195 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
14196
14197 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14198 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14200 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
14201 VariantClear(&v);
14202
14203 IUIAutomationElement_Release(element2);
14204 ok_method_sequence(find_seq11, "find_seq11");
14206
14207 IUIAutomationCondition_Release(condition);
14208 IUIAutomationCondition_Release(condition2);
14209 IUIAutomationCacheRequest_Release(cache_req);
14210
14211 /*
14212 * Equivalent to: Maximum find depth of 1, find first is FALSE,
14213 * exclude root is FALSE. FindAll() uses the default
14214 * IUIAutomationCacheRequest, which uses the ControlView condition
14215 * as its view condition. Since Provider_child doesn't match this view
14216 * condition, it isn't a child of Provider in this treeview. No property
14217 * values are cached by the default internal cache request, so we need to
14218 * use a separate method sequence.
14219 */
14221 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14222 set_provider_prop_override(&Provider_child, &prop_override, 1);
14223
14224 /* condition is now UIA_IsContentElementPropertyId == TRUE. */
14226 hr = IUIAutomation_CreatePropertyCondition(uia_iface, UIA_IsContentElementPropertyId, v, &condition);
14227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14228 ok(!!condition, "cond == NULL\n");
14229
14230 hr = IUIAutomationElement_FindAll(element, TreeScope_Element | TreeScope_Children, condition, &element_arr);
14231 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14232
14233 set_elem_desc(&exp_elems[0], &Provider, NULL, GetCurrentProcessId(), 2, 2);
14234 add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider", TRUE);
14235 set_elem_desc(&exp_elems[1], &Provider_child_child, NULL, GetCurrentProcessId(), 2, 1);
14236 add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child_child", TRUE);
14237 set_elem_desc(&exp_elems[2], &Provider_child_child2, NULL, GetCurrentProcessId(), 2, 1);
14238 add_provider_desc(&exp_elems[2].prov_desc, L"Main", L"Provider_child_child2", TRUE);
14239 set_elem_desc(&exp_elems[3], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
14240 add_provider_desc(&exp_elems[3].prov_desc, L"Main", L"Provider_child2", TRUE);
14241
14242 test_uia_element_arr(element_arr, exp_elems, 4);
14243 ok_method_sequence(element_find_seq1, "element_find_seq1");
14245
14246 /*
14247 * Equivalent to: Maximum find depth of -1, find first is TRUE,
14248 * exclude root is FALSE. FindFirst() also uses the default cache request.
14249 * Provider_child_child2 will be the first provider in the tree to match
14250 * this view condition, so it will be returned.
14251 */
14253 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14254 set_provider_prop_override(&Provider, &prop_override, 1);
14255 set_provider_prop_override(&Provider_child, &prop_override, 1);
14256 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14257
14258 hr = IUIAutomationElement_FindFirst(element, TreeScope_Subtree, condition, &element2);
14259 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14260 ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
14261
14262 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14263 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14265 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
14266 VariantClear(&v);
14267
14268 IUIAutomationElement_Release(element2);
14269 ok_method_sequence(element_find_seq2, "element_find_seq2");
14271
14272 IUIAutomationCondition_Release(condition);
14273 IUIAutomationElement_Release(element);
14274 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14275
14277 UnregisterClassA("test_Element_Find class", NULL);
14278}
14279
14280static const struct prov_method_sequence treewalker_seq1[] = {
14281 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
14283 { 0 }
14284};
14285
14286static const struct prov_method_sequence treewalker_seq2[] = {
14287 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_FirstChild */
14290 { 0 }
14291};
14292
14293static const struct prov_method_sequence treewalker_seq3[] = {
14294 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
14296 { 0 }
14297};
14298
14299static const struct prov_method_sequence treewalker_seq4[] = {
14300 { &Provider, FRAG_NAVIGATE }, /* NavigateDirection_LastChild */
14303 { 0 }
14304};
14305
14306static const struct prov_method_sequence treewalker_seq5[] = {
14307 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
14309 { 0 }
14310};
14311
14312static const struct prov_method_sequence treewalker_seq6[] = {
14313 { &Provider_child, FRAG_NAVIGATE }, /* NavigateDirection_NextSibling */
14316 { 0 }
14317};
14318
14319static const struct prov_method_sequence treewalker_seq7[] = {
14320 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
14322 { 0 }
14323};
14324
14325static const struct prov_method_sequence treewalker_seq8[] = {
14326 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_PreviousSibling */
14329 { 0 }
14330};
14331
14332static const struct prov_method_sequence treewalker_seq9[] = {
14333 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
14335 { 0 }
14336};
14337
14339 { &Provider_child2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
14342 { 0 }
14343};
14344
14346{
14347 HWND hwnd = create_test_hwnd("test_CUIAutomation_TreeWalker_ifaces class");
14348 IUIAutomationElement *element, *element2, *element3;
14349 IUIAutomationCacheRequest *cache_req;
14350 IUIAutomationCondition *cond, *cond2;
14351 IUIAutomationTreeWalker *walker;
14352 HRESULT hr;
14353
14354 cond = NULL;
14355 hr = IUIAutomation_CreateTrueCondition(uia_iface, &cond);
14356 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14357 ok(!!cond, "cond == NULL\n");
14358
14359 /* NULL input argument tests. */
14360 walker = (void *)0xdeadbeef;
14361 hr = IUIAutomation_CreateTreeWalker(uia_iface, NULL, &walker);
14362 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14363 ok(!walker, "walker != NULL\n");
14364
14365 hr = IUIAutomation_CreateTreeWalker(uia_iface, cond, NULL);
14366 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14367
14368 /* Actually create TreeWalker. */
14369 walker = NULL;
14370 hr = IUIAutomation_CreateTreeWalker(uia_iface, cond, &walker);
14371 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14372 ok(!!walker, "walker == NULL\n");
14373
14374 hr = IUIAutomationTreeWalker_get_Condition(walker, &cond2);
14375 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14376 ok(!!cond2, "cond2 == NULL\n");
14377
14378 ok(iface_cmp((IUnknown *)cond, (IUnknown *)cond2), "cond != cond2\n");
14379 IUIAutomationCondition_Release(cond);
14380 IUIAutomationCondition_Release(cond2);
14381
14382 cache_req = NULL;
14383 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
14384 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14385 ok(!!cache_req, "cache_req == NULL\n");
14386
14393
14394 /* NULL input argument tests. */
14395 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, element, NULL);
14396 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14397
14398 element2 = (void *)0xdeadbeef;
14399 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, NULL, &element2);
14400 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14401 ok(!element2, "element2 != NULL\n");
14402
14403 /* NavigateDirection_FirstChild. */
14404 element2 = NULL;
14405 hr = IUIAutomationTreeWalker_GetFirstChildElement(walker, element, &element2);
14406 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14407 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14408 ok(!!element2, "element2 == NULL\n");
14409 ok_method_sequence(treewalker_seq1, "treewalker_seq1");
14410
14411 IUIAutomationElement_Release(element2);
14412 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14413
14414 element2 = NULL;
14415 hr = IUIAutomationTreeWalker_GetFirstChildElementBuildCache(walker, element, cache_req, &element2);
14416 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14417 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14418 ok(!!element2, "element2 == NULL\n");
14419 ok_method_sequence(treewalker_seq2, "treewalker_seq2");
14420
14421 /* NavigateDirection_NextSibling. */
14422 element3 = NULL;
14423 hr = IUIAutomationTreeWalker_GetNextSiblingElement(walker, element2, &element3);
14424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14425 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14426 ok(!!element3, "element3 == NULL\n");
14427 ok_method_sequence(treewalker_seq5, "treewalker_seq5");
14428 IUIAutomationElement_Release(element3);
14429 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14430
14431 element3 = NULL;
14432 hr = IUIAutomationTreeWalker_GetNextSiblingElementBuildCache(walker, element2, cache_req, &element3);
14433 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14434 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14435 ok(!!element3, "element3 == NULL\n");
14436 ok_method_sequence(treewalker_seq6, "treewalker_seq6");
14437 IUIAutomationElement_Release(element3);
14438 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14439
14440 IUIAutomationElement_Release(element2);
14441 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14442
14443 /* NavigateDirection_LastChild. */
14444 element2 = NULL;
14445 hr = IUIAutomationTreeWalker_GetLastChildElement(walker, element, &element2);
14446 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14447 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14448 ok(!!element2, "element2 == NULL\n");
14449 ok_method_sequence(treewalker_seq3, "treewalker_seq3");
14450
14451 IUIAutomationElement_Release(element2);
14452 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14453
14454 element2 = NULL;
14455 hr = IUIAutomationTreeWalker_GetLastChildElementBuildCache(walker, element, cache_req, &element2);
14456 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14457 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
14458 ok(!!element2, "element2 == NULL\n");
14459 ok_method_sequence(treewalker_seq4, "treewalker_seq4");
14460
14461 /* NavigateDirection_PreviousSibling. */
14462 element3 = NULL;
14463 hr = IUIAutomationTreeWalker_GetPreviousSiblingElement(walker, element2, &element3);
14464 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14465 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14466 ok(!!element3, "element3 == NULL\n");
14467 ok_method_sequence(treewalker_seq7, "treewalker_seq7");
14468 IUIAutomationElement_Release(element3);
14469 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14470
14471 element3 = NULL;
14472 hr = IUIAutomationTreeWalker_GetPreviousSiblingElementBuildCache(walker, element2, cache_req, &element3);
14473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14474 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
14475 ok(!!element3, "element3 == NULL\n");
14476 ok_method_sequence(treewalker_seq8, "treewalker_seq8");
14477 IUIAutomationElement_Release(element3);
14478 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
14479
14480 /* NavigateDirection_Parent. */
14481 element3 = NULL;
14482 Provider.hwnd = NULL;
14483 hr = IUIAutomationTreeWalker_GetParentElement(walker, element2, &element3);
14484 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14485 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
14486 ok(!!element3, "element3 == NULL\n");
14487 ok_method_sequence(treewalker_seq9, "treewalker_seq9");
14488 IUIAutomationElement_Release(element3);
14489 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14490
14491 element3 = NULL;
14492 hr = IUIAutomationTreeWalker_GetParentElementBuildCache(walker, element2, cache_req, &element3);
14493 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14494 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
14495 ok(!!element3, "element3 == NULL\n");
14496 ok_method_sequence(treewalker_seq10, "treewalker_seq10");
14497 IUIAutomationElement_Release(element3);
14498 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
14499
14500 IUIAutomationElement_Release(element2);
14501 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
14502
14503 IUIAutomationElement_Release(element);
14504 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
14505
14506 IUIAutomationCacheRequest_Release(cache_req);
14507 IUIAutomationTreeWalker_Release(walker);
14508
14510 UnregisterClassA("test_CUIAutomation_TreeWalker_ifaces class", NULL);
14511}
14512
14514 struct Provider *hwnd_prov, HWND hwnd)
14515{
14516 if (proxy_prov)
14517 {
14519 proxy_prov->frag_root = &proxy_prov->IRawElementProviderFragmentRoot_iface;
14520 proxy_prov->ignore_hwnd_prop = TRUE;
14521 }
14522
14525 hwnd_prov->frag_root = &hwnd_prov->IRawElementProviderFragmentRoot_iface;
14526 nc_prov->frag_root = &nc_prov->IRawElementProviderFragmentRoot_iface;
14527 nc_prov->ignore_hwnd_prop = TRUE;
14528}
14529
14530static void test_GetRootElement(IUIAutomation *uia_iface)
14531{
14532 IUIAutomationElement *element;
14533 HRESULT hr;
14534 VARIANT v;
14535
14536 hr = IUIAutomation_GetRootElement(uia_iface, NULL);
14537 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14538
14540
14542 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14543 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14544 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14545
14546 /* Retrieve an element representing the desktop HWND. */
14548 SET_EXPECT(prov_callback_base_hwnd);
14549 SET_EXPECT(prov_callback_nonclient);
14550 SET_EXPECT(prov_callback_proxy);
14551 hr = IUIAutomation_GetRootElement(uia_iface, &element);
14552 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14553 ok(!!element, "Node == NULL.\n");
14554 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
14555 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
14556 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
14557 CHECK_CALLED(prov_callback_base_hwnd);
14558 CHECK_CALLED(prov_callback_nonclient);
14559 CHECK_CALLED(prov_callback_proxy);
14560
14561 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14562 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
14564 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
14565 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
14566 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
14567 VariantClear(&v);
14568
14569 IUIAutomationElement_Release(element);
14570 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
14571 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
14572 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
14573
14576 TRUE);
14579
14582}
14583
14584#define test_get_focused_elem( uia_iface, cache_req, exp_hr, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, \
14585 nc_cback_count, win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, \
14586 base_hwnd_cback_todo, nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo ) \
14587 test_get_focused_elem_( (uia_iface), (cache_req), (exp_hr), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), \
14588 (nc_cback_count), (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), \
14589 (base_hwnd_cback_todo), (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
14590static void test_get_focused_elem_(IUIAutomation *uia_iface, IUIAutomationCacheRequest *cache_req, HRESULT exp_hr,
14591 struct node_provider_desc *exp_node_desc, int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
14592 int win_get_obj_count, int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo,
14593 BOOL nc_cback_todo, BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
14594{
14595 IUIAutomationElement *element = NULL;
14596 HRESULT hr;
14597 VARIANT v;
14598
14599 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14600 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
14601 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
14602 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
14603 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
14604 if (cache_req)
14605 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, &element);
14606 else
14607 hr = IUIAutomation_GetFocusedElement(uia_iface, &element);
14608 ok_(file, line)(hr == exp_hr, "Unexpected hr %#lx.\n", hr);
14609 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14610 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
14611 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
14612 todo_wine_if(win_get_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
14613 todo_wine_if(child_win_get_obj_todo) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
14614
14615 if (exp_node_desc->prov_count)
14616 {
14617 ok_(file, line)(!!element, "element == NULL\n");
14618
14619 hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14620 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14621 test_node_provider_desc_(exp_node_desc, V_BSTR(&v), file, line);
14622 VariantClear(&v);
14623
14624 IUIAutomationElement_Release(element);
14625 }
14626 else
14627 ok_(file, line)(!element, "element != NULL\n");
14628}
14629
14630static void test_GetFocusedElement(IUIAutomation *uia_iface)
14631{
14632 struct Provider_prop_override prop_override;
14633 struct node_provider_desc exp_node_desc;
14634 IUIAutomationCacheRequest *cache_req;
14635 IUIAutomationElement *element;
14636 HWND hwnd, hwnd_child;
14637 HRESULT hr;
14638 VARIANT v;
14639
14640 hwnd = create_test_hwnd("test_GetFocusedElement class");
14641 hwnd_child = create_child_test_hwnd("test_GetFocusedElement child class", hwnd);
14643
14644 cache_req = NULL;
14645 hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req);
14646 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
14647 ok(!!cache_req, "cache_req == NULL\n");
14648
14649 /*
14650 * Set clientside providers for our test windows and the desktop. Same
14651 * tests as UiaNodeFromFocus, just with COM methods.
14652 */
14654 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
14655 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
14656 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
14657
14658 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
14663
14664 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, hwnd_child);
14666 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
14667 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
14668 Provider2.ignore_hwnd_prop = TRUE;
14669
14670 /* NULL input argument tests. */
14671 hr = IUIAutomation_GetFocusedElement(uia_iface, NULL);
14672 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14673
14674 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, cache_req, NULL);
14675 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14676
14677 element = (void *)0xdeadbeef;
14678 hr = IUIAutomation_GetFocusedElementBuildCache(uia_iface, NULL, &element);
14679 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
14680 ok(!element, "element != NULL\n");
14681
14682 /*
14683 * None of the providers for the desktop node return a provider from
14684 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
14685 * desktop node.
14686 */
14689 add_provider_desc(&exp_node_desc, L"Main", L"Provider_proxy", TRUE);
14690 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc", FALSE);
14691 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd", FALSE);
14692
14693 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14694 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14695
14696 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
14697 Provider_hwnd.focus_prov = &Provider_hwnd2.IRawElementProviderFragment_iface;
14698
14700 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
14701 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
14702 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
14703
14704 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14705 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14706
14707 /*
14708 * Provider_proxy returns Provider from GetFocus. The provider that
14709 * creates the node will not have GetFocus called on it to avoid returning
14710 * the same provider twice. Similarly, on nodes other than the desktop
14711 * node, the HWND provider will not have GetFocus called on it.
14712 */
14713 Provider_hwnd.focus_prov = NULL;
14715 Provider.focus_prov = Provider_hwnd2.focus_prov = &Provider2.IRawElementProviderFragment_iface;
14716
14718 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
14719 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
14720 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
14721
14722 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14723 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14724
14725 /*
14726 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
14727 * Provider2, Provider_nc3 returns Provider_child.
14728 */
14730 Provider_proxy.focus_prov = Provider_hwnd.focus_prov = NULL;
14731 Provider_nc.focus_prov = &Provider_nc2.IRawElementProviderFragment_iface;
14732 Provider.focus_prov = &Provider2.IRawElementProviderFragment_iface;
14733 Provider_nc3.focus_prov = &Provider_child.IRawElementProviderFragment_iface;
14734
14736 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
14737
14738 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
14739 test_get_focused_elem(uia_iface, cache_req, S_OK, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
14740
14741 /*
14742 * Provider_proxy returns Provider_child_child from GetFocus. The focus
14743 * provider is normalized against the cache request view condition.
14744 * Provider_child_child and its ancestors don't match the cache request
14745 * view condition, so we'll get no provider.
14746 */
14750 provider_add_child(&Provider_child, &Provider_child_child);
14751 Provider_proxy.focus_prov = &Provider_child_child.IRawElementProviderFragment_iface;
14752 Provider_nc.focus_prov = Provider_hwnd.focus_prov = NULL;
14753
14755 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
14756 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
14757 set_provider_prop_override(&Provider_child, &prop_override, 1);
14758 set_provider_prop_override(&Provider, &prop_override, 1);
14759
14760 /*
14761 * GetFocusedElement returns UIA_E_ELEMENTNOTAVAILABLE when no provider
14762 * matches our view condition, GetFocusedElementBuildCache returns E_FAIL.
14763 */
14764 init_node_provider_desc(&exp_node_desc, 0, NULL);
14766 &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14768 &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
14769
14770 /* This time, Provider_child matches our view condition. */
14772
14774 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
14775
14776 test_get_focused_elem(uia_iface, NULL, S_OK, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
14777
14782
14784 IUIAutomationCacheRequest_Release(cache_req);
14787 UnregisterClassA("test_GetFocusedElement class", NULL);
14788 UnregisterClassA("test_GetFocusedElement child class", NULL);
14789}
14790
14791static void set_uia_hwnd_expects(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
14792 int win_get_uia_obj_count, int win_get_client_obj_count)
14793{
14794 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14795 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
14796 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
14797 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14798 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14799}
14800
14801static void check_uia_hwnd_expects(int proxy_cback_count, BOOL proxy_cback_todo,
14802 int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo,
14803 int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
14804{
14805 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
14806 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
14807 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
14808 todo_wine_if(win_get_uia_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14809 if (win_get_client_obj_count)
14810 todo_wine_if(win_get_client_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14811}
14812
14813static void check_uia_hwnd_expects_at_most(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count,
14814 int win_get_uia_obj_count, int win_get_client_obj_count)
14815{
14816 CHECK_CALLED_AT_MOST(prov_callback_proxy, proxy_cback_count);
14817 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, base_hwnd_cback_count);
14818 CHECK_CALLED_AT_MOST(prov_callback_nonclient, nc_cback_count);
14819 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14820 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14821}
14822
14823static void check_uia_hwnd_expects_at_least(int proxy_cback_count, BOOL proxy_cback_todo,
14824 int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo,
14825 int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
14826{
14827 todo_wine_if(proxy_cback_todo) CHECK_CALLED_AT_LEAST(prov_callback_proxy, proxy_cback_count);
14828 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_AT_LEAST(prov_callback_base_hwnd, base_hwnd_cback_count);
14829 todo_wine_if(nc_cback_todo) CHECK_CALLED_AT_LEAST(prov_callback_nonclient, nc_cback_count);
14830 todo_wine_if(win_get_uia_obj_todo) CHECK_CALLED_AT_LEAST(winproc_GETOBJECT_UiaRoot, win_get_uia_obj_count);
14831 todo_wine_if(win_get_client_obj_todo) CHECK_CALLED_AT_LEAST(winproc_GETOBJECT_CLIENT, win_get_client_obj_count);
14832}
14833
14834#define MAX_EVENT_QUEUE_COUNT 4
14840};
14841
14842static void push_event_queue_event(struct ExpectedEventQueue *queue, struct node_provider_desc *exp_node_desc)
14843{
14844 const int idx = queue->exp_event_count;
14845
14847
14848 if (exp_node_desc)
14849 {
14850 int i;
14851
14852 queue->exp_node_desc[idx] = *exp_node_desc;
14853 for (i = 0; i < exp_node_desc->prov_count; i++)
14854 {
14855 if (exp_node_desc->nested_desc[i])
14856 {
14857 queue->exp_nested_node_desc[idx] = *exp_node_desc->nested_desc[i];
14858 queue->exp_node_desc[idx].nested_desc[i] = &queue->exp_nested_node_desc[idx];
14859 break;
14860 }
14861 }
14862 }
14863 else
14864 memset(&queue->exp_node_desc[idx], 0, sizeof(queue->exp_node_desc[idx]));
14865 queue->exp_event_count++;
14866}
14867
14869{
14870 if (!queue->exp_event_count || queue->exp_event_pos >= queue->exp_event_count)
14871 {
14872 ok(0, "Failed to pop expected event from queue\n");
14873 return NULL;
14874 }
14875
14876 return &queue->exp_node_desc[queue->exp_event_pos++];
14877}
14878
14879static struct ComEventData {
14881
14886
14888{
14891
14894}
14895
14897{
14900}
14901
14902#define test_com_event_data( sender ) \
14903 test_com_event_data_( (sender), __FILE__, __LINE__)
14904static void test_com_event_data_(IUIAutomationElement *sender, const char *file, int line)
14905{
14907 HRESULT hr;
14908 VARIANT v;
14909
14911
14912 VariantInit(&v);
14913 hr = IUIAutomationElement_GetCurrentPropertyValueEx(sender, UIA_ProviderDescriptionPropertyId, TRUE, &v);
14914 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
14915 test_node_provider_desc_(exp_desc, V_BSTR(&v), file, line);
14916 VariantClear(&v);
14917
14919 if (ComEventData.event_handle && (ComEventData.exp_events.exp_event_count == ComEventData.exp_events.exp_event_pos))
14921}
14922
14923/*
14924 * IUIAutomationEventHandler.
14925 */
14927{
14928 IUIAutomationEventHandler IUIAutomationEventHandler_iface;
14931
14932static inline struct AutomationEventHandler *impl_from_AutomationEventHandler(IUIAutomationEventHandler *iface)
14933{
14935}
14936
14937static HRESULT WINAPI AutomationEventHandler_QueryInterface(IUIAutomationEventHandler *iface, REFIID riid, void **ppv)
14938{
14939 *ppv = NULL;
14940 if (IsEqualIID(riid, &IID_IUIAutomationEventHandler) || IsEqualIID(riid, &IID_IUnknown))
14941 *ppv = iface;
14942 else
14943 return E_NOINTERFACE;
14944
14945 IUIAutomationEventHandler_AddRef(iface);
14946 return S_OK;
14947}
14948
14949static ULONG WINAPI AutomationEventHandler_AddRef(IUIAutomationEventHandler* iface)
14950{
14952 return InterlockedIncrement(&handler->ref);
14953}
14954
14955static ULONG WINAPI AutomationEventHandler_Release(IUIAutomationEventHandler* iface)
14956{
14958 return InterlockedDecrement(&handler->ref);
14959}
14960
14961static HRESULT WINAPI AutomationEventHandler_HandleAutomationEvent(IUIAutomationEventHandler *iface,
14962 IUIAutomationElement *sender, EVENTID event_id)
14963{
14964 test_com_event_data(sender);
14965
14966 return S_OK;
14967}
14968
14969static const IUIAutomationEventHandlerVtbl AutomationEventHandlerVtbl = {
14974};
14975
14977{
14979 1,
14980};
14981
14982/*
14983 * IUIAutomationFocusChangedEventHandler.
14984 */
14986{
14987 IUIAutomationFocusChangedEventHandler IUIAutomationFocusChangedEventHandler_iface;
14989
14992
14993static inline struct FocusChangedHandler *impl_from_FocusChangedHandler(IUIAutomationFocusChangedEventHandler *iface)
14994{
14996}
14997
14998static HRESULT WINAPI FocusChangedHandler_QueryInterface(IUIAutomationFocusChangedEventHandler *iface,
14999 REFIID riid, void **ppv)
15000{
15001 *ppv = NULL;
15002 if (IsEqualIID(riid, &IID_IUIAutomationFocusChangedEventHandler) || IsEqualIID(riid, &IID_IUnknown))
15003 *ppv = iface;
15004 else
15005 return E_NOINTERFACE;
15006
15007 IUIAutomationFocusChangedEventHandler_AddRef(iface);
15008 return S_OK;
15009}
15010
15011static ULONG WINAPI FocusChangedHandler_AddRef(IUIAutomationFocusChangedEventHandler* iface)
15012{
15014 return InterlockedIncrement(&handler->ref);
15015}
15016
15017static ULONG WINAPI FocusChangedHandler_Release(IUIAutomationFocusChangedEventHandler* iface)
15018{
15020 return InterlockedDecrement(&handler->ref);
15021}
15022
15023static HRESULT WINAPI FocusChangedHandler_HandleFocusChangedEvent(IUIAutomationFocusChangedEventHandler *iface,
15024 IUIAutomationElement *sender)
15025{
15027
15028 if (handler->event_handler_added)
15029 test_com_event_data(sender);
15030
15031 return S_OK;
15032}
15033
15034static const IUIAutomationFocusChangedEventHandlerVtbl FocusChangedHandlerVtbl = {
15039};
15040
15042{
15044 1,
15045};
15046
15048{
15049 struct node_provider_desc exp_node_desc;
15050 HRESULT hr;
15051
15052 /*
15053 * Raise an event from inside of an MTA - the event handler proxy will be
15054 * called from the current thread because it was registered in an MTA.
15055 */
15057
15059 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15060 set_com_event_data(&exp_node_desc);
15061 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15062 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15064 ok(ComEventData.last_call_tid == GetCurrentThreadId(), "Event handler called on unexpected thread %ld\n",
15067
15068 /*
15069 * Raise an event from inside of an STA - an event handler proxy will be
15070 * created, and our handler will be invoked from another thread.
15071 */
15073
15074 set_com_event_data(&exp_node_desc);
15075 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15076 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15078 ok(ComEventData.last_call_tid != GetCurrentThreadId(), "Event handler called on unexpected thread %ld\n",
15081
15082 return 0;
15083}
15084
15085static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomationElement *elem)
15086{
15087 struct Provider_prop_override prop_override;
15088 struct node_provider_desc exp_node_desc;
15089 IUIAutomationElement *elem2;
15090 HANDLE thread;
15091 HRESULT hr;
15092 VARIANT v;
15093
15094 /*
15095 * Invalid input argument tests.
15096 */
15097 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, NULL, TreeScope_Subtree, NULL,
15099 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
15100
15101 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15102 NULL);
15103 ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
15104
15105 /*
15106 * Passing in a NULL element to this method results in an access violation
15107 * on Windows.
15108 */
15109 if (0)
15110 {
15111 IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, NULL, &AutomationEventHandler.IUIAutomationEventHandler_iface);
15112 }
15113
15114 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, elem, NULL);
15115 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15116
15117 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem,
15119 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15120
15121 /*
15122 * UIA_AutomationFocusChangedEventId can only be listened for with
15123 * AddFocusChangedEventHandler. Trying to register it on a regular event
15124 * handler returns E_INVALIDARG.
15125 */
15126 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem, TreeScope_Subtree, NULL,
15128 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
15129
15130 /* Windows 11 queries the HWND for the element when adding a new handler. */
15131 set_uia_hwnd_expects(3, 2, 2, 3, 0);
15132 /* All other event IDs are fine, only focus events are blocked. */
15133 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, 1, elem, TreeScope_Subtree, NULL,
15135 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15136 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15137 check_uia_hwnd_expects_at_most(3, 2, 2, 3, 0);
15138
15139 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, 1, elem,
15141 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15142 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15143
15144 /*
15145 * Test event raising behavior.
15146 */
15147 set_uia_hwnd_expects(3, 2, 2, 3, 0);
15148 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15150 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15151 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15152 check_uia_hwnd_expects_at_most(3, 2, 2, 3, 0);
15153
15154 /* Same behavior as HUIAEVENTs, events are matched by runtime ID. */
15156 Provider2.runtime_id[0] = 0x2a;
15158
15160 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15161 set_com_event_data(&exp_node_desc);
15162 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15163 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15165
15166 /*
15167 * If no cache request is provided by the user in
15168 * AddAutomationEventHandler, the default cache request is used. If no
15169 * elements match the view condition, the event handler isn't invoked.
15170 */
15172 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
15173 set_provider_prop_override(&Provider2, &prop_override, 1);
15174 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_LiveRegionChangedEventId);
15175 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15176
15180 {
15181 MSG msg;
15182
15183 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
15184 {
15187 }
15188 }
15190
15191 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15193 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15194 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15195
15196 VariantInit(&v);
15198 hr = IUIAutomationElement_GetCurrentPropertyValueEx(elem, UIA_LabeledByPropertyId, TRUE, &v);
15199 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15200 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
15201 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
15202
15203 hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&elem2);
15204 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15205 ok(!!elem2, "elem2 == NULL\n");
15206 VariantClear(&v);
15207
15208 /*
15209 * Register an event on an element that has no runtime ID. The only way to
15210 * remove an individual event handler is by matching a combination of
15211 * runtime-id, property ID, and event handler interface pointer. Without a
15212 * runtime-id, the only way to unregister the event handler is to call
15213 * RemoveAllEventHandlers().
15214 */
15215 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem2, TreeScope_Subtree, NULL,
15217 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15218 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15219
15220 /* No removal will occur due to a lack of a runtime ID to match. */
15221 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem2,
15223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15224 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15225
15226 hr = IUIAutomation_RemoveAllEventHandlers(uia_iface);
15227 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15228 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15229
15230 IUIAutomationElement_Release(elem2);
15231}
15232
15234{
15235 struct node_provider_desc exp_node_desc;
15236 IUIAutomationElement *elem;
15237 HRESULT hr;
15238
15240
15241 /*
15242 * FocusChangedEventHandlers are always registered on the desktop node
15243 * with a scope of the entire desktop.
15244 *
15245 * All versions of Windows query the currently focused HWND when adding a
15246 * new focus changed event handler, but behavior differs between versions:
15247 *
15248 * Win7-Win10v1507 queries for the focused provider and raises an event
15249 * while also advising of events.
15250 *
15251 * Win10v1809+ will query the focused HWND, but doesn't advise of events
15252 * or raise a focus event. Windows 11 will advise the provider of the
15253 * focused HWND of events, but not any clientside providers.
15254 */
15255 set_uia_hwnd_expects(6, 6, 6, 3, 0);
15256 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15258 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15259 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15260 check_uia_hwnd_expects_at_most(6, 6, 6, 3, 0);
15262
15263 /*
15264 * Focus changed event handlers are registered on the desktop with a scope
15265 * of all elements, so all elements match regardless of runtime ID.
15266 */
15269 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
15270 set_com_event_data(&exp_node_desc);
15271 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
15272 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15274
15275 /*
15276 * Removing the focus changed event handler creates a desktop node -
15277 * presumably to use to get a runtime ID for removal.
15278 */
15279 set_uia_hwnd_expects(1, 1, 1, 0, 0);
15280 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
15282 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15283 ok(FocusChangedHandler.ref == 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15285 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15286
15287 /*
15288 * The focus changed event handler can also be removed by called
15289 * RemoveAutomationEventHandler, which isn't documented.
15290 */
15291 set_uia_hwnd_expects(6, 6, 6, 3, 0);
15292 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15294 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15295 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15296 check_uia_hwnd_expects_at_most(6, 6, 6, 3, 0);
15298
15299 set_uia_hwnd_expects(1, 1, 1, 0, 0);
15300 hr = IUIAutomation_GetRootElement(uia_iface, &elem);
15301 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15302 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15303
15304 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_AutomationFocusChangedEventId, elem,
15306 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15307 ok(FocusChangedHandler.ref == 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15308
15309 IUIAutomationElement_Release(elem);
15310}
15311
15313{
15314 IUIAutomation *uia_iface;
15317};
15318
15320 HANDLE *handles, int method)
15321{
15322 if (!handles || method < 0)
15323 {
15327 }
15328 else
15329 {
15333 }
15334}
15335
15337{
15341}
15342
15343#define test_hwnd_providers_event_advise_added( main, hwnd, nc, event_id, todo) \
15344 test_hwnd_providers_event_advise_added_( (main), (hwnd), (nc), (event_id), (todo), __FILE__, __LINE__)
15346 int event_id, BOOL todo, const char *file, int line)
15347{
15351}
15352
15353static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface, HWND test_hwnd, HWND test_child_hwnd)
15354{
15355 GUITHREADINFO info = { .cbSize = sizeof(info) };
15356 IUIAutomationElement *elem;
15357 HANDLE method_event[4];
15358 int event_handle_count;
15359 DWORD wait_res;
15360 BOOL is_win11;
15361 HRESULT hr;
15362 int i;
15363
15364 for (i = 0; i < ARRAY_SIZE(method_event); i++)
15365 method_event[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
15366
15367 /* Only sends WM_GETOBJECT twice on Win11. */
15368 set_uia_hwnd_expects(0, 1, 1, 2, 0);
15369 hr = IUIAutomation_ElementFromHandle(uia_iface, test_hwnd, &elem);
15370 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15371 ok(!!elem, "elem == NULL\n");
15372 ok(Provider.ref >= 2, "Unexpected refcnt %ld\n", Provider.ref);
15373 ok(Provider_hwnd2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd2.ref);
15374 ok(Provider_nc2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc2.ref);
15376
15377 /*
15378 * The COM API has no equivalent to UiaEventAddWindow, which means all
15379 * event advisement has to be done by the COM API itself. It does this by
15380 * using EVENT_OBJECT_SHOW as a way to find HWNDs that need to be advised.
15381 */
15382 set_uia_hwnd_expects(0, 1, 1, 4, 0); /* Only done on Win11. */
15383 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15385 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15386 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15387 is_win11 = !!CALLED_COUNT(prov_callback_base_hwnd);
15388 check_uia_hwnd_expects_at_most(0, 1, 1, 4, 0);
15389
15390 set_provider_method_event_data(&Provider_hwnd2, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
15391 set_provider_method_event_data(&Provider_nc2, method_event[1], ADVISE_EVENTS_EVENT_ADDED);
15393 event_handle_count = 3;
15394
15395 /*
15396 * Raise EVENT_OBJECT_SHOW on a non-visible HWND. Its providers will not
15397 * be advised of events being listened for.
15398 */
15399 ok(!IsWindowVisible(test_hwnd), "Test HWND is visible\n");
15400 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15401 ok(msg_wait_for_all_events(method_event, event_handle_count, 500) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
15402
15403 /*
15404 * This fires off EVENT_OBJECT_SHOW, our providers will be advised of
15405 * events.
15406 */
15410
15411 set_uia_hwnd_expects(0, 2, 2, 6, 0); /* Only done more than one of each on Win11. */
15412 ShowWindow(test_hwnd, SW_SHOW);
15413 wait_res = msg_wait_for_all_events(method_event, event_handle_count, 3000);
15414 if ((wait_res == WAIT_TIMEOUT) && (Provider_nc2.advise_events_added_event_id && Provider_hwnd2.advise_events_added_event_id) &&
15416 {
15417 /*
15418 * Windows 7 won't advise a nested node provider from the current
15419 * process of events being listened for.
15420 */
15421 win_skip("Windows 7 only advises clientside providers of events, skipping further tests.\n");
15422 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15424 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15425 ok(AutomationEventHandler.ref == 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15426 IUIAutomationElement_Release(elem);
15427
15428 set_provider_method_event_data(&Provider_hwnd2, NULL, -1);
15429 set_provider_method_event_data(&Provider_nc2, NULL, -1);
15431 goto exit;
15432 }
15433 ok(wait_res != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15435
15436 /*
15437 * Manually fire off EVENT_OBJECT_SHOW, providers will be advised of
15438 * events being added again.
15439 */
15440 set_uia_hwnd_expects(0, 2, 2, 6, 0); /* Only done more than one of each on Win11. */
15441 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15442 ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15444
15445 /*
15446 * Providers are only advised of events being listened for if an event is
15447 * raised with an objid of OBJID_WINDOW.
15448 */
15449 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15450 ok(msg_wait_for_all_events(method_event, event_handle_count, 500) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
15451
15452 set_provider_method_event_data(&Provider_hwnd2, NULL, -1);
15453 set_provider_method_event_data(&Provider_nc2, NULL, -1);
15455
15456 /*
15457 * Show our child HWND. Navigation is done to confirm it is within the
15458 * scope of our event handler, and it is only advised if it is.
15459 */
15460 set_provider_method_event_data(&Provider_hwnd3, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
15461 set_provider_method_event_data(&Provider_nc3, method_event[1], ADVISE_EVENTS_EVENT_ADDED);
15463
15464 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 6); /* Only done more than once on Win11. */
15465 set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
15466 ShowWindow(test_child_hwnd, SW_SHOW);
15467 ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15469 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
15470
15471 /* Same deal as before, it will advise multiple times. */
15472 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 6); /* Only done more than once on Win11. */
15473 set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
15474 NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15475 ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15477 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
15478
15479 /* Break navigation chain, can't reach our test element so no advisement. */
15480 Provider_hwnd3.parent = NULL;
15481 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only done more than once on Win11. */
15482 set_uia_hwnd_expects(0, 1, 1, 1, 0);
15483 NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15484 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
15485 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
15486 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
15487
15488 set_provider_method_event_data(&Provider_hwnd3, NULL, -1);
15489 set_provider_method_event_data(&Provider_nc3, NULL, -1);
15491
15492 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15495
15496 IUIAutomationElement_Release(elem);
15497
15498 /*
15499 * Register event handler on desktop element with a scope of
15500 * TreeScope_Subtree. All EVENT_OBJECT_SHOW events will result in event
15501 * advisement regardless of navigation.
15502 */
15503 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15504 hr = IUIAutomation_GetRootElement(uia_iface, &elem);
15505 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15506 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15507
15508 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
15509 set_uia_hwnd_expects(0, 2, 2, 3, 0); /* Only done on Win11. */
15510 hr = IUIAutomation_AddAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem, TreeScope_Subtree, NULL,
15512 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15513 ok(AutomationEventHandler.ref > 1, "Unexpected refcnt %ld\n", AutomationEventHandler.ref);
15514 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15515 check_uia_hwnd_expects_at_most(0, 2, 2, 3, 0);
15516
15520
15521 /*
15522 * Windows 11 always advises all HWNDs on the desktop, so we wait for our
15523 * child window provider to be advised as well.
15524 */
15525 if (is_win11)
15526 {
15528 event_handle_count++;
15529 }
15530
15531 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
15532 set_uia_hwnd_expects(0, 3, 3, 1, 0); /* Only done more than once on Win11. */
15534 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15535 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, 1);
15536 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15538
15542
15543 /*
15544 * Test window isn't connected to desktop element through navigation, but
15545 * still gets advised of events on a desktop HWND event.
15546 */
15547 set_provider_method_event_data(&Provider_hwnd2, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
15548 set_provider_method_event_data(&Provider_nc2, method_event[1], ADVISE_EVENTS_EVENT_ADDED);
15550 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
15551 set_uia_hwnd_expects(0, 2, 2, 7, 0); /* Only done more than once on Win11. */
15552 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15553 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15554 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15555 check_uia_hwnd_expects_at_most(0, 2, 2, 7, 0);
15556
15557 hr = IUIAutomation_RemoveAutomationEventHandler(uia_iface, UIA_LiveRegionChangedEventId, elem,
15559 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15560
15561 IUIAutomationElement_Release(elem);
15562
15563 set_provider_method_event_data(&Provider_hwnd2, NULL, -1);
15564 set_provider_method_event_data(&Provider_nc2, NULL, -1);
15566 if (is_win11)
15568
15569 /*
15570 * IUIAutomationFocusChangedEventHandler is treated differently than all
15571 * other event handlers - it only advises providers of events the first
15572 * time it encounters an EVENT_OBJECT_FOCUS WinEvent for an HWND.
15573 */
15575 reset_event_advise_values_for_hwnd_providers(&Provider, &Provider_hwnd2, &Provider_nc2);
15576 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15577
15578 set_uia_hwnd_expects(0, 6, 6, 5, 0);
15579 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15581 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15583 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15584 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15585 check_uia_hwnd_expects_at_most(0, 6, 6, 5, 0);
15586 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15587
15588 /*
15589 * Windows 10 version 1507 and below only advise the currently focused
15590 * HWNDs providers of events being added - newer versions instead advise
15591 * the desktop HWND's providers of events being added. We're matching the
15592 * newer behavior, so skip the tests on older versions.
15593 */
15594 if (!Provider_nc.advise_events_added_event_id && !Provider_hwnd.advise_events_added_event_id &&
15595 !Provider_proxy.advise_events_added_event_id)
15596 {
15597 win_skip("Win10v1507 and below advise the currently focused HWND and not the desktop HWND, skipping tests.\n");
15598
15599 test_hwnd_providers_event_advise_added(&Provider, &Provider_hwnd2, &Provider_nc2, UIA_AutomationFocusChangedEventId, FALSE);
15600 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15601 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
15603 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15604 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15605 goto exit;
15606 }
15607
15608 /*
15609 * Currently focused HWND is not advised, it's expected that the desktop
15610 * providers will advise it using GetEmbeddedFragmentRoots.
15611 */
15612 test_provider_event_advise_added(&Provider_hwnd2, 0, FALSE);
15613 test_provider_event_advise_added(&Provider_nc2, 0, FALSE);
15615
15616 /*
15617 * EVENT_OBJECT_SHOW doesn't advise events on anything other than the
15618 * desktop HWND for focus changed event handlers.
15619 */
15620 event_handle_count = 3;
15621 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Win11 sends WM_GETOBJECT twice. */
15622 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, method_event, ADVISE_EVENTS_EVENT_ADDED);
15623 NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
15624 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15625 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15626 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15627 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, NULL, -1);
15628
15629 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, method_event, ADVISE_EVENTS_EVENT_ADDED);
15630 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only done twice on Win11. */
15631 set_uia_hwnd_expects(0, 1, 1, 1, 0);
15632 NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15633 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15634 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15635 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, NULL, -1);
15636 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
15637 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 2);
15638
15639 /*
15640 * This will advise events.
15641 */
15644 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15645 set_uia_hwnd_expects(0, 3, 3, 1, 0); /* Only Win11 sends WM_GETOBJECT. */
15646
15648 ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15649 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15650
15653 check_uia_hwnd_expects_at_most(0, 3, 3, 1, 0);
15654 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15655
15656 /*
15657 * The HWND that was focused when adding the event handler is ignored,
15658 * EVENT_OBJECT_FOCUS only advises of events the first time
15659 * EVENT_OBJECT_FOCUS is raised on an HWND, and it tracks if it has
15660 * encountered a particular HWND before.
15661 */
15662 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, method_event, ADVISE_EVENTS_EVENT_ADDED);
15663 set_uia_hwnd_expects(0, 1, 1, 3, 0); /* Only Win11 sends WM_GETOBJECT 3 times. */
15664
15665 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15666 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15667 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15668
15669 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, NULL, -1);
15670 check_uia_hwnd_expects_at_most(0, 1, 1, 3, 0);
15671
15672 /* Only OBJID_CLIENT is listened for, all other OBJIDs are ignored. */
15673 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, method_event, ADVISE_EVENTS_EVENT_ADDED);
15674
15675 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15676 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15677 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15678
15679 /*
15680 * First time EVENT_OBJECT_FOCUS is fired for this HWND, it will be
15681 * advised of UIA_AutomationFocusChangedEventId being listened for.
15682 * But only the serverside provider.
15683 */
15684 set_method_event_handle_for_providers(&Provider2, &Provider_hwnd3, &Provider_nc3, NULL, -1);
15685 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15687 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
15688 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
15689
15690 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15691 ok(msg_wait_for_all_events(method_event, 1, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
15692 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15693
15694 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15695 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
15696 test_provider_event_advise_added(&Provider2, UIA_AutomationFocusChangedEventId, FALSE);
15697 test_provider_event_advise_added(&Provider_hwnd3, 0, FALSE);
15698 test_provider_event_advise_added(&Provider_nc3, 0, FALSE);
15699
15700 /* Doing it again has no effect, it has already been advised. */
15701 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15702 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
15703 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
15704
15705 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15706 ok(msg_wait_for_all_events(method_event, 1, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15707 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15708
15710 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15711 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
15712 test_hwnd_providers_event_advise_added(&Provider2, &Provider_hwnd3, &Provider_nc3, 0, FALSE);
15713
15714 /*
15715 * Same deal here - we've already encountered this HWND and advised it
15716 * when the event handler was added initially, so it too is ignored.
15717 */
15718 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, method_event, ADVISE_EVENTS_EVENT_ADDED);
15719 reset_event_advise_values_for_hwnd_providers(&Provider, &Provider_hwnd2, &Provider_nc2);
15720 set_uia_hwnd_expects(0, 1, 1, 3, 0); /* Only Win11 sends WM_GETOBJECT 3 times. */
15721
15722 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15723 ok(msg_wait_for_all_events(method_event, event_handle_count, 750) == WAIT_TIMEOUT, "Wait for method_event(s) didn't time out.\n");
15724 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15725
15726 set_method_event_handle_for_providers(&Provider, &Provider_hwnd2, &Provider_nc2, NULL, -1);
15727 check_uia_hwnd_expects_at_most(0, 1, 1, 3, 0);
15728 test_hwnd_providers_event_advise_added(&Provider, &Provider_hwnd2, &Provider_nc2, 0, FALSE);
15729
15730 /* HWND destruction is tracked with EVENT_OBJECT_DESTROY/OBJID_WINDOW. */
15731 NotifyWinEvent(EVENT_OBJECT_DESTROY, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
15732 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15733
15734 /*
15735 * EVENT_OBJECT_DESTROY removed this HWND, EVENT_OBJECT_FOCUS will now
15736 * advise it again.
15737 */
15738 reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
15740 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
15741 set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
15742
15743 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15744 wait_res = msg_wait_for_all_events(method_event, 1, 2000);
15745 ok(wait_res != WAIT_TIMEOUT || broken(wait_res == WAIT_TIMEOUT), /* Win10v1709 */
15746 "Wait for method_event(s) timed out.\n");
15747 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15748
15750 check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
15751 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
15752 if (!winetest_platform_is_wine && (wait_res == WAIT_TIMEOUT)) /* Win10v1709 */
15754 else
15755 test_provider_event_advise_added(&Provider2, UIA_AutomationFocusChangedEventId, FALSE);
15756 test_provider_event_advise_added(&Provider_hwnd3, 0, FALSE);
15757 test_provider_event_advise_added(&Provider_nc3, 0, FALSE);
15758
15759 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15760 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
15762 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15763 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15764
15765exit:
15766 Provider_hwnd3.parent = &Provider_hwnd2.IRawElementProviderFragment_iface;
15767 for (i = 0; i < ARRAY_SIZE(method_event); i++)
15768 CloseHandle(method_event[i]);
15769}
15770
15771static struct MultiEventData {
15773
15777
15779{
15782
15784}
15785
15787{
15790}
15791
15792static void WINAPI multi_uia_event_callback(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
15793{
15794 struct node_provider_desc *exp_desc;
15795 LONG exp_lbound[2], exp_elems[2];
15796
15798 return;
15799
15801
15802 exp_lbound[0] = exp_lbound[1] = 0;
15803 exp_elems[0] = exp_elems[1] = 1;
15805 test_cache_req_sa(req_data, exp_lbound, exp_elems, exp_desc);
15806
15807 ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
15808 if (MultiEventData.event_handle && (MultiEventData.exp_events.exp_event_count == MultiEventData.exp_events.exp_event_pos))
15810}
15811
15813 HWND test_child_hwnd)
15814{
15815 struct UiaCacheRequest cache_req = { (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
15817 struct node_provider_desc exp_node_desc, exp_nested_node_desc;
15818 struct Provider_prop_override prop_override;
15819 HANDLE event_handles[2];
15820 HUIAEVENT event;
15821 HUIANODE node;
15822 HRESULT hr;
15823 VARIANT v;
15824 int i;
15825
15826 for (i = 0; i < ARRAY_SIZE(event_handles); i++)
15827 event_handles[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
15828
15829 set_uia_hwnd_expects(0, 1, 1, 0, 0);
15831 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15832 ok(!!node, "Node == NULL.\n");
15833 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
15834
15835 set_uia_hwnd_expects(0, 6, 6, 5, 0);
15836 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15837 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, multi_uia_event_callback, TreeScope_Subtree, NULL, 0, &cache_req,
15838 &event);
15839 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15840 ok(!!event, "event == NULL.\n");
15841 check_uia_hwnd_expects_at_most(0, 6, 6, 5, 0);
15842 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15843
15845
15846 MultiEventData.event_handle = event_handles[0];
15847 ComEventData.event_handle = event_handles[1];
15848
15849 /*
15850 * No IUIAutomationFocusChangedEventHandler is installed, and no
15851 * IProxyProviderWinEventHandler interfaces were returned from our
15852 * clientside desktop providers. This WinEvent will be ignored.
15853 */
15854 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15855 ok(msg_wait_for_all_events(event_handles, 1, 750) == WAIT_TIMEOUT, "Wait for event_handle(s) didn't time out.\n");
15856
15857 /* Add our IUIAutomationFocusChangedEventHandler. */
15858 set_uia_hwnd_expects(0, 6, 6, 5, 0);
15859 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
15862 hr = IUIAutomation_AddFocusChangedEventHandler(uia_iface, NULL,
15864 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
15865 ok(FocusChangedHandler.ref > 1, "Unexpected refcnt %ld\n", FocusChangedHandler.ref);
15866 check_uia_hwnd_expects_at_most(0, 6, 6, 5, 0);
15867 CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
15868
15869 /*
15870 * Now that we have an IUIAutomationFocusChangedEventHandler installed,
15871 * EVENT_OBJECT_FOCUS events will be translated into native UIA events on
15872 * our serverside provider. This is done for both HUIAEVENTs and COM
15873 * events, unlike event advisement which only applies to COM event
15874 * handlers.
15875 */
15878 init_node_provider_desc(&exp_nested_node_desc, GetCurrentProcessId(), test_hwnd);
15879 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider", TRUE);
15880
15881 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_hwnd);
15882 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
15883 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
15884 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, TRUE, &exp_nested_node_desc);
15885
15886 set_multi_event_data(&exp_node_desc);
15887 set_com_event_data(&exp_node_desc);
15888
15889 set_uia_hwnd_expects(0, 2, 2, 4, 0); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15890 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15891 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15892 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15896
15897 /*
15898 * Child ID is ignored when translating EVENT_OBJECT_FOCUS events into
15899 * native UIA events on our serverside provider.
15900 */
15901 set_multi_event_data(&exp_node_desc);
15902 set_com_event_data(&exp_node_desc);
15903 set_uia_hwnd_expects(0, 2, 2, 4, 0); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15904
15905 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, -1);
15906 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15907 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15911
15912 /*
15913 * UIA queries the serverside provider for UIA_HasKeyboardFocusPropertyId.
15914 * If this is anything other than TRUE, it won't raise an event for our
15915 * serverside provider.
15916 */
15918 set_property_override(&prop_override, UIA_HasKeyboardFocusPropertyId, &v);
15919 set_provider_prop_override(&Provider, &prop_override, 1);
15920
15921 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2); /* Only done twice on Win11. */
15922 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
15923 ok(msg_wait_for_all_events(event_handles, 2, 750) == WAIT_TIMEOUT, "Wait for event_handle(s) didn't time out.\n");
15924 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15925 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
15927
15928 /*
15929 * The first time EVENT_OBJECT_FOCUS is raised for an HWND with a
15930 * serverside provider UIA will query for the currently focused provider
15931 * and raise a focus change event for it, alongside advising the root
15932 * provider of focus change events being listened for. All subsequent
15933 * EVENT_OBJECT_FOCUS events on the same HWND only query the root
15934 * provider.
15935 */
15937 Provider_child2.parent = &Provider2.IRawElementProviderFragment_iface;
15938 Provider_child2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
15939 Provider2.focus_prov = &Provider_child2.IRawElementProviderFragment_iface;
15942
15944 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child2", TRUE);
15945
15946 set_multi_event_data(&exp_node_desc);
15947 set_com_event_data(&exp_node_desc);
15948
15949 /* Second event. */
15950 init_node_provider_desc(&exp_nested_node_desc, GetCurrentProcessId(), test_child_hwnd);
15951 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider2", TRUE);
15952
15953 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_child_hwnd);
15954 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd3", TRUE);
15955 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc3", FALSE);
15956 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, FALSE, &exp_nested_node_desc);
15957
15958 push_expected_event(&exp_node_desc);
15959 push_expected_com_event(&exp_node_desc);
15960 set_uia_hwnd_expects(0, 2, 2, 3, 0); /* Win11 sends 3 WM_GETOBJECT messages, normally only 2. */
15961 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15962 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15963 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15964 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15966 CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 3);
15969
15970 /*
15971 * Second time EVENT_OBJECT_FOCUS is raised for this HWND, only the root
15972 * provider will have an event raised.
15973 */
15974 init_node_provider_desc(&exp_nested_node_desc, GetCurrentProcessId(), test_child_hwnd);
15975 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider2", TRUE);
15976
15977 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_child_hwnd);
15978 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd3", TRUE);
15979 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc3", FALSE);
15980 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, FALSE, &exp_nested_node_desc);
15981
15982 set_multi_event_data(&exp_node_desc);
15983 set_com_event_data(&exp_node_desc);
15984 set_uia_hwnd_expects(0, 2, 2, 3, 0); /* Win11 sends 3 WM_GETOBJECT messages, normally only 2. */
15985 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 3. */
15986 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
15987 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
15988 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
15990 CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 3);
15993
15994 /*
15995 * Windows 7 has quirky behavior around MSAA proxy creation, skip tests.
15996 */
15997 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
15998 {
15999 win_skip("Skipping focus MSAA proxy tests for Win7\n");
16000 goto exit;
16001 }
16002
16003 /*
16004 * Creates an MSAA proxy, raises event on that.
16005 */
16006 prov_root = NULL;
16007 set_accessible_props(&Accessible, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
16008 Accessible.ow_hwnd = test_hwnd;
16011
16012 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_hwnd);
16013 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
16014 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
16015 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16016
16017 set_multi_event_data(&exp_node_desc);
16018 set_com_event_data(&exp_node_desc);
16019
16020 set_uia_hwnd_expects(0, 1, 1, 4, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 2. */
16021 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 3);
16022 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accParent, 3);
16023 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
16024 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
16025 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
16026 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16027 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16029 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, QI_IAccIdentity);
16031 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
16032 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
16035
16036 /*
16037 * Return Accessible_child2 from get_accFocus.
16038 */
16039 set_accessible_props(&Accessible, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
16040 Accessible.focus_child_id = 4; /* 4 gets us Accessible_child2. */
16041 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSED, 0, L"acc_child2", 0, 0, 0, 0);
16042
16044 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16045
16046 set_multi_event_data(&exp_node_desc);
16047 set_com_event_data(&exp_node_desc);
16048 set_uia_hwnd_expects(0, 0, 0, 2, 3); /* Win11 sends 2/3 WM_GETOBJECT messages, normally only 1/2. */
16049 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 4); /* Only done 4 times on Win11, normally 3. */
16050 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accParent, 3); /* Only done 3 times on Win11, normally 2. */
16051 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
16052 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
16053 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
16054 SET_ACC_METHOD_EXPECT(&Accessible_child2, QI_IAccIdentity);
16057 SET_ACC_METHOD_EXPECT(&Accessible_child2, accNavigate); /* Wine only, Windows doesn't pass this through the DA wrapper. */
16060 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
16061 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16062 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16066 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
16067 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
16068 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
16077
16078 /*
16079 * accFocus returns Accessible_child2, however it has
16080 * STATE_SYSTEM_INVISIBLE set. Falls back to Accessible.
16081 */
16082 set_accessible_props(&Accessible_child2, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_INVISIBLE | STATE_SYSTEM_FOCUSED, 0, L"acc_child2", 0, 0, 0, 0);
16083 set_accessible_props(&Accessible, ROLE_SYSTEM_CLIENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
16084
16085 init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), test_hwnd);
16086 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
16087 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
16088 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16089
16090 set_multi_event_data(&exp_node_desc);
16091 set_com_event_data(&exp_node_desc);
16092 set_uia_hwnd_expects(0, 1, 1, 4, 4); /* Win11 sends 4 WM_GETOBJECT messages, normally only 2. */
16093 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 4); /* Only done 4 times on Win11, normally 2. */
16094 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, get_accParent, 3); /* Only done 3 times on Win11, normally 1. */
16095 SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
16096 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
16097 SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
16098 SET_ACC_METHOD_EXPECT(&Accessible_child2, accNavigate); /* Wine only, Windows doesn't pass this through the DA wrapper. */
16099 SET_ACC_METHOD_EXPECT(&Accessible_child2, QI_IAccIdentity);
16102 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, CHILDID_SELF);
16103 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16104 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16108 CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
16109 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
16110 CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
16117
16118 /*
16119 * Get Accessible_child2 by raising an event with its child ID directly.
16120 * It will have its get_accFocus method called.
16121 */
16123 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA Proxy provider. */
16124
16125 set_multi_event_data(&exp_node_desc);
16126 set_com_event_data(&exp_node_desc);
16127 set_uia_hwnd_expects(0, 0, 0, 2, 2); /* Win11 sends 2/2 WM_GETOBJECT messages, normally only 1/1. */
16128 SET_ACC_METHOD_EXPECT_MULTI(&Accessible, QI_IAccIdentity, 2); /* Only done 2 times on Win11, normally 1. */
16129 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent); /* Only done on Win11. */
16130 SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
16131 SET_ACC_METHOD_EXPECT(&Accessible_child2, QI_IAccIdentity);
16135 NotifyWinEvent(EVENT_OBJECT_FOCUS, test_hwnd, OBJID_CLIENT, 4);
16136 ok(msg_wait_for_all_events(event_handles, 2, 5000) != WAIT_TIMEOUT, "Wait for event_handle(s) timed out.\n");
16137 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16139 CHECK_ACC_METHOD_CALLED_AT_MOST(&Accessible, get_accParent, 1); /* Only done on Win11. */
16140 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, QI_IAccIdentity);
16141 CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
16148 acc_client = NULL;
16149
16150exit:
16151 set_uia_hwnd_expects(0, 1, 1, 0, 0);
16152 hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
16154 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16155 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
16156
16158 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16159
16161 for (i = 0; i < ARRAY_SIZE(event_handles); i++)
16162 CloseHandle(event_handles[i]);
16163}
16164
16166{
16168 IUIAutomation *uia_iface = test_data->uia_iface;
16169
16172
16175
16176 if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
16179
16180 return 0;
16181}
16182
16184{
16186 IUIAutomationElement *elem;
16187 HANDLE thread;
16188 HRESULT hr;
16189 HWND hwnd;
16190
16191 test_data.test_hwnd = ComEventData.event_hwnd = hwnd = create_test_hwnd("test_CUIAutomation_event_handlers class");
16192
16193 /* Set up providers for the desktop window and our test HWND. */
16195 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
16196 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
16197 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
16198
16199 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
16204
16206 set_uia_hwnd_expects(1, 1, 1, 1, 1);
16208 hr = IUIAutomation_ElementFromHandle(uia_iface, hwnd, &elem);
16209 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16210 ok(!!elem, "elem == NULL\n");
16211 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
16212 ok(Provider_hwnd2.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd2.ref);
16213 ok(Provider_nc2.ref == 2, "Unexpected refcnt %ld\n", Provider_nc2.ref);
16214 check_uia_hwnd_expects(1, TRUE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
16215
16218 IUIAutomationElement_Release(elem);
16219
16220 /* Create a test child window. */
16221 test_data.test_child_hwnd = create_child_test_hwnd("test_CUIAutomation_event_handlers child class", hwnd);
16222 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, test_data.test_child_hwnd);
16224 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
16225 Provider2.ignore_hwnd_prop = TRUE;
16226 Provider_hwnd3.parent = &Provider_hwnd2.IRawElementProviderFragment_iface;
16227 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
16228
16229 hr = IUIAutomation_RemoveAllEventHandlers(uia_iface);
16230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16231
16232 /*
16233 * Particular versions of Windows 7 trigger access violations when doing
16234 * WinEvent tests, just skip them for Windows 7.
16235 */
16236 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
16237 {
16238 win_skip("Skipping COM API WinEvent translation tests for Win7\n");
16239 goto exit;
16240 }
16241
16244 {
16245 MSG msg;
16246
16247 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
16248 {
16251 }
16252 }
16254
16255exit:
16258 UnregisterClassA("test_CUIAutomation_event_handlers class", NULL);
16259 UnregisterClassA("test_CUIAutomation_event_handlers child class", NULL);
16261}
16262
16264 const GUID *clsid;
16265 const GUID *iid;
16266};
16267
16268static const struct uia_com_classes com_classes[] = {
16269 { &CLSID_CUIAutomation, &IID_IUnknown },
16270 { &CLSID_CUIAutomation, &IID_IUIAutomation },
16271 { &CLSID_CUIAutomation8, &IID_IUnknown },
16272 { &CLSID_CUIAutomation8, &IID_IUIAutomation },
16273 { &CLSID_CUIAutomation8, &IID_IUIAutomation2 },
16274 { &CLSID_CUIAutomation8, &IID_IUIAutomation3 },
16275 { &CLSID_CUIAutomation8, &IID_IUIAutomation4 },
16276 { &CLSID_CUIAutomation8, &IID_IUIAutomation5 },
16277 { &CLSID_CUIAutomation8, &IID_IUIAutomation6 },
16278};
16279
16280static void test_CUIAutomation(void)
16281{
16282 BOOL has_cui8 = TRUE, tmp_b;
16283 IUIAutomation *uia_iface;
16284 IUnknown *unk1, *unk2;
16285 HRESULT hr;
16286 VARIANT v;
16287 int i;
16288
16290
16291 for (i = 0; i < ARRAY_SIZE(com_classes); i++)
16292 {
16293 IUnknown *iface = NULL;
16294
16295 hr = CoCreateInstance(com_classes[i].clsid, NULL, CLSCTX_INPROC_SERVER, com_classes[i].iid,
16296 (void **)&iface);
16297
16298 if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == REGDB_E_CLASSNOTREG))
16299 {
16300 win_skip("CLSID_CUIAutomation8 class not registered, skipping further tests.\n");
16301 has_cui8 = FALSE;
16302 break;
16303 }
16304 else if ((com_classes[i].clsid == &CLSID_CUIAutomation8) && (hr == E_NOINTERFACE) &&
16305 (com_classes[i].iid != &IID_IUIAutomation2) && (com_classes[i].iid != &IID_IUIAutomation) &&
16307 {
16308 win_skip("No object for clsid %s, iid %s, skipping further tests.\n", debugstr_guid(com_classes[i].clsid),
16310 break;
16311 }
16312
16313 ok(hr == S_OK, "Failed to create interface for clsid %s, iid %s, hr %#lx\n",
16315 ok(!!iface, "iface == NULL\n");
16316 IUnknown_Release(iface);
16317 }
16318
16319 if (has_cui8)
16320 hr = CoCreateInstance(&CLSID_CUIAutomation8, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
16321 (void **)&uia_iface);
16322 else
16323 hr = CoCreateInstance(&CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, &IID_IUIAutomation,
16324 (void **)&uia_iface);
16325 ok(hr == S_OK, "Failed to create IUIAutomation interface, hr %#lx\n", hr);
16326 ok(!!uia_iface, "uia_iface == NULL\n");
16327
16328 /* Reserved value retrieval methods. */
16330 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16331
16332 hr = IUIAutomation_get_ReservedNotSupportedValue(uia_iface, &unk2);
16333 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16334 ok(unk1 == unk2, "unk1 != unk2\n");
16335
16336 V_VT(&v) = VT_UNKNOWN;
16337 V_UNKNOWN(&v) = unk1;
16338 hr = IUIAutomation_CheckNotSupported(uia_iface, v, &tmp_b);
16339 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16340 ok(tmp_b == TRUE, "tmp_b != TRUE\n");
16341
16342 IUnknown_Release(unk1);
16343 IUnknown_Release(unk2);
16344
16346 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16347
16348 hr = IUIAutomation_get_ReservedMixedAttributeValue(uia_iface, &unk2);
16349 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16350 ok(unk1 == unk2, "unk1 != unk2\n");
16351
16352 V_VT(&v) = VT_UNKNOWN;
16353 V_UNKNOWN(&v) = unk1;
16354 hr = IUIAutomation_CheckNotSupported(uia_iface, v, &tmp_b);
16355 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16356 ok(tmp_b == FALSE, "tmp_b != FALSE\n");
16357
16358 IUnknown_Release(unk1);
16359 IUnknown_Release(unk2);
16360
16372
16373 IUIAutomation_Release(uia_iface);
16375}
16376
16378 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
16379 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16380 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_NativeWindowHandlePropertyId */
16381 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16382 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_NamePropertyId */
16383 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16384 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_NamePropertyId */
16385 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16386 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ClassNamePropertyId */
16387 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16388 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ClassNamePropertyId */
16389 { &Provider_nc, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Windows 7. */
16390 { &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_ProcessIdPropertyId */
16392 { &Provider_nc, PROV_GET_PROPERTY_VALUE }, /* UIA_ProcessIdPropertyId */
16394 { 0 }
16395};
16396
16397#define test_node_hwnd_provider( node, hwnd ) \
16398 test_node_hwnd_provider_( (node), (hwnd), __FILE__, __LINE__)
16399static void test_node_hwnd_provider_(HUIANODE node, HWND hwnd, const char *file, int line)
16400{
16401 WCHAR buf[1024] = { 0 };
16402 HRESULT hr;
16403 VARIANT v;
16404 DWORD pid;
16405
16406 winetest_push_context("UIA_NativeWindowHandlePropertyId");
16407 hr = UiaGetPropertyValue(node, UIA_NativeWindowHandlePropertyId, &v);
16408 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16409 ok_(file, line)(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16410 ok_(file, line)(V_I4(&v) == HandleToUlong(hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), HandleToUlong(hwnd));
16411 VariantClear(&v);
16413
16414 winetest_push_context("UIA_NamePropertyId");
16416 hr = UiaGetPropertyValue(node, UIA_NamePropertyId, &v);
16417 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16418 ok_(file, line)(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
16419 ok(!lstrcmpW(V_BSTR(&v), buf), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
16420 VariantClear(&v);
16422
16423 winetest_push_context("UIA_ClassNamePropertyId");
16424 memset(buf, 0, sizeof(buf));
16426 hr = UiaGetPropertyValue(node, UIA_ClassNamePropertyId, &v);
16427 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16428 ok_(file, line)(V_VT(&v) == VT_BSTR, "Unexpected VT %d\n", V_VT(&v));
16429 ok(!lstrcmpW(V_BSTR(&v), buf), "Unexpected BSTR %s\n", wine_dbgstr_w(V_BSTR(&v)));
16430 VariantClear(&v);
16432
16434 winetest_push_context("UIA_ProcessIdPropertyId");
16435 hr = UiaGetPropertyValue(node, UIA_ProcessIdPropertyId, &v);
16436 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16437 ok_(file, line)(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16438 ok_(file, line)(V_I4(&v) == pid, "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v), pid);
16439 VariantClear(&v);
16441}
16442
16443enum {
16447};
16448
16454};
16455
16457 { WS_OVERLAPPEDWINDOW, 0, UIA_WindowControlTypeId, PARENT_HWND_NULL },
16458 /* Top-level window (parent is desktop window) is always a window control. */
16459 { WS_CHILD, 0, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
16460 /* Not a top-level window, considered a pane. */
16461 { WS_CHILD, 0, UIA_PaneControlTypeId, PARENT_HWND_HWND },
16462 /* Not a top-level window, but WS_EX_APPWINDOW is always considered a window. */
16463 { WS_CHILD, WS_EX_APPWINDOW, UIA_WindowControlTypeId, PARENT_HWND_HWND },
16464 /*
16465 * WS_POPUP is always a pane regardless of being a top level window,
16466 * unless WS_CAPTION is set.
16467 */
16468 { WS_CAPTION | WS_POPUP, 0, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
16469 { WS_BORDER | WS_POPUP, 0, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
16470 { WS_POPUP, 0, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
16471 /*
16472 * Top level window with WS_EX_TOOLWINDOW and without WS_CAPTION is
16473 * considered a pane.
16474 */
16475 { WS_CHILD, WS_EX_TOOLWINDOW, UIA_PaneControlTypeId, PARENT_HWND_DESKTOP },
16476 { WS_CHILD | WS_CAPTION, WS_EX_TOOLWINDOW, UIA_WindowControlTypeId, PARENT_HWND_DESKTOP },
16477};
16478
16479static void create_base_hwnd_test_node(HWND hwnd, BOOL child_hwnd, struct Provider *main, struct Provider *nc,
16480 HUIANODE *ret_node)
16481{
16482 ULONG main_ref, nc_ref;
16483 HRESULT hr;
16484
16487 nc->ignore_hwnd_prop = main->ignore_hwnd_prop = TRUE;
16488 main_ref = main->ref;
16489 nc_ref = nc->ref;
16490
16491 if (!child_hwnd)
16492 {
16493 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16494 SET_EXPECT(winproc_GETOBJECT_CLIENT);
16495 prov_root = &main->IRawElementProviderSimple_iface;
16496 }
16497 else
16498 {
16499 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16500 SET_EXPECT(winproc_GETOBJECT_CLIENT);
16501 SET_EXPECT(child_winproc_GETOBJECT_UiaRoot);
16502 child_win_prov_root = &main->IRawElementProviderSimple_iface;
16503 }
16504
16506 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16507 ok(main->ref == (main_ref + 1), "Unexpected refcnt %ld\n", main->ref);
16508 ok(nc->ref == (nc_ref + 1), "Unexpected refcnt %ld\n", nc->ref);
16509 if (child_hwnd)
16510 {
16511 /* Called while trying to get override provider. */
16512 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16513 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
16514 }
16515 else
16516 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16517 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
16518 Provider.ret_invalid_prop_type = Provider_nc.ret_invalid_prop_type = TRUE;
16519}
16520
16521#define test_node_hwnd_provider_navigation( node, dir, exp_dest_hwnd ) \
16522 test_node_hwnd_provider_navigation_( (node), (dir), (exp_dest_hwnd), __FILE__, __LINE__)
16523static void test_node_hwnd_provider_navigation_(HUIANODE node, int nav_dir, HWND exp_dest_hwnd, const char *file,
16524 int line)
16525{
16527 const WCHAR *exp_tree_struct = exp_dest_hwnd ? L"P)" : L"";
16528 SAFEARRAY *out_req = NULL;
16529 BSTR tree_struct = NULL;
16530 LONG idx[2] = { 0 };
16531 HUIANODE tmp_node;
16532 HRESULT hr;
16533 VARIANT v;
16534 int i;
16535
16536 hr = UiaNavigate(node, nav_dir, (struct UiaCondition *)&UiaTrueCondition, &cache_req, &out_req, &tree_struct);
16537 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx\n", hr);
16538 ok_(file, line)(!!out_req, "out_req == NULL\n");
16539 ok_(file, line)(!!tree_struct, "tree_struct == NULL\n");
16540 if (!exp_dest_hwnd)
16541 goto exit;
16542
16543 for (i = 0; i < 2; i++)
16544 {
16545 hr = SafeArrayGetLBound(out_req, 1 + i, &idx[i]);
16546 ok_(file, line)(hr == S_OK, "SafeArrayGetLBound unexpected hr %#lx\n", hr);
16547 }
16548
16549 hr = SafeArrayGetElement(out_req, idx, &v);
16550 ok_(file, line)(hr == S_OK, "SafeArrayGetElement unexpected hr %#lx\n", hr);
16551
16552 hr = UiaHUiaNodeFromVariant(&v, &tmp_node);
16553 ok_(file, line)(hr == S_OK, "UiaHUiaNodeFromVariant unexpected hr %#lx\n", hr);
16554 ok_(file, line)(!!tmp_node, "tmp_node == NULL\n");
16555 VariantClear(&v);
16556
16557 hr = UiaGetPropertyValue(tmp_node, UIA_NativeWindowHandlePropertyId, &v);
16558 ok_(file, line)(hr == S_OK, "UiaGetPropertyValue unexpected hr %#lx\n", hr);
16559 ok_(file, line)(V_VT(&v) == VT_I4, "V_VT(&v) = %d\n", V_VT(&v));
16560 ok_(file, line)(V_I4(&v) == HandleToUlong(exp_dest_hwnd), "V_I4(&v) = %#lx, expected %#lx\n", V_I4(&v),
16561 HandleToUlong(exp_dest_hwnd));
16562 VariantClear(&v);
16563 UiaNodeRelease(tmp_node);
16564
16565exit:
16566 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct), "unexpected tree structure %s\n", debugstr_w(tree_struct));
16567 SafeArrayDestroy(out_req);
16568 SysFreeString(tree_struct);
16569}
16570
16572{
16573 struct UiaRect uia_rect = { 0 };
16574 HWND hwnd, hwnd_child, hwnd2;
16575 RECT rect = { 0 };
16576 IUnknown *unk_ns;
16577 HUIANODE node;
16578 HRESULT hr;
16579 VARIANT v;
16580 int i;
16581
16583 hwnd = create_test_hwnd("test_default_clientside_providers class");
16584 hwnd_child = create_child_test_hwnd("test_default_clientside_providers child class", hwnd);
16586
16588 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16589
16590 /*
16591 * Test default BaseHwnd provider. Unlike the other default providers, the
16592 * default BaseHwnd IRawElementProviderSimple is not available to test
16593 * directly. To isolate the BaseHwnd provider, we set the node's nonclient
16594 * provider to Provider_nc, and its Main provider to Provider. These
16595 * providers will return nothing so that we can isolate properties coming
16596 * from the BaseHwnd provider.
16597 */
16599
16600 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
16601 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16603 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
16604 check_node_provider_desc_todo(V_BSTR(&v), L"Main", L"Provider", FALSE);
16606 VariantClear(&v);
16607
16609 Provider.ret_invalid_prop_type = Provider_nc.ret_invalid_prop_type = TRUE;
16611 ok_method_sequence(default_hwnd_prov_props_seq, "default_hwnd_prov_props_seq");
16613
16614 /* Get the bounding rectangle from the default BaseHwnd provider. */
16616 set_uia_rect(&uia_rect, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
16617 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
16618 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16619 check_uia_rect_val(&v, &uia_rect);
16620 VariantClear(&v);
16621
16622 /* Minimized top-level HWNDs don't return a bounding rectangle. */
16624 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
16625 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16626 ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
16627 ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
16628 VariantClear(&v);
16629
16631 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
16632 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
16633
16634 /* Create a child window node. */
16636 test_node_hwnd_provider(node, hwnd_child);
16637
16638 /* Get the bounding rectangle from the default BaseHwnd provider. */
16639 GetWindowRect(hwnd_child, &rect);
16640 set_uia_rect(&uia_rect, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
16641 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
16642 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16643 check_uia_rect_val(&v, &uia_rect);
16644 VariantClear(&v);
16645
16646 /* Minimized non top-level HWNDs return a bounding rectangle. */
16647 ShowWindow(hwnd_child, SW_MINIMIZE);
16648 GetWindowRect(hwnd_child, &rect);
16649 set_uia_rect(&uia_rect, rect.left, rect.top, (rect.right - rect.left), (rect.bottom - rect.top));
16650 hr = UiaGetPropertyValue(node, UIA_BoundingRectanglePropertyId, &v);
16651 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16652 check_uia_rect_val(&v, &uia_rect);
16653 VariantClear(&v);
16654
16656 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
16657 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
16658
16659 VariantInit(&v);
16660 for (i = 0; i < ARRAY_SIZE(hwnd_control_type_test); i++)
16661 {
16663 HWND parent;
16664
16665 if (test->parent_hwnd_type == PARENT_HWND_HWND)
16666 parent = hwnd;
16667 else if (test->parent_hwnd_type == PARENT_HWND_DESKTOP)
16669 else
16670 parent = NULL;
16671
16672 hwnd2 = CreateWindowExA(test->style_ex, "test_default_clientside_providers class", "Test window", test->style,
16673 0, 0, 100, 100, parent, NULL, NULL, NULL);
16676 Provider_nc.ignore_hwnd_prop = Provider.ignore_hwnd_prop = TRUE;
16677 Provider.ret_invalid_prop_type = Provider_nc.ret_invalid_prop_type = TRUE;
16678
16679 /* If parent is hwnd, it will be queried for an override provider. */
16680 if (test->style == WS_CHILD && (parent == hwnd))
16681 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2);
16682 else
16683 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16684 /* Only sent on Win7. */
16685 SET_EXPECT(winproc_GETOBJECT_CLIENT);
16686 hr = UiaNodeFromProvider(&Provider_nc.IRawElementProviderSimple_iface, &node);
16687 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16688 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
16689 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
16691 todo_wine CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, 2);
16692 else
16693 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16694 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
16695
16696 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
16697 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16698 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16699 ok(V_I4(&v) == test->exp_control_type, "Unexpected control type %ld\n", V_I4(&v));
16700 VariantClear(&v);
16701
16703 DestroyWindow(hwnd2);
16704 }
16705
16706 /*
16707 * Default ProviderType_BaseHwnd provider navigation tests.
16708 */
16711
16712 /*
16713 * Navigate to the parent of our top-level HWND, will get a node
16714 * representing the desktop HWND.
16715 */
16718
16719 /*
16720 * Create a node representing an HWND that is a top-level window, but is
16721 * owned by another window. For top-level HWNDs, parent navigation will go
16722 * to the owner instead of the parent.
16723 */
16724 hwnd2 = CreateWindowA("test_default_clientside_providers class", "Test window", WS_POPUP, 0, 0, 50, 50, hwnd, NULL,
16725 NULL, NULL);
16726 ok(GetAncestor(hwnd2, GA_PARENT) == GetDesktopWindow(), "unexpected parent hwnd");
16727 ok(GetWindow(hwnd2, GW_OWNER) == hwnd, "unexpected owner hwnd");
16730
16731 /* Navigate to the parent. */
16732 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16733 /* Only sent on Win7. */
16734 SET_EXPECT(winproc_GETOBJECT_CLIENT);
16736 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16737 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
16738
16740 DestroyWindow(hwnd2);
16741
16742 /*
16743 * Create a node for our child window.
16744 */
16746 Provider2.ignore_hwnd_prop = TRUE;
16747 prov_root = &Provider2.IRawElementProviderSimple_iface;
16749 test_node_hwnd_provider(node, hwnd_child);
16750
16751 /* Navigate to parent. */
16752 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16753 /* Only sent on Win7. */
16754 SET_EXPECT(winproc_GETOBJECT_CLIENT);
16756 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16757 called_winproc_GETOBJECT_CLIENT = expect_winproc_GETOBJECT_CLIENT = 0;
16758
16760 prov_root = NULL;
16761
16762 /*
16763 * Test default ProviderType_Proxy clientside provider. Provider will be
16764 * the HWND provider for this node, and Accessible will be the main
16765 * provider.
16766 */
16768 set_accessible_props(&Accessible, ROLE_SYSTEM_TEXT, STATE_SYSTEM_FOCUSABLE, 0, L"Accessible", 0, 0, 20, 20);
16772
16773 SET_ACC_METHOD_EXPECT(&Accessible, QI_IAccIdentity);
16774 SET_ACC_METHOD_EXPECT(&Accessible, get_accParent);
16775 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16776 /* Only sent twice on Win7. */
16777 SET_EXPECT_MULTI(winproc_GETOBJECT_CLIENT, 2);
16779 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16780 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
16781 ok(Accessible.ref >= 2, "Unexpected refcnt %ld\n", Accessible.ref);
16782 todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, QI_IAccIdentity);
16784 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16785 CHECK_CALLED(winproc_GETOBJECT_CLIENT);
16786
16787 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
16788 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16790 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
16793 VariantClear(&v);
16794
16795 SET_ACC_METHOD_EXPECT(&Accessible, get_accRole);
16796 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
16797 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16798 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16799 ok(V_I4(&v) == UIA_EditControlTypeId, "Unexpected I4 %#lx\n", V_I4(&v));
16800 VariantClear(&v);
16801 CHECK_ACC_METHOD_CALLED(&Accessible, get_accRole);
16802
16804 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
16805 ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
16806
16807 /*
16808 * Unlike UiaProviderFromIAccessible which won't create a provider for an
16809 * MSAA proxy, the default clientside proxy provider will.
16810 */
16811 hwnd2 = CreateWindowA("EDIT", "", WS_VISIBLE | WS_CHILD | ES_PASSWORD,
16812 0, 0, 100, 100, hwnd, NULL, NULL, NULL);
16814
16815 /* Tries to get override provider from parent HWND. */
16816 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
16818 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16819 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
16820 todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
16821
16822 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
16823 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16825 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider", FALSE);
16827 check_node_provider_desc_todo(V_BSTR(&v), L"Annotation", NULL, TRUE);
16828 VariantClear(&v);
16829
16830 hr = UiaGetPropertyValue(node, UIA_ControlTypePropertyId, &v);
16831 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16832 ok(V_VT(&v) == VT_I4, "Unexpected VT %d\n", V_VT(&v));
16833 ok(V_I4(&v) == UIA_EditControlTypeId, "Unexpected I4 %#lx\n", V_I4(&v));
16834 VariantClear(&v);
16835
16836 hr = UiaGetPropertyValue(node, UIA_IsPasswordPropertyId, &v);
16837 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16838 ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
16839 ok(check_variant_bool(&v, TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v));
16840 VariantClear(&v);
16841
16843 DestroyWindow(hwnd2);
16844
16845 set_accessible_props(&Accessible, 0, 0, 0, NULL, 0, 0, 0, 0);
16846 acc_client = NULL;
16848
16851 DestroyWindow(hwnd_child);
16852 UnregisterClassA("test_default_clientside_providers class", NULL);
16853 UnregisterClassA("test_default_clientside_providers child class", NULL);
16854
16855 IUnknown_Release(unk_ns);
16857}
16858
16859static void test_UiaGetRootNode(void)
16860{
16861 HUIANODE node;
16862 HRESULT hr;
16863 VARIANT v;
16864
16867
16868 /*
16869 * UiaGetRootNode is the same as calling UiaNodeFromHandle with the
16870 * desktop window handle.
16871 */
16873 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
16874 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
16875 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
16876
16878 SET_EXPECT(prov_callback_base_hwnd);
16879 SET_EXPECT(prov_callback_nonclient);
16880 SET_EXPECT(prov_callback_proxy);
16882 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16883 ok(!!node, "Node == NULL.\n");
16884 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
16885 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
16886 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
16887 CHECK_CALLED(prov_callback_base_hwnd);
16888 CHECK_CALLED(prov_callback_nonclient);
16889 CHECK_CALLED(prov_callback_proxy);
16890
16891 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
16892 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
16894 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_proxy", TRUE);
16895 check_node_provider_desc(V_BSTR(&v), L"Hwnd", L"Provider_hwnd", FALSE);
16896 check_node_provider_desc(V_BSTR(&v), L"Nonclient", L"Provider_nc", FALSE);
16897 VariantClear(&v);
16898
16899 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
16900 ok(Provider_proxy.ref == 1, "Unexpected refcnt %ld\n", Provider_proxy.ref);
16901 ok(Provider_hwnd.ref == 1, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
16902 ok(Provider_nc.ref == 1, "Unexpected refcnt %ld\n", Provider_nc.ref);
16903
16906 TRUE);
16909
16913}
16914
16915#define test_node_from_focus( cache_req, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, nc_cback_count, \
16916 win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, base_hwnd_cback_todo, \
16917 nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo) \
16918 test_node_from_focus_( (cache_req), (exp_node_desc), (proxy_cback_count), (base_hwnd_cback_count), (nc_cback_count), \
16919 (win_get_obj_count), (child_win_get_obj_count), (proxy_cback_todo), (base_hwnd_cback_todo), \
16920 (nc_cback_todo), (win_get_obj_todo), (child_win_get_obj_todo), __FILE__, __LINE__)
16921static void test_node_from_focus_(struct UiaCacheRequest *cache_req, struct node_provider_desc *exp_node_desc,
16922 int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count, int win_get_obj_count,
16923 int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo, BOOL nc_cback_todo,
16924 BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
16925{
16926 const WCHAR *exp_tree_struct = exp_node_desc->prov_count ? L"P)" : L"";
16927 LONG exp_lbound[2], exp_elems[2];
16928 SAFEARRAY *out_req = NULL;
16929 BSTR tree_struct = NULL;
16930 HRESULT hr;
16931
16932 SET_EXPECT_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
16933 SET_EXPECT_MULTI(prov_callback_nonclient, nc_cback_count);
16934 SET_EXPECT_MULTI(prov_callback_proxy, proxy_cback_count);
16935 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
16936 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
16937 hr = UiaNodeFromFocus(cache_req, &out_req, &tree_struct);
16938 ok_(file, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
16939 if (exp_node_desc->prov_count)
16940 ok_(file, line)(!!out_req, "out_req == NULL\n");
16941 else
16942 ok_(file, line)(!out_req, "out_req != NULL\n");
16943 ok_(file, line)(!!tree_struct, "tree_struct == NULL\n");
16944 todo_wine_if(base_hwnd_cback_todo) CHECK_CALLED_MULTI(prov_callback_base_hwnd, base_hwnd_cback_count);
16945 todo_wine_if(proxy_cback_todo) CHECK_CALLED_MULTI(prov_callback_proxy, proxy_cback_count);
16946 todo_wine_if(nc_cback_todo) CHECK_CALLED_MULTI(prov_callback_nonclient, nc_cback_count);
16947 todo_wine_if(win_get_obj_todo) CHECK_CALLED_MULTI(winproc_GETOBJECT_UiaRoot, win_get_obj_count);
16948 todo_wine_if(child_win_get_obj_todo) CHECK_CALLED_MULTI(child_winproc_GETOBJECT_UiaRoot, child_win_get_obj_count);
16949
16950 ok_(file, line)(!wcscmp(tree_struct, exp_tree_struct), "unexpected tree structure %s\n", debugstr_w(tree_struct));
16951 if (exp_node_desc->prov_count)
16952 {
16953 exp_lbound[0] = exp_lbound[1] = 0;
16954 exp_elems[0] = 1;
16955 exp_elems[1] = 1 + cache_req->cProperties;
16956 test_cache_req_sa_(out_req, exp_lbound, exp_elems, exp_node_desc, file, line);
16957 }
16958
16959 SafeArrayDestroy(out_req);
16960 SysFreeString(tree_struct);
16961}
16962
16963static void test_UiaNodeFromFocus(void)
16964{
16965 struct Provider_prop_override prop_override;
16966 struct node_provider_desc exp_node_desc;
16967 struct UiaPropertyCondition prop_cond;
16968 struct UiaCacheRequest cache_req;
16969 struct UiaNotCondition not_cond;
16970 HWND hwnd, hwnd_child;
16971 int cache_prop;
16972 VARIANT v;
16973
16975
16976 hwnd = create_test_hwnd("UiaNodeFromFocus class");
16977 hwnd_child = create_child_test_hwnd("UiaNodeFromFocus child class", hwnd);
16978
16980
16981 /* Set clientside providers for our test windows and the desktop. */
16983 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
16984 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
16985 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
16986
16987 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
16992
16993 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, hwnd_child);
16995 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
16996 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
16997 Provider2.ignore_hwnd_prop = TRUE;
16998
16999 /*
17000 * Nodes are normalized against the cache request view condition. Here,
17001 * we're setting it to the same as the default ControlView.
17002 */
17004 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
17005 set_not_condition(&not_cond, (struct UiaCondition *)&prop_cond);
17006 cache_prop = UIA_RuntimeIdPropertyId;
17007 set_cache_request(&cache_req, (struct UiaCondition *)&not_cond, TreeScope_Element, &cache_prop, 1, NULL, 0,
17009
17010 /*
17011 * None of the providers for the desktop node return a provider from
17012 * IRawElementProviderFragmentRoot::GetFocus, so we just get the
17013 * desktop node.
17014 */
17017 add_provider_desc(&exp_node_desc, L"Main", L"Provider_proxy", TRUE);
17018 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc", FALSE);
17019 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd", FALSE);
17020
17021 test_node_from_focus(&cache_req, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
17022
17023 /* Provider_hwnd returns Provider_hwnd2 from GetFocus. */
17024 Provider_hwnd.focus_prov = &Provider_hwnd2.IRawElementProviderFragment_iface;
17025
17027 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
17028 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
17029 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
17030
17031 test_node_from_focus(&cache_req, &exp_node_desc, 2, 1, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
17032
17033 /*
17034 * Provider_proxy returns Provider from GetFocus. The provider that
17035 * creates the node will not have GetFocus called on it to avoid returning
17036 * the same provider twice. Similarly, on nodes other than the desktop
17037 * node, the HWND provider will not have GetFocus called on it.
17038 */
17039 Provider_hwnd.focus_prov = NULL;
17041 Provider.focus_prov = Provider_hwnd2.focus_prov = &Provider2.IRawElementProviderFragment_iface;
17042
17044 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
17045 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
17046 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
17047
17048 test_node_from_focus(&cache_req, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
17049
17050 /*
17051 * Provider_nc returns Provider_nc2 from GetFocus, Provider returns
17052 * Provider2, Provider_nc3 returns Provider_child.
17053 */
17055 Provider_proxy.focus_prov = Provider_hwnd.focus_prov = Provider_hwnd2.focus_prov = NULL;
17056 Provider_nc.focus_prov = &Provider_nc2.IRawElementProviderFragment_iface;
17057 Provider.focus_prov = &Provider2.IRawElementProviderFragment_iface;
17058 Provider_nc3.focus_prov = &Provider_child.IRawElementProviderFragment_iface;
17059
17061 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
17062
17063 test_node_from_focus(&cache_req, &exp_node_desc, 2, 3, 2, 2, 1, TRUE, FALSE, FALSE, TRUE, FALSE);
17064
17065 /*
17066 * Provider_proxy returns Provider_child_child from GetFocus. The focus
17067 * provider is normalized against the cache request view condition.
17068 * Provider_child_child and its ancestors don't match the cache request
17069 * view condition, so we'll get no provider.
17070 */
17074 provider_add_child(&Provider_child, &Provider_child_child);
17075 Provider_proxy.focus_prov = &Provider_child_child.IRawElementProviderFragment_iface;
17076 Provider_nc.focus_prov = Provider_hwnd.focus_prov = NULL;
17077
17079 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
17080 set_provider_prop_override(&Provider_child_child, &prop_override, 1);
17081 set_provider_prop_override(&Provider_child, &prop_override, 1);
17082 set_provider_prop_override(&Provider, &prop_override, 1);
17083
17084 init_node_provider_desc(&exp_node_desc, 0, NULL);
17085 test_node_from_focus(&cache_req, &exp_node_desc, 2, 2, 2, 1, 0, TRUE, FALSE, FALSE, FALSE, FALSE);
17086
17087 /* This time, Provider_child matches our view condition. */
17089
17091 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
17092
17093 test_node_from_focus(&cache_req, &exp_node_desc, 1, 1, 1, 0, 0, FALSE, FALSE, FALSE, FALSE, FALSE);
17094
17099
17103 UnregisterClassA("UiaNodeFromFocus class", NULL);
17104 UnregisterClassA("UiaNodeFromFocus child class", NULL);
17105}
17106
17107static const struct prov_method_sequence event_seq1[] = {
17108 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win8+. */
17109 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Only called on Arabic version of Win10+. */
17110 { 0 },
17111};
17112
17113static const struct prov_method_sequence event_seq2[] = {
17115 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
17117 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Called twice on Win11. */
17118 NODE_CREATE_SEQ_OPTIONAL(&Provider), /* Only done in Win11. */
17119 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win8+. */
17120 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
17122 { 0 },
17123};
17124
17125static const struct prov_method_sequence event_seq3[] = {
17127 /* The following four methods are only called on Arabic versions of Win10+. */
17130 { &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
17132 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win8+. */
17135 { 0 },
17136};
17137
17138static const struct prov_method_sequence event_seq4[] = {
17140 { 0 },
17141};
17142
17143static const struct prov_method_sequence event_seq5[] = {
17145 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
17147 { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Called twice on Win11. */
17149 NODE_CREATE_SEQ_OPTIONAL(&Provider), /* Only done in Win11. */
17150 { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win8+. */
17151 { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
17153 { 0 },
17154};
17155
17156static const struct prov_method_sequence event_seq6[] = {
17160 { 0 },
17161};
17162
17163static struct EventData {
17168
17172
17173static void set_event_data_struct(struct EventData *data, LONG exp_lbound0, LONG exp_lbound1, LONG exp_elems0,
17174 LONG exp_elems1, struct node_provider_desc *exp_node_desc, const WCHAR *exp_tree_struct)
17175{
17176 data->exp_lbound[0] = exp_lbound0;
17177 data->exp_lbound[1] = exp_lbound1;
17178 data->exp_elems[0] = exp_elems0;
17179 data->exp_elems[1] = exp_elems1;
17180 if (exp_node_desc)
17181 {
17182 int i;
17183
17184 data->exp_node_desc = *exp_node_desc;
17185 for (i = 0; i < exp_node_desc->prov_count; i++)
17186 {
17187 if (exp_node_desc->nested_desc[i])
17188 {
17189 data->exp_nested_node_desc = *exp_node_desc->nested_desc[i];
17190 data->exp_node_desc.nested_desc[i] = &data->exp_nested_node_desc;
17191 break;
17192 }
17193 }
17194 }
17195 else
17196 memset(&data->exp_node_desc, 0, sizeof(data->exp_node_desc));
17197 data->exp_tree_struct = exp_tree_struct;
17198}
17199
17200static void set_event_data(LONG exp_lbound0, LONG exp_lbound1, LONG exp_elems0, LONG exp_elems1,
17201 struct node_provider_desc *exp_node_desc, const WCHAR *exp_tree_struct)
17202{
17203 set_event_data_struct(&EventData, exp_lbound0, exp_lbound1, exp_elems0, exp_elems1, exp_node_desc,
17204 exp_tree_struct);
17205}
17206
17207#define check_event_data( data, args, req_data, tree_struct ) \
17208 check_event_data_( (data), (args), (req_data), (tree_struct), __FILE__, __LINE__)
17209static void check_event_data_(struct EventData *data, struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct,
17210 const char *file, int line)
17211{
17212 if (!data->exp_elems[0] && !data->exp_elems[1])
17213 ok(!req_data, "req_data != NULL\n");
17214 else
17215 test_cache_req_sa_(req_data, data->exp_lbound, data->exp_elems, &data->exp_node_desc, file, line);
17216
17217 ok(!wcscmp(tree_struct, data->exp_tree_struct), "tree structure %s\n", debugstr_w(tree_struct));
17218 if (data->event_handle)
17219 SetEvent(data->event_handle);
17220}
17221
17222static void WINAPI uia_event_callback(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
17223{
17225 check_event_data(&EventData, args, req_data, tree_struct);
17226}
17227
17228static void WINAPI uia_event_callback2(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
17229{
17231 check_event_data(&EventData2, args, req_data, tree_struct);
17232}
17233
17234enum {
17241};
17242
17243enum {
17247};
17248
17251{
17253 return NULL;
17254 else
17255 return event_test_provs[idx];
17256}
17257
17258static void post_event_message(HWND hwnd, int msg, WPARAM wparam, int prov_id, int lparam_lower)
17259{
17260 PostMessageW(hwnd, msg, wparam, MAKELONG(lparam_lower, prov_id));
17261}
17262
17264{
17265 IRawElementProviderFragmentRoot *embedded_root = &Provider_hwnd2.IRawElementProviderFragmentRoot_iface;
17266 struct node_provider_desc exp_node_desc, exp_nested_node_desc;
17267 struct UiaCacheRequest cache_req;
17268 HUIAEVENT event;
17269 HUIANODE node;
17270 BOOL is_win11;
17271 HRESULT hr;
17272 DWORD pid;
17273 HWND hwnd;
17274
17276 hwnd = FindWindowA("UiaAddEvent test class", "Test window");
17279
17280 /* Provider_proxy/hwnd/nc are desktop providers. */
17282 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
17283 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
17284 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
17285
17286 /*
17287 * Provider_nc2/Provider_hwnd2 are clientside providers for our test
17288 * window.
17289 */
17290 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
17291 provider_add_child(&Provider_hwnd, &Provider_hwnd2);
17292
17294 SET_EXPECT(prov_callback_base_hwnd);
17295 SET_EXPECT(prov_callback_nonclient);
17296 SET_EXPECT(prov_callback_proxy);
17298 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17299 ok(!!node, "Node == NULL.\n");
17300 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
17301 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
17302 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
17303 CHECK_CALLED(prov_callback_base_hwnd);
17304 CHECK_CALLED(prov_callback_nonclient);
17305 CHECK_CALLED(prov_callback_proxy);
17306
17308
17309 /* Register an event on the desktop HWND with a scope of all elements. */
17312 event = NULL;
17313 /* Only done on Win11. */
17314 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
17315 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
17316 SET_EXPECT_MULTI(prov_callback_proxy, 2);
17317 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants,
17318 NULL, 0, &cache_req, &event);
17319 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17320 ok(!!event, "event == NULL\n");
17321 is_win11 = !!CALLED_COUNT(prov_callback_base_hwnd);
17322 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, 2);
17323 CHECK_CALLED_AT_MOST(prov_callback_nonclient, 2);
17324 CHECK_CALLED_AT_MOST(prov_callback_proxy, 2);
17326
17327 /*
17328 * Raise event in another process, prior to calling UiaEventAddWindow.
17329 * Event handler will not get triggered.
17330 */
17332 ok(WaitForSingleObject(EventData.event_handle, 300) == WAIT_TIMEOUT, "Wait for event_handle didn't timeout.\n");
17334
17335 /* Call UiaEventAddWindow, the event will now be connected. */
17336 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
17337 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
17338 SET_EXPECT_MULTI(prov_callback_proxy, 3);
17340 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17341 CHECK_CALLED(prov_callback_base_hwnd);
17342 CHECK_CALLED(prov_callback_nonclient);
17343 todo_wine CHECK_CALLED(prov_callback_proxy);
17344 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED, UIA_AutomationFocusChangedEventId, PROVIDER_ID, FALSE);
17345
17346 /* Successfully raise event. */
17348 init_node_provider_desc(&exp_nested_node_desc, pid, hwnd);
17349 add_provider_desc(&exp_nested_node_desc, L"Main", L"Provider", TRUE);
17350
17352 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", TRUE);
17353 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", FALSE);
17354 add_nested_provider_desc(&exp_node_desc, L"Main", NULL, FALSE, &exp_nested_node_desc);
17355 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17356
17357 SET_EXPECT(prov_callback_base_hwnd);
17358 SET_EXPECT(prov_callback_nonclient);
17359 SET_EXPECT(prov_callback_proxy);
17362 ok(!WaitForSingleObject(EventData.event_handle, 2000), "Wait for event_handle failed.\n");
17364 CHECK_CALLED(prov_callback_base_hwnd);
17365 CHECK_CALLED(prov_callback_nonclient);
17366 todo_wine CHECK_CALLED(prov_callback_proxy);
17367
17368 /*
17369 * If a clientside provider raises an event, it stays within its own
17370 * process.
17371 */
17373 ok(WaitForSingleObject(EventData.event_handle, 300) == WAIT_TIMEOUT, "Wait for event_handle didn't timeout.\n");
17374
17375 /* Raise serverside event. */
17377 init_node_provider_desc(&exp_node_desc, pid, NULL);
17378 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
17379 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17380
17383 ok(!WaitForSingleObject(EventData.event_handle, 2000), "Wait for event_handle failed.\n");
17385
17387 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17389
17393
17394 /*
17395 * Register an event on the desktop node, except this time the scope
17396 * doesn't include the desktop node itself. In this case, navigation will
17397 * have to be done to confirm a provider that raised an event is a
17398 * descendant of the desktop, but not the desktop itself.
17399 *
17400 * No need for UiaEventAddWindow this time, because Provider_hwnd2 is an
17401 * embedded root. This method no longer works on Windows 11, which breaks
17402 * the managed UI Automation API. We match the old behavior instead.
17403 */
17404 Provider_hwnd.embedded_frag_roots = &embedded_root;
17405 Provider_hwnd.embedded_frag_roots_count = 1;
17406 Provider_hwnd2.frag_root = &Provider_hwnd2.IRawElementProviderFragmentRoot_iface;
17407
17408 event = NULL;
17409 /* Only done on Win11. */
17410 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
17411 SET_EXPECT_MULTI(prov_callback_nonclient, 3);
17412 SET_EXPECT_MULTI(prov_callback_proxy, 3);
17413 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Descendants,
17414 NULL, 0, &cache_req, &event);
17415 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17416 ok(!!event, "event == NULL\n");
17417 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
17418 CHECK_CALLED_AT_MOST(prov_callback_base_hwnd, 2);
17419 CHECK_CALLED_AT_MOST(prov_callback_nonclient, 3);
17420 CHECK_CALLED_AT_MOST(prov_callback_proxy, 3);
17421
17422 if (is_win11)
17423 {
17425 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
17426 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
17427 SET_EXPECT_MULTI(prov_callback_proxy, 3);
17429 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17430 CHECK_CALLED_MULTI(prov_callback_base_hwnd, 2);
17431 CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
17432 CHECK_CALLED_MULTI(prov_callback_proxy, 3);
17433 }
17434
17435 post_event_message(hwnd, WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED, UIA_AutomationFocusChangedEventId, PROVIDER_ID, FALSE);
17436
17437 /*
17438 * Starts navigation in server process, then completes navigation in the
17439 * client process.
17440 */
17442 init_node_provider_desc(&exp_node_desc, pid, NULL);
17443 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
17444 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17445 SET_EXPECT(prov_callback_base_hwnd);
17446 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
17447 SET_EXPECT_MULTI(prov_callback_proxy, 2);
17449
17451 ok(!WaitForSingleObject(EventData.event_handle, 5000), "Wait for event_handle failed.\n");
17452 CHECK_CALLED(prov_callback_base_hwnd);
17453 CHECK_CALLED_MULTI(prov_callback_nonclient, 2);
17454 todo_wine CHECK_CALLED_MULTI(prov_callback_proxy, 2);
17456
17458 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17460
17461 /*
17462 * Register an event on a node that won't require any navigation to reach.
17463 */
17465 Provider.runtime_id[0] = 0x1337;
17466 Provider.runtime_id[1] = 0xbeef;
17468 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17469 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17470
17471 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element,
17472 NULL, 0, &cache_req, &event);
17473 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17474 ok(!!event, "event == NULL\n");
17475 ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
17476
17477 SET_EXPECT_MULTI(prov_callback_base_hwnd, 2);
17478 SET_EXPECT_MULTI(prov_callback_nonclient, 2);
17479 SET_EXPECT_MULTI(prov_callback_proxy, 3);
17481 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17482 CHECK_CALLED(prov_callback_base_hwnd);
17483 CHECK_CALLED(prov_callback_nonclient);
17484 todo_wine CHECK_CALLED(prov_callback_proxy);
17485
17486 /* Wrong runtime ID, no match. */
17488 ok(WaitForSingleObject(EventData.event_handle, 500) == WAIT_TIMEOUT, "Wait for event_handle didn't timeout.\n");
17489
17490 /* Successfully raise event. */
17492 init_node_provider_desc(&exp_node_desc, pid, NULL);
17493 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
17494 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17497 ok(!WaitForSingleObject(EventData.event_handle, 2000), "Wait for event_handle failed.\n");
17499
17501 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17504}
17505
17507 HUIAEVENT event;
17509};
17510
17512{
17514 HRESULT hr;
17515
17517
17518 hr = UiaRemoveEvent(data->event);
17519 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17520 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17521 ok(Provider2.ref == 1, "Unexpected refcnt %ld\n", Provider2.ref);
17522 ok(Provider2.last_call_tid == data->exp_thread_id ||
17523 broken(Provider2.last_call_tid == GetCurrentThreadId()), "Expected method call on separate thread\n");
17524 ok(Provider2.advise_events_removed_event_id == UIA_AutomationFocusChangedEventId,
17525 "Unexpected advise event removed, event ID %d\n", Provider.advise_events_removed_event_id);
17526
17528 return 0;
17529}
17530
17531static void test_UiaAddEvent_args(HUIANODE node)
17532{
17533 struct UiaCacheRequest cache_req;
17534 HUIAEVENT event;
17535 HRESULT hr;
17536
17539
17540 /* NULL node. */
17541 hr = UiaAddEvent(NULL, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
17542 &event);
17543 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17544
17545 /* NULL event callback. */
17546 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, NULL, TreeScope_Element, NULL, 0, &cache_req,
17547 &event);
17548 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17549
17550 /* NULL cache request. */
17551 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, NULL,
17552 &event);
17553 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17554
17555 /* NULL event handle. */
17556 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
17557 NULL);
17558 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17559
17560 /* Event IDs aren't checked for validity, 1 is not a valid UIA event ID. */
17561 event = NULL;
17563 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17564 ok(!!event, "event == NULL\n");
17565
17567 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17568}
17569
17570static void test_UiaRemoveEvent_args(HUIANODE node)
17571{
17572 HRESULT hr;
17573
17575 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17576
17577 hr = UiaRemoveEvent((HUIAEVENT)node);
17578 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17579}
17580
17582{
17583 HRESULT hr;
17584
17585 hr = UiaRaiseAutomationEvent(NULL, UIA_AutomationFocusChangedEventId);
17586 ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
17587
17588 /* Returns failure code from get_ProviderOptions. */
17590 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17591 /* Windows 7 returns S_OK. */
17592 ok(hr == E_NOTIMPL || broken(hr == S_OK), "Unexpected hr %#lx.\n", hr);
17593
17594 /* Invalid event ID - doesn't return failure code. */
17596 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, 1);
17597 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17598
17599 /*
17600 * UIA_StructureChangedEventId should use UiaRaiseStructureChangedEvent.
17601 * No failure code is returned, however.
17602 */
17603 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_StructureChangedEventId);
17604 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17605}
17606
17607static void test_UiaAddEvent(const char *name)
17608{
17609 IRawElementProviderFragmentRoot *embedded_roots[2] = { &Provider_child.IRawElementProviderFragmentRoot_iface,
17610 &Provider_child2.IRawElementProviderFragmentRoot_iface };
17611 struct event_test_thread_data thread_data = { 0 };
17612 struct Provider_prop_override prop_override;
17613 struct node_provider_desc exp_node_desc;
17614 struct UiaPropertyCondition prop_cond;
17615 struct UiaCacheRequest cache_req;
17617 char cmdline[MAX_PATH];
17619 HUIAEVENT event;
17621 HUIANODE node;
17622 HANDLE thread;
17623 HRESULT hr;
17624 HWND hwnd;
17625 VARIANT v;
17626
17628
17633 provider_add_child(&Provider_child, &Provider_child_child);
17634
17635 /* Create a node with Provider as its only provider. */
17638 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17639 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17640
17641 hr = UiaGetPropertyValue(node, UIA_ProviderDescriptionPropertyId, &v);
17642 ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
17644 check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider", TRUE);
17645 VariantClear(&v);
17646
17647 /* Test valid function input arguments. */
17651
17652 /*
17653 * Raise event without any registered event handlers.
17654 */
17656 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17657 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17658 ok_method_sequence(event_seq1, "event_seq1");
17659
17660 /*
17661 * Register an event on a node without an HWND/RuntimeId. The event will
17662 * be created successfully, but without any way to match a provider to
17663 * this node, we won't be able to trigger the event handler.
17664 */
17665 event = NULL;
17669 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
17670 &event);
17671 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17672 ok(!!event, "event == NULL\n");
17673 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
17674 ok_method_sequence(event_seq2, "event_seq2");
17675
17676 /*
17677 * Even though we raise an event on the same provider as the one our node
17678 * currently represents, without an HWND/RuntimeId, we have no way to
17679 * match them. The event handler will not be called.
17680 */
17681 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17682 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17683 ok_method_sequence(event_seq3, "event_seq3");
17684
17686 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17687 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17688 ok_method_sequence(event_seq4, "event_seq4");
17689
17690 /*
17691 * Register an event on the same node again, except this time we have a
17692 * runtimeID. Nodes returned to the event handler are normalized against
17693 * the cache request view condition.
17694 */
17695 event = NULL;
17697 set_property_condition(&prop_cond, UIA_IsControlElementPropertyId, &v, PropertyConditionFlags_None);
17698 set_cache_request(&cache_req, (struct UiaCondition *)&prop_cond, TreeScope_Element, NULL, 0, NULL, 0,
17700
17701 Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
17702 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
17703 &event);
17704 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17705 ok(!!event, "event == NULL\n");
17706 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
17707 ok_method_sequence(event_seq2, "event_seq2");
17708
17709 /* Event callback is now invoked since we can match by runtime ID. */
17712 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
17713 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17715 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17716 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17718
17719 /*
17720 * Runtime ID matches so event callback is invoked, but nothing matches
17721 * the cache request view condition, so the callback will be passed a
17722 * NULL cache request.
17723 */
17725 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
17726 set_provider_prop_override(&Provider, &prop_override, 1);
17727
17728 set_event_data(0, 0, 0, 0, &exp_node_desc, L"");
17730 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17731 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17734
17737 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17738 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17739 ok_method_sequence(event_seq4, "event_seq4");
17740
17741 /* Create an event with TreeScope_Children. */
17742 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Children, NULL, 0, &cache_req,
17743 &event);
17744 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17745 ok(!!event, "event == NULL\n");
17746 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
17747 ok_method_sequence(event_seq5, "event_seq5");
17748
17749 /*
17750 * Only TreeScope_Children and not TreeScope_Element, handler won't be
17751 * called.
17752 */
17754 hr = UiaRaiseAutomationEvent(&Provider.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17755 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17756
17757 /* Provider_child_child is not a direct child, handler won't be called. */
17758 hr = UiaRaiseAutomationEvent(&Provider_child_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17759 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17760
17761 /* Raised an event on Provider_child, handler will be called. */
17763 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
17764 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17766 hr = UiaRaiseAutomationEvent(&Provider_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17767 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17769
17770 /* Provider_child doesn't match the view condition, but Provider does. */
17772 set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
17773 set_provider_prop_override(&Provider_child, &prop_override, 1);
17774
17776 add_provider_desc(&exp_node_desc, L"Main", L"Provider", TRUE);
17777 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17779 hr = UiaRaiseAutomationEvent(&Provider_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17780 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17783
17785 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17786 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17787
17788 /* Create an event with TreeScope_Descendants. */
17789 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
17790 &cache_req, &event);
17791 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17792 ok(!!event, "event == NULL\n");
17793 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
17794
17795 /* Raised an event on Provider_child_child. */
17797 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child_child", TRUE);
17798 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17800 hr = UiaRaiseAutomationEvent(&Provider_child_child.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17801 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17803
17805 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17806 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17807
17809
17810 /*
17811 * When adding an event, each node provider's fragment root is queried
17812 * for, and if one is retrieved, it's IRawElementProviderAdviseEvents
17813 * interface is used. On Win10v1809+, ProviderOptions_UseComThreading is
17814 * respected for these interfaces. Set Provider2 as the fragment root here
17815 * to test this.
17816 */
17818
17821 Provider.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
17822 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
17823 &cache_req, &event);
17824 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17825 ok(!!event, "event == NULL\n");
17826 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17827 ok(Provider2.ref > 1, "Unexpected refcnt %ld\n", Provider2.ref);
17828 ok(!Provider.advise_events_added_event_id, "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
17829 ok(Provider2.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
17830 "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
17831
17832 thread_data.exp_thread_id = GetCurrentThreadId();
17833 thread_data.event = event;
17834 thread = CreateThread(NULL, 0, uia_add_event_test_thread, (void *)&thread_data, 0, NULL);
17836 {
17837 MSG msg;
17838
17839 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
17840 {
17843 }
17844 }
17846
17847 /* Test retrieving AdviseEvents on embedded fragment roots. */
17852 Provider.embedded_frag_roots = embedded_roots;
17854 Provider_child.frag_root = &Provider_child.IRawElementProviderFragmentRoot_iface;
17855 Provider_child2.frag_root = &Provider_child2.IRawElementProviderFragmentRoot_iface;
17856
17857 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
17858 &cache_req, &event);
17859 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17860 ok(!!event, "event == NULL\n");
17861 ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref);
17862 ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
17863 ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref);
17864 ok(Provider.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
17865 "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
17866 ok(Provider_child.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
17867 "Unexpected advise event added, event ID %d\n", Provider_child.advise_events_added_event_id);
17868 ok(Provider_child2.advise_events_added_event_id == UIA_AutomationFocusChangedEventId,
17869 "Unexpected advise event added, event ID %d\n", Provider_child2.advise_events_added_event_id);
17870
17873 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17874 ok(Provider.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
17875 ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
17876 ok(Provider_child2.ref == 1, "Unexpected refcnt %ld\n", Provider_child2.ref);
17877 ok_method_sequence(event_seq6, "event_seq6");
17878
17880 ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
17884
17885 hwnd = create_test_hwnd("UiaAddEvent test class");
17887
17888 /* Set clientside providers for our test window and the desktop. */
17890 Provider_proxy.frag_root = Provider_hwnd.frag_root = Provider_nc.frag_root = NULL;
17891 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
17892 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
17893 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
17894
17895 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd);
17896 provider_add_child(&Provider_nc, &Provider_nc2);
17901
17903 SET_EXPECT(prov_callback_base_hwnd);
17904 SET_EXPECT(prov_callback_nonclient);
17905 SET_EXPECT(prov_callback_proxy);
17907 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17908 ok(!!node, "Node == NULL.\n");
17909 ok(Provider_proxy.ref == 2, "Unexpected refcnt %ld\n", Provider_proxy.ref);
17910 ok(Provider_hwnd.ref == 2, "Unexpected refcnt %ld\n", Provider_hwnd.ref);
17911 ok(Provider_nc.ref == 2, "Unexpected refcnt %ld\n", Provider_nc.ref);
17912 CHECK_CALLED(prov_callback_base_hwnd);
17913 CHECK_CALLED(prov_callback_nonclient);
17914 CHECK_CALLED(prov_callback_proxy);
17915
17916 /* Register an event on the desktop HWND. */
17919 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Children, NULL, 0,
17920 &cache_req, &event);
17921 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17922 ok(!!event, "event == NULL\n");
17923
17924 /*
17925 * Raising an event on a serverside provider results in no clientside
17926 * providers being added for the HWND, which means we won't match this
17927 * event.
17928 */
17929 Provider_hwnd2.prov_opts = ProviderOptions_ServerSideProvider;
17930 hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17931 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17932
17933 /* Now that Provider has clientside providers, the event will be matched. */
17934 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
17935 SET_EXPECT(prov_callback_base_hwnd);
17936 SET_EXPECT(prov_callback_nonclient);
17937 SET_EXPECT_MULTI(prov_callback_proxy, 2);
17939 add_provider_desc(&exp_node_desc, L"Main", L"Provider", FALSE);
17940 add_provider_desc(&exp_node_desc, L"Nonclient", L"Provider_nc2", TRUE);
17941 add_provider_desc(&exp_node_desc, L"Hwnd", L"Provider_hwnd2", FALSE);
17942 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17944 Provider_hwnd2.prov_opts = ProviderOptions_ClientSideProvider;
17945 hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17946 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17947 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
17948 CHECK_CALLED(prov_callback_base_hwnd);
17949 CHECK_CALLED(prov_callback_nonclient);
17950 todo_wine CHECK_CALLED_MULTI(prov_callback_proxy, 2);
17952
17954 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17955
17956 /*
17957 * Register an event on the desktop HWND with a scope of TreeScope_Element
17958 * and TreeScope_Descendants. This is a special case where all providers
17959 * will match, regardless of whether or not they can navigate to the
17960 * desktop node.
17961 */
17964 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
17965 &cache_req, &event);
17966 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17967 ok(!!event, "event == NULL\n");
17968
17969 /*
17970 * Raise an event on Provider2 - completely disconnected from all other
17971 * providers, will still trigger the event callback.
17972 */
17975 add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
17976 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17978 hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17979 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17981
17982 /*
17983 * No clientside providers to match us to the desktop node through
17984 * navigation, but event will still be triggered.
17985 */
17987 add_provider_desc(&exp_node_desc, L"Main", L"Provider_hwnd2", TRUE);
17988 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
17990 Provider_hwnd2.prov_opts = ProviderOptions_ServerSideProvider;
17991 Provider_hwnd2.ignore_hwnd_prop = TRUE;
17992 hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
17993 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
17995
17997 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18000
18001 /* Cross process event tests. */
18008
18010 sprintf(cmdline, "\"%s\" uiautomation UiaAddEvent_client_proc", name);
18011 memset(&startup, 0, sizeof(startup));
18012 startup.cb = sizeof(startup);
18013 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 22);
18014 /* Only sent on Win7. */
18015 SET_EXPECT(winproc_GETOBJECT_CLIENT);
18016
18019 {
18020 struct Provider *prov;
18021 MSG msg = { 0 };
18022
18023 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
18024 {
18025 switch (msg.message)
18026 {
18028 {
18029 int i;
18030
18031 for (i = 0; i < ARRAY_SIZE(event_test_provs); i++)
18033 break;
18034 }
18035
18038 if (!(prov = get_event_test_prov(HIWORD(msg.lParam))))
18039 break;
18040
18042 todo_wine_if(LOWORD(msg.lParam)) ok(prov->advise_events_added_event_id == msg.wParam,
18043 "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id);
18044 else
18046 "Unexpected advise event removed, event ID %d\n", Provider.advise_events_removed_event_id);
18047 break;
18048
18052 if (!(prov = get_event_test_prov(HIWORD(msg.lParam))))
18053 break;
18054
18055 if ((msg.message == WM_UIA_TEST_RAISE_EVENT) || (msg.message == WM_UIA_TEST_SET_EVENT_PROVIDER_DATA))
18056 {
18057 prov->prov_opts = LOWORD(msg.lParam);
18058 prov->hwnd = UlongToHandle(msg.wParam);
18059 prov->ignore_hwnd_prop = !!prov->hwnd;
18060 }
18061 else if (msg.message == WM_UIA_TEST_RAISE_EVENT_RT_ID)
18062 {
18063 prov->runtime_id[0] = LOWORD(msg.lParam);
18064 prov->runtime_id[1] = msg.wParam;
18065 }
18066
18068 {
18069 hr = UiaRaiseAutomationEvent(&prov->IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
18070 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18071 }
18072 break;
18073
18074 default:
18075 prov = NULL;
18076 break;
18077 }
18078
18081 }
18082 }
18083
18084 CHECK_CALLED_AT_LEAST(winproc_GETOBJECT_UiaRoot, 5);
18085 GetExitCodeProcess(proc.hProcess, &exit_code);
18086 if (exit_code > 255)
18087 ok(0, "unhandled exception %08x in child process %04x\n", (UINT)exit_code, (UINT)GetProcessId(proc.hProcess));
18088 else if (exit_code)
18089 ok(0, "%u failures in child process\n", (UINT)exit_code);
18090 CloseHandle(proc.hProcess);
18091
18095 UnregisterClassA("UiaAddEvent test class", NULL);
18096}
18097
18100 /* Windows 10+ calls this. */
18102 { 0 }
18103};
18104
18106{
18107 BOOL ret_val;
18108 HWND hwnd;
18109
18111 hwnd = create_test_hwnd("UiaHasServerSideProvider test class");
18112
18113 /* NULL hwnd. */
18114 ret_val = UiaHasServerSideProvider(NULL);
18115 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
18116
18117 /* Desktop window has no serverside providers. */
18120 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
18121
18122 /* No provider to pass to UiaReturnRawElementProvider, returns FALSE. */
18123 prov_root = NULL;
18124 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
18125 ret_val = UiaHasServerSideProvider(hwnd);
18126 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
18127 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
18128
18129 /*
18130 * Provider passed to UiaReturnRawElementProvider returns a failure from
18131 * get_ProviderOptions. Returns FALSE.
18132 */
18135 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
18136 ret_val = UiaHasServerSideProvider(hwnd);
18137 ok(!ret_val, "UiaHasServerSideProvider returned TRUE\n");
18139 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
18140
18141 /* Successfully return a provider from UiaReturnRawElementProvider. */
18143 SET_EXPECT(winproc_GETOBJECT_UiaRoot);
18144 ret_val = UiaHasServerSideProvider(hwnd);
18145 ok(ret_val, "UiaHasServerSideProvider returned FALSE\n");
18146 ok_method_sequence(serverside_prov_seq, "serverside_prov_seq");
18147 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
18148
18150 prov_root = NULL;
18153 UnregisterClassA("UiaHasServerSideProvider test class", NULL);
18154}
18155
18158 { &Provider_hwnd2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
18159 { &Provider_nc2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
18160 { &Provider_hwnd2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
18161 { &Provider_nc2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT },
18162 { &Provider_hwnd2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT },
18165 { &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
18166 { 0 }
18167};
18168
18169#define test_uia_event_win_event_mapping( win_event, hwnd, obj_id, child_id, event_handles, event_handle_count, \
18170 expect_event1, expect_event2, todo ) \
18171 test_uia_event_win_event_mapping_( (win_event), (hwnd), (obj_id), (child_id), (event_handles), (event_handle_count), \
18172 (expect_event1), (expect_event2), (todo), __FILE__, __LINE__)
18173static void test_uia_event_win_event_mapping_(DWORD win_event, HWND hwnd, LONG obj_id, LONG child_id,
18174 HANDLE *event_handles, int event_handle_count, BOOL expect_event1, BOOL expect_event2,
18175 BOOL todo, const char *file, int line)
18176{
18177 const BOOL exp_timeout = (!expect_event1 && !expect_event2);
18178 DWORD timeout_val = exp_timeout ? 500 : 3000;
18179 DWORD wait_res;
18180
18181 SET_EXPECT_MULTI(uia_event_callback, !!expect_event1);
18182 SET_EXPECT_MULTI(uia_event_callback2, !!expect_event2);
18183 if (expect_event2)
18185 NotifyWinEvent(win_event, hwnd, obj_id, child_id);
18186
18187 wait_res = msg_wait_for_all_events(event_handles, event_handle_count, timeout_val);
18188 todo_wine_if(todo) ok_(file, line)((wait_res == WAIT_TIMEOUT) == exp_timeout,
18189 "Unexpected result while waiting for event callback(s).\n");
18190 if (expect_event1)
18192 if (expect_event2)
18194}
18195
18197{
18198 struct UiaCacheRequest cache_req = { (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
18200 HWND hwnd[2] = { ((HWND *)param)[0], ((HWND *)param)[1] };
18201 struct node_provider_desc exp_node_desc;
18202 HWND tmp_hwnd, tmp_hwnd2;
18203 HUIAEVENT event, event2;
18204 HANDLE event_handles[2];
18205 HUIANODE node;
18206 HRESULT hr;
18207 int i;
18208
18211 for (i = 0; i < ARRAY_SIZE(event_handles); i++)
18212 event_handles[i] = CreateEventW(NULL, FALSE, FALSE, NULL);
18213
18214 set_uia_hwnd_expects(1, 1, 1, 2, 0);
18215 hr = UiaNodeFromHandle(hwnd[0], &node);
18216 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18217 ok(!!node, "Node == NULL.\n");
18218 check_uia_hwnd_expects_at_most(1, 1, 1, 2, 0);
18219
18220 set_uia_hwnd_expects(2, 2, 2, 4, 0);
18221 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
18222 &event);
18223 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18224 /* Windows 11 recreates HWND clientside providers for the node passed into UiaAddEvent. */
18225 check_uia_hwnd_expects_at_most(2, 2, 2, 4, 0);
18226
18227 set_uia_hwnd_expects(2, 2, 2, 4, 0);
18228 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback2, TreeScope_Subtree, NULL, 0, &cache_req,
18229 &event2);
18230 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18231 /* Windows 11 recreates HWND clientside providers for the node passed into UiaAddEvent. */
18232 check_uia_hwnd_expects_at_most(2, 2, 2, 4, 0);
18234
18235 /*
18236 * Raise EVENT_OBJECT_FOCUS. If none of our clientside providers returned
18237 * an IProxyProviderWinEventHandler interface when being advised of events
18238 * being listened for, nothing happens.
18239 */
18240 EventData.event_handle = event_handles[0];
18241 EventData2.event_handle = event_handles[1];
18242 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18243 ARRAY_SIZE(event_handles), FALSE, FALSE, FALSE);
18244
18245 /*
18246 * Return an IProxyProviderWinEventHandler interface on our clientside
18247 * providers. WinEvents will now be listened for. If a provider returns a
18248 * WinEvent handler interface, IRawElementProviderAdviseEvents will not be
18249 * queried for or used.
18250 */
18253 Provider_hwnd2.win_event_handler_data.is_supported = Provider_nc2.win_event_handler_data.is_supported = TRUE;
18254 set_uia_hwnd_expects(1, 1, 1, 2, 0);
18256 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18257 test_provider_event_advise_added(&Provider_hwnd2, 0, FALSE);
18258 test_provider_event_advise_added(&Provider_nc2, 0, FALSE);
18260
18261 /*
18262 * WinEvents will now be listened for, however if our HWND has a
18263 * serverside provider they will be ignored.
18264 */
18265 SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2); /* Only called twice on Win11. */
18266 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18267 1, FALSE, FALSE, FALSE);
18268 CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
18269
18270 /*
18271 * Get rid of our serverside provider and raise EVENT_OBJECT_FOCUS
18272 * again. Now, our WinEvent handler interfaces will be invoked.
18273 */
18274 prov_root = NULL;
18275 set_provider_win_event_handler_win_event_expects(&Provider_hwnd2, EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF);
18276 set_provider_win_event_handler_win_event_expects(&Provider_nc2, EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF);
18277
18280 set_provider_win_event_handler_respond_prov(&Provider_hwnd2, &Provider_child.IRawElementProviderSimple_iface,
18281 UIA_AutomationFocusChangedEventId);
18282
18284 add_provider_desc(&exp_node_desc, L"Main", L"Provider_child", TRUE);
18285 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
18286
18288 set_uia_hwnd_expects(1, 1, 1, 4, 3);
18289 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18290 1, TRUE, FALSE, FALSE);
18291 ok_method_sequence(win_event_handler_seq, "win_event_handler_seq");
18294
18295 /*
18296 * Not all WinEvents are passed to our WinEvent responder interface -
18297 * they're filtered by HWND.
18298 */
18299 Provider_hwnd.win_event_handler_data.is_supported = Provider_nc.win_event_handler_data.is_supported = TRUE;
18302 UIA_AutomationFocusChangedEventId);
18304 set_uia_hwnd_expects(0, 1, 1, 0, 0);
18306 if (msg_wait_for_all_events(event_handles, 1, 3000) == WAIT_OBJECT_0)
18307 {
18308 win_skip("Win10v1507 and below don't filter WinEvents by HWND, skipping further tests.\n");
18309
18311 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
18313 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18314
18315 hr = UiaRemoveEvent(event2);
18316 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18317 goto skip_win_event_hwnd_filter_test;
18318 }
18319
18320 /* Clear expects/called values. */
18322
18323 /*
18324 * Child HWNDs of top level HWNDs that are within our scope are listened
18325 * to by default.
18326 */
18328 Provider_hwnd3.win_event_handler_data.is_supported = Provider_nc3.win_event_handler_data.is_supported = TRUE;
18329 set_provider_win_event_handler_win_event_expects(&Provider_nc3, EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF);
18330 set_provider_win_event_handler_win_event_expects(&Provider_hwnd3, EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF);
18331 set_provider_win_event_handler_respond_prov(&Provider_nc3, &Provider_child.IRawElementProviderSimple_iface,
18332 UIA_AutomationFocusChangedEventId);
18333
18334 set_uia_hwnd_expects(0, 1, 1, 2, 0);
18335 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 4); /* Only sent 4 times on Win11. */
18336 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
18337 1, TRUE, FALSE, FALSE);
18339 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
18340
18341 /*
18342 * Child HWND now has a serverside provider, WinEvent is ignored.
18343 */
18344 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
18345
18346 SET_EXPECT(winproc_GETOBJECT_UiaRoot); /* Only sent on Win11. */
18347 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only sent 2 times on Win11. */
18348 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
18349 1, FALSE, FALSE, FALSE);
18350 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
18351 CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, 1);
18352
18353 /*
18354 * HWNDs owned by a top level HWND that is within our scope are ignored.
18355 */
18357 tmp_hwnd = CreateWindowA("ProxyProviderWinEventHandler test child class", "Test child window 2", WS_POPUP,
18358 0, 0, 50, 50, hwnd[0], NULL, NULL, NULL);
18359 Provider_nc3.hwnd = Provider_hwnd3.hwnd = tmp_hwnd;
18360 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, tmp_hwnd, OBJID_WINDOW, CHILDID_SELF, event_handles,
18361 1, FALSE, FALSE, FALSE);
18362 DestroyWindow(tmp_hwnd);
18363
18364 /*
18365 * Add our test child HWND to event2. This only puts the child HWND within
18366 * the scope of event2, it doesn't put the parent HWND within its scope.
18367 */
18368 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
18369 Provider_nc3.hwnd = Provider_hwnd3.hwnd = hwnd[1];
18370 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only sent 2 times on Win11. */
18371 set_uia_hwnd_expects(0, 1, 1, 1, 0);
18372 hr = UiaEventAddWindow(event2, hwnd[1]);
18373 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18375 CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
18376
18377 /*
18378 * Raise a WinEvent on our top level test HWND, will not invoke the
18379 * callback on event2.
18380 */
18381 set_uia_hwnd_expects(1, 1, 1, 4, 3);
18382 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18383 1, TRUE, FALSE, FALSE);
18385
18386 /* Raise a WinEvent on our test child HWND, both event callbacks invoked. */
18388 set_event_data_struct(&EventData2, 0, 0, 1, 1, &exp_node_desc, L"P)");
18389
18390 set_uia_hwnd_expects(0, 2, 2, 4, 0);
18391 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 8); /* Only sent 8 times on Win11. */
18392 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
18393 ARRAY_SIZE(event_handles), TRUE, TRUE, FALSE);
18394 CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
18396
18397 /*
18398 * Raise a WinEvent on a descendant HWND of our test HWND. If any ancestor
18399 * in the parent chain of HWNDs up to the root HWND is within scope, this
18400 * WinEvent is within scope.
18401 */
18402 tmp_hwnd = CreateWindowA("ProxyProviderWinEventHandler test child class", "Test child window 2", WS_CHILD,
18403 0, 0, 50, 50, hwnd[1], NULL, NULL, NULL);
18404 tmp_hwnd2 = CreateWindowA("ProxyProviderWinEventHandler test child class", "Test child window 3", WS_CHILD,
18405 0, 0, 50, 50, tmp_hwnd, NULL, NULL, NULL);
18406 set_provider_win_event_handler_win_event_expects(&Provider_nc3, EVENT_OBJECT_FOCUS, tmp_hwnd2, OBJID_WINDOW, CHILDID_SELF);
18407 set_provider_win_event_handler_win_event_expects(&Provider_hwnd3, EVENT_OBJECT_FOCUS, tmp_hwnd2, OBJID_WINDOW, CHILDID_SELF);
18408 Provider_nc3.hwnd = Provider_hwnd3.hwnd = tmp_hwnd2;
18409
18410 set_uia_hwnd_expects(0, 2, 2, 0, 0);
18411 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 12); /* Only sent 12 times on Win11. */
18412 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, tmp_hwnd2, OBJID_WINDOW, CHILDID_SELF, event_handles,
18413 ARRAY_SIZE(event_handles), TRUE, TRUE, FALSE);
18414 CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
18416
18417 DestroyWindow(tmp_hwnd);
18418 Provider_nc3.hwnd = Provider_hwnd3.hwnd = hwnd[1];
18419 set_provider_win_event_handler_win_event_expects(&Provider_nc3, EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF);
18420 set_provider_win_event_handler_win_event_expects(&Provider_hwnd3, EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF);
18421
18423 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18424
18425 hr = UiaRemoveEvent(event2);
18426 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18427
18428 /*
18429 * Create an event on the desktop HWND. If a WinEvent handler interface is
18430 * returned on a provider representing the desktop HWND, all visible
18431 * top-level HWNDs at the time of advisement will be considered within
18432 * scope.
18433 */
18434 set_uia_hwnd_expects(1, 1, 1, 0, 0);
18436 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18437 ok(!!node, "Node == NULL.\n");
18438 check_uia_hwnd_expects(1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
18439
18440 Provider_proxy.win_event_handler_data.is_supported = TRUE;
18441 Provider_hwnd.win_event_handler_data.is_supported = Provider_nc.win_event_handler_data.is_supported = TRUE;
18445 UIA_AutomationFocusChangedEventId);
18446
18447 /* Register a focus change event handler on the desktop HWND. */
18448 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
18449 &event);
18450 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18454
18455 /* Raise WinEvent on the desktop HWND. */
18458 UIA_AutomationFocusChangedEventId);
18459 set_uia_hwnd_expects(0, 1, 1, 0, 0);
18460 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, GetDesktopWindow(), OBJID_WINDOW, CHILDID_SELF, event_handles,
18461 1, TRUE, FALSE, FALSE);
18462 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
18463
18464 /*
18465 * Top-level HWND, a child of the desktop HWND. Will not have an event
18466 * raised since it was not visible when the desktop providers were advised
18467 * of an event being added.
18468 */
18469 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18470 1, FALSE, FALSE, FALSE);
18471
18472 /* Test child hwnd, same deal. */
18473 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
18474 1, FALSE, FALSE, FALSE);
18475
18476 /*
18477 * Show window after calling UiaAddEvent(), does nothing. Window must be
18478 * visible when provider is advised of an event being added.
18479 */
18480 ShowWindow(hwnd[0], SW_SHOW);
18481 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18482 1, FALSE, FALSE, FALSE);
18483
18485 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18486
18487 /*
18488 * Create the event again, except this time our test HWND was visible when
18489 * the desktop provider was advised that our event was being added. Now
18490 * WinEvents on our test HWND will be handled.
18491 */
18492 hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element, NULL, 0, &cache_req,
18493 &event);
18494 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18498
18499 /* WinEvent handled. */
18500 set_uia_hwnd_expects(1, 1, 1, 2, 1);
18501 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
18502 1, TRUE, FALSE, FALSE);
18503 check_uia_hwnd_expects(1, TRUE, 1, FALSE, 1, FALSE, 2, FALSE, 1, FALSE);
18504
18505 /* Child HWNDs of our test window are handled as well. */
18506 SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2);
18507 set_uia_hwnd_expects(0, 1, 1, 1, 0);
18508 test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
18509 1, TRUE, FALSE, FALSE);
18510 check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
18511
18513 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18514
18516
18517skip_win_event_hwnd_filter_test:
18518 /*
18519 * Test default MSAA proxy WinEvent handler.
18520 */
18522 set_uia_hwnd_expects(2, 1, 1, 2, 0);
18523 hr = UiaNodeFromHandle(hwnd[0], &node);
18524 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18525 ok(!!node, "Node == NULL.\n");
18526 check_uia_hwnd_expects_at_most(1, 1, 1, 2, 0);
18527
18528 Provider_hwnd2.win_event_handler_data.is_supported = Provider_nc2.win_event_handler_data.is_supported = TRUE;
18529 hr = UiaAddEvent(node, UIA_SystemAlertEventId, uia_event_callback, TreeScope_Subtree, NULL, 0, &cache_req,
18530 &event);
18531 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18533
18535 set_provider_win_event_handler_win_event_expects(&Provider_hwnd2, 0, hwnd[0], 0, 0);
18538
18539 prov_root = NULL;
18541 add_provider_desc(&exp_node_desc, L"Main", NULL, TRUE); /* MSAA proxy. */
18542 set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
18543
18544 /* WinEvent handled by default MSAA proxy provider. */
18545 set_uia_hwnd_expects(1, 1, 1, 4, 5);
18546 test_uia_event_win_event_mapping(EVENT_SYSTEM_ALERT, hwnd[0], OBJID_CLIENT, 2, event_handles,
18547 1, TRUE, FALSE, FALSE);
18548 check_uia_hwnd_expects_at_most(1, 1, 1, 4, 5);
18549
18551 ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
18552
18553 for (i = 0; i < ARRAY_SIZE(event_handles); i++)
18554 CloseHandle(event_handles[i]);
18557 return 0;
18558}
18559
18561{
18562 HANDLE thread;
18563 HWND hwnd[2];
18564
18565 /*
18566 * Windows 7 behaves different than all other versions, just skip the
18567 * tests.
18568 */
18569 if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID))
18570 {
18571 win_skip("Skipping IProxyProviderWinEventSink tests for Win7\n");
18572 return;
18573 }
18574
18576
18577 hwnd[0] = create_test_hwnd("ProxyProviderWinEventHandler test class");
18578 hwnd[1] = create_child_test_hwnd("ProxyProviderWinEventHandler test child class", hwnd[0]);
18579
18581
18582 /* Set clientside providers for our test windows and the desktop. */
18584 base_hwnd_prov = &Provider_hwnd.IRawElementProviderSimple_iface;
18585 nc_prov = &Provider_nc.IRawElementProviderSimple_iface;
18586 proxy_prov = &Provider_proxy.IRawElementProviderSimple_iface;
18587
18588 set_clientside_providers_for_hwnd(NULL, &Provider_nc2, &Provider_hwnd2, hwnd[0]);
18592
18593 set_clientside_providers_for_hwnd(NULL, &Provider_nc3, &Provider_hwnd3, hwnd[1]);
18595 Provider2.frag_root = &Provider2.IRawElementProviderFragmentRoot_iface;
18596 Provider2.ignore_hwnd_prop = TRUE;
18597
18599 child_win_prov_root = &Provider2.IRawElementProviderSimple_iface;
18600
18603 {
18604 MSG msg;
18605
18606 while (PeekMessageW(&msg, 0, 0, 0, PM_REMOVE))
18607 {
18610 }
18611 }
18613
18615 destroy_test_hwnd(hwnd[0], "ProxyProviderWinEventHandler test class", "ProxyProviderWinEventHandler test child class");
18617}
18618
18620{
18621 BOOL ret;
18622
18623 /* Always returns TRUE on Windows 7 and above. */
18625 ok(!!ret, "ret != TRUE\n");
18626}
18627
18628/*
18629 * Once a process returns a UI Automation provider with
18630 * UiaReturnRawElementProvider it ends up in an implicit MTA until exit. This
18631 * messes with tests around COM initialization, so we run these tests in
18632 * separate processes.
18633 */
18634static void launch_test_process(const char *name, const char *test_name)
18635{
18638 char cmdline[MAX_PATH];
18639
18640 sprintf(cmdline, "\"%s\" uiautomation %s", name, test_name);
18641 memset(&startup, 0, sizeof(startup));
18642 startup.cb = sizeof(startup);
18644 wait_child_process(proc.hProcess);
18645}
18646
18647START_TEST(uiautomation)
18648{
18649 HMODULE uia_dll = LoadLibraryA("uiautomationcore.dll");
18650 BOOL (WINAPI *pImmDisableIME)(DWORD);
18651 HMODULE hModuleImm32;
18652 char **argv;
18653 int argc;
18654
18655 /* Make sure COM isn't initialized by imm32. */
18656 hModuleImm32 = LoadLibraryA("imm32.dll");
18657 if (hModuleImm32) {
18658 pImmDisableIME = (void *)GetProcAddress(hModuleImm32, "ImmDisableIME");
18659 if (pImmDisableIME)
18660 pImmDisableIME(0);
18661 }
18662 pImmDisableIME = NULL;
18663 FreeLibrary(hModuleImm32);
18664
18665 if (uia_dll)
18666 pUiaDisconnectProvider = (void *)GetProcAddress(uia_dll, "UiaDisconnectProvider");
18667
18669 if (argc == 3)
18670 {
18671 if (!strcmp(argv[2], "UiaNodeFromHandle"))
18673 else if (!strcmp(argv[2], "UiaNodeFromHandle_client_proc"))
18675 else if (!strcmp(argv[2], "UiaRegisterProviderCallback"))
18677 else if (!strcmp(argv[2], "UiaAddEvent_client_proc"))
18679
18680 FreeLibrary(uia_dll);
18681 return;
18682 }
18683
18692 launch_test_process(argv[0], "UiaNodeFromHandle");
18693 launch_test_process(argv[0], "UiaRegisterProviderCallback");
18696 test_UiaFind();
18704 if (uia_dll)
18705 {
18706 pUiaProviderFromIAccessible = (void *)GetProcAddress(uia_dll, "UiaProviderFromIAccessible");
18707 if (pUiaProviderFromIAccessible)
18709 else
18710 win_skip("UiaProviderFromIAccessible not exported by uiautomationcore.dll\n");
18711
18712 FreeLibrary(uia_dll);
18713 }
18714}
#define CO_E_NOTINITIALIZED
@ wparam
Definition: SystemMenu.c:30
COMPILER_DEPENDENT_UINT64 UINT64
Definition: actypes.h:131
static void startup(void)
static struct sockaddr_in sa
Definition: adnsresfilter.c:69
Arabic default style
Definition: afstyles.h:94
static int state
Definition: maze.c:121
#define InterlockedIncrement
Definition: armddk.h:53
#define InterlockedDecrement
Definition: armddk.h:52
#define trace
Definition: atltest.h:70
#define ok(value,...)
Definition: atltest.h:57
#define broken(x)
Definition: atltest.h:178
#define START_TEST(x)
Definition: atltest.h:75
#define ok_(x1, x2)
Definition: atltest.h:61
#define msg(x)
Definition: auth_time.c:54
#define ARRAY_SIZE(A)
Definition: main.h:20
static HANDLE thread
Definition: service.c:33
#define UlongToHandle(ul)
Definition: basetsd.h:91
#define HandleToUlong(h)
Definition: basetsd.h:73
#define ULongToHandle(h)
Definition: basetsd.h:75
#define HandleToULong(h)
Definition: basetsd.h:89
const GUID IID_IUnknown
static WCHAR * get_locale(void)
Definition: builtin.c:3937
RECT rect
Definition: combotst.c:67
WPARAM wParam
Definition: combotst.c:138
LPARAM lParam
Definition: combotst.c:139
#define WAIT_TIMEOUT
Definition: dderror.h:14
#define E_INVALIDARG
Definition: ddrawi.h:101
#define E_NOTIMPL
Definition: ddrawi.h:99
#define E_FAIL
Definition: ddrawi.h:102
#define realloc
Definition: debug_ros.c:6
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
HRESULT hr
Definition: delayimp.cpp:573
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned int idx
Definition: utils.c:41
HRESULT WINAPI CoGetApartmentType(APTTYPE *type, APTTYPEQUALIFIER *qualifier)
Definition: combase.c:2928
HRESULT WINAPI DECLSPEC_HOTPATCH CoInitializeEx(void *reserved, DWORD model)
Definition: combase.c:2803
void WINAPI DECLSPEC_HOTPATCH CoUninitialize(void)
Definition: combase.c:2842
HRESULT WINAPI DECLSPEC_HOTPATCH CoCreateInstance(REFCLSID rclsid, IUnknown *outer, DWORD cls_context, REFIID riid, void **obj)
Definition: combase.c:1685
HRESULT WINAPI CoMarshalInterThreadInterfaceInStream(REFIID riid, IUnknown *unk, IStream **stream)
Definition: marshal.c:154
HRESULT WINAPI CoGetInterfaceAndReleaseStream(IStream *stream, REFIID riid, void **obj)
Definition: marshal.c:139
nav_direction
Definition: monthcal.c:156
#define CloseHandle
Definition: compat.h:739
#define wcschr
Definition: compat.h:17
#define GetProcAddress(x, y)
Definition: compat.h:753
#define FreeLibrary(x)
Definition: compat.h:748
OLECHAR * BSTR
Definition: compat.h:2293
HANDLE HWND
Definition: compat.h:19
#define GetProcessId(x)
Definition: compat.h:737
#define MAX_PATH
Definition: compat.h:34
unsigned short VARTYPE
Definition: compat.h:2254
@ VT_BSTR
Definition: compat.h:2303
@ VT_INT
Definition: compat.h:2316
@ VT_UNKNOWN
Definition: compat.h:2308
@ VT_ARRAY
Definition: compat.h:2341
@ VT_R8
Definition: compat.h:2300
@ VT_VARIANT
Definition: compat.h:2307
@ VT_I8
Definition: compat.h:2314
@ VT_I4
Definition: compat.h:2298
@ VT_BOOL
Definition: compat.h:2306
@ VT_EMPTY
Definition: compat.h:2295
@ VT_DISPATCH
Definition: compat.h:2304
#define lstrcpynW
Definition: compat.h:738
HMODULE WINAPI DECLSPEC_HOTPATCH GetModuleHandleA(LPCSTR lpModuleName)
Definition: loader.c:812
HINSTANCE WINAPI DECLSPEC_HOTPATCH LoadLibraryA(LPCSTR lpLibFileName)
Definition: loader.c:111
BOOL WINAPI GetExitCodeProcess(IN HANDLE hProcess, IN LPDWORD lpExitCode)
Definition: proc.c:1166
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
BOOL WINAPI SleepConditionVariableCS(PCONDITION_VARIABLE ConditionVariable, PCRITICAL_SECTION CriticalSection, DWORD Timeout)
Definition: sync.c:59
VOID WINAPI InitializeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:22
VOID WINAPI WakeConditionVariable(PCONDITION_VARIABLE ConditionVariable)
Definition: sync.c:98
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4152
LCID lcid
Definition: locale.c:5656
BOOL WINAPI DECLSPEC_HOTPATCH CreateProcessA(const char *app_name, char *cmd_line, SECURITY_ATTRIBUTES *process_attr, SECURITY_ATTRIBUTES *thread_attr, BOOL inherit, DWORD flags, void *env, const char *cur_dir, STARTUPINFOA *startup_info, PROCESS_INFORMATION *info)
Definition: process.c:686
ULONG WINAPI DECLSPEC_HOTPATCH GetTickCount(void)
Definition: sync.c:182
GUID guid
Definition: version.c:147
MonoAssembly int argc
Definition: metahost.c:107
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
static REFPROPVARIANT PROPVAR_CHANGE_FLAGS VARTYPE vt
Definition: suminfo.c:91
#define assert(_expr)
Definition: assert.h:32
#define __cdecl
Definition: corecrt.h:121
_ACRTIMP __msvcrt_ulong __cdecl wcstoul(const wchar_t *, wchar_t **, int)
Definition: wcs.c:2912
_ACRTIMP size_t __cdecl wcslen(const wchar_t *)
Definition: wcs.c:2983
_ACRTIMP int __cdecl wcscmp(const wchar_t *, const wchar_t *)
Definition: wcs.c:1972
_ACRTIMP wchar_t *__cdecl wcsstr(const wchar_t *, const wchar_t *)
Definition: wcs.c:2993
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
_ACRTIMP int __cdecl strcmp(const char *, const char *)
Definition: string.c:3319
LRESULT WINAPI LresultFromObject(REFIID riid, WPARAM wParam, LPUNKNOWN pAcc)
Definition: main.c:249
HRESULT WINAPI CreateStdAccessibleObject(HWND hwnd, LONG idObject, REFIID riidInterface, void **ppvObject)
Definition: main.c:154
HRESULT WINAPI SafeArrayGetUBound(SAFEARRAY *psa, UINT nDim, LONG *plUbound)
Definition: safearray.c:1033
HRESULT WINAPI SafeArrayGetElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:947
HRESULT WINAPI SafeArrayCopy(SAFEARRAY *psa, SAFEARRAY **ppsaOut)
Definition: safearray.c:1379
UINT WINAPI SafeArrayGetDim(SAFEARRAY *psa)
Definition: safearray.c:1094
SAFEARRAY *WINAPI SafeArrayCreateVector(VARTYPE vt, LONG lLbound, ULONG cElements)
Definition: safearray.c:677
HRESULT WINAPI SafeArrayGetLBound(SAFEARRAY *psa, UINT nDim, LONG *plLbound)
Definition: safearray.c:1066
HRESULT WINAPI SafeArrayDestroy(SAFEARRAY *psa)
Definition: safearray.c:1347
HRESULT WINAPI SafeArrayGetVartype(SAFEARRAY *psa, VARTYPE *pvt)
Definition: safearray.c:1534
HRESULT WINAPI SafeArrayPutElement(SAFEARRAY *psa, LONG *rgIndices, void *pvData)
Definition: safearray.c:864
method
Definition: dragdrop.c:54
return ret
Definition: mutex.c:146
#define L(x)
Definition: resources.c:13
r parent
Definition: btrfs.c:3010
int main()
Definition: test.c:6
#define INFINITE
Definition: serial.h:102
#define WM_APP
Definition: eventvwr.h:73
unsigned short WORD
Definition: ntddk_ex.h:93
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
static const FxOffsetAndName offsets[]
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
const GLdouble * v
Definition: gl.h:2040
GLuint GLuint GLsizei count
Definition: gl.h:1545
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLuint GLuint end
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLint GLint GLsizei GLsizei height
Definition: gl.h:1546
GLint GLint GLsizei width
Definition: gl.h:1546
struct _cl_event * event
Definition: glext.h:7739
GLuint * ids
Definition: glext.h:5907
GLintptr offset
Definition: glext.h:5920
GLenum condition
Definition: glext.h:9255
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:10859
GLdouble GLdouble right
Definition: glext.h:10859
GLboolean GLboolean GLboolean b
Definition: glext.h:6204
GLenum const GLfloat * params
Definition: glext.h:5645
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLint left
Definition: glext.h:7726
GLbitfield flags
Definition: glext.h:7161
GLint GLint bottom
Definition: glext.h:7726
GLuint GLfloat * val
Definition: glext.h:7180
GLfloat GLfloat p
Definition: glext.h:8902
GLfloat param
Definition: glext.h:5796
GLenum GLsizei len
Definition: glext.h:6722
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
GLfloat GLfloat v1
Definition: glext.h:6062
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
IA2ScrollType
IA2CoordinateType
long AccessibleStates
REFIID riid
Definition: atlbase.h:39
REFIID LPVOID * ppv
Definition: atlbase.h:39
static TfClientId cid
This interface exposes the primary set of information about an IAccessible2 enabled accessible object...
#define S_OK
Definition: intsafe.h:52
#define SUCCEEDED(hr)
Definition: intsafe.h:50
#define a
Definition: ke_i.h:78
#define b
Definition: ke_i.h:79
#define debugstr_guid
Definition: kernel32.h:35
#define debugstr_w
Definition: kernel32.h:32
#define wine_dbgstr_w
Definition: kernel32.h:34
void WINAPI CoTaskMemFree(void *ptr)
Definition: malloc.c:389
const char * winetest_platform
#define win_skip
Definition: minitest.h:67
#define todo_wine_if(is_todo)
Definition: minitest.h:81
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
Definition: test.h:537
#define todo_wine
Definition: minitest.h:80
LONG_PTR LPARAM
Definition: minwindef.h:175
LONG_PTR LRESULT
Definition: minwindef.h:176
UINT_PTR WPARAM
Definition: minwindef.h:174
static struct test_info tests[]
#define sprintf
Definition: sprintf.c:45
BOOL todo
Definition: filedlg.c:313
BOOL expected
Definition: store.c:2000
D3D11_SHADER_VARIABLE_DESC desc
Definition: reflection.c:1204
static const char * test_name
Definition: run.c:177
static UINT exit_code
Definition: process.c:80
CONDITION_VARIABLE cv
Definition: sync.c:1887
static const WCHAR sp[]
Definition: suminfo.c:287
static size_t elem
Definition: string.c:71
static const get_attributes_t get_attributes[]
Definition: domdoc.c:10186
#define cmp(status, error)
Definition: error.c:118
static BSTR *static LPOLESTR
Definition: varformat.c:44
static HANDLE event_handle
Definition: service.c:343
static VARIANTARG static DISPID
Definition: ordinal.c:49
static UINT UINT * out_count
Definition: clipboard.c:31
static DWORD unk1
Definition: cursoricon.c:1804
static HWND child
Definition: cursoricon.c:298
#define argv
Definition: mplay32.c:18
const CLSID * clsid
Definition: msctf.cpp:50
unsigned int UINT
Definition: ndis.h:50
direction
Definition: netio.c:882
#define BOOL
Definition: nt_native.h:43
@ COINIT_APARTMENTTHREADED
Definition: objbase.h:279
@ COINIT_MULTITHREADED
Definition: objbase.h:280
@ APTTYPEQUALIFIER_IMPLICIT_MTA
enum _APTTYPEQUALIFIER APTTYPEQUALIFIER
BSTR WINAPI SysAllocString(LPCOLESTR str)
Definition: oleaut.c:238
void WINAPI DECLSPEC_HOTPATCH SysFreeString(BSTR str)
Definition: oleaut.c:271
#define V_I8(A)
Definition: oleauto.h:249
#define V_BOOL(A)
Definition: oleauto.h:224
#define V_ARRAY(A)
Definition: oleauto.h:222
#define V_UNKNOWN(A)
Definition: oleauto.h:281
#define V_VT(A)
Definition: oleauto.h:211
#define V_BSTR(A)
Definition: oleauto.h:226
#define V_I4(A)
Definition: oleauto.h:247
#define V_DISPATCH(A)
Definition: oleauto.h:239
#define V_R8(A)
Definition: oleauto.h:262
const GUID IID_IOleWindow
const GUID IID_IDispatch
static HANDLE proc()
Definition: pdb.c:32
#define LOWORD(l)
Definition: pedump.c:82
#define ES_PASSWORD
Definition: pedump.c:670
#define WS_CHILD
Definition: pedump.c:617
#define WS_CAPTION
Definition: pedump.c:624
#define WS_OVERLAPPEDWINDOW
Definition: pedump.c:637
#define WS_MAXIMIZEBOX
Definition: pedump.c:632
#define WS_SYSMENU
Definition: pedump.c:629
short WCHAR
Definition: pedump.c:58
#define WS_BORDER
Definition: pedump.c:625
#define WS_POPUP
Definition: pedump.c:616
#define WS_VISIBLE
Definition: pedump.c:620
long LONG
Definition: pedump.c:60
#define WS_MINIMIZEBOX
Definition: pedump.c:631
#define DEFINE_GUID(name, l, w1, w2, b1, b2, b3, b4, b5, b6, b7, b8)
Definition: guiddef.h:68
#define IsEqualIID(riid1, riid2)
Definition: guiddef.h:95
#define REFIID
Definition: guiddef.h:118
#define test
Definition: rosglue.h:37
const WCHAR * str
DWORD LCID
Definition: nls.h:13
mbstowcs
Definition: stdlib.h:925
int winetest_get_mainargs(char ***pargv)
int winetest_platform_is_wine
#define wait_child_process
Definition: test.h:159
#define exit(n)
Definition: config.h:202
XML_HIDDEN void xmlParserErrors const char const xmlChar const xmlChar * str2
Definition: parser.h:35
#define memset(x, y, z)
Definition: compat.h:39
TCHAR * cmdline
Definition: stretchblt.cpp:32
LPCWSTR name
Definition: uiautomation.c:547
BOOL enable_ia2
Definition: uiautomation.c:549
LONG child_count
Definition: uiautomation.c:546
IAccessible * parent
Definition: uiautomation.c:541
INT focus_child_id
Definition: uiautomation.c:551
IAccessible IAccessible_iface
Definition: uiautomation.c:533
IServiceProvider IServiceProvider_iface
Definition: uiautomation.c:536
LONG unique_id
Definition: uiautomation.c:550
IAccessible2 IAccessible2_iface
Definition: uiautomation.c:534
IAccessible * focus_acc
Definition: uiautomation.c:552
DEFINE_ACC_METHOD_EXPECTS
Definition: uiautomation.c:553
IOleWindow IOleWindow_iface
Definition: uiautomation.c:535
const char * interface_name
Definition: uiautomation.c:539
IUIAutomationEventHandler IUIAutomationEventHandler_iface
IRawElementProviderSimple IRawElementProviderSimple_iface
enum ProviderType prov_type
HANDLE event_handle
struct ExpectedEventQueue exp_events
HANDLE event_handle
struct node_provider_desc exp_node_desc
struct node_provider_desc exp_nested_node_desc
LONG exp_elems[2]
const WCHAR * exp_tree_struct
LONG exp_lbound[2]
struct node_provider_desc exp_nested_node_desc[MAX_EVENT_QUEUE_COUNT]
struct node_provider_desc exp_node_desc[MAX_EVENT_QUEUE_COUNT]
IUIAutomationFocusChangedEventHandler IUIAutomationFocusChangedEventHandler_iface
struct ExpectedEventQueue exp_events
IRawElementProviderSimple * responder_prov
IRawElementProviderFragment IRawElementProviderFragment_iface
struct Provider_value_pattern_data value_pattern_data
IRawElementProviderFragment * prev_sibling
int advise_events_removed_event_id
struct UiaRect bounds_rect
IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface
IRawElementProviderFragment * first_child
IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface
int prop_override_count
int runtime_id[2]
BOOL ret_invalid_prop_type
int embedded_frag_roots_count
IRawElementProviderFragmentRoot * frag_root
IRawElementProviderFragment * focus_prov
const char * prov_name
int method_call_event_method_id
IRawElementProviderSimple IRawElementProviderSimple_iface
HANDLE method_call_event_handle
IRawElementProviderFragment * next_sibling
IRawElementProviderFragmentRoot ** embedded_frag_roots
ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface
struct Provider_legacy_accessible_pattern_data legacy_acc_pattern_data
BOOL ignore_hwnd_prop
DWORD last_call_tid
int advise_events_added_event_id
IProxyProviderWinEventHandler IProxyProviderWinEventHandler_iface
HWND override_hwnd
IValueProvider IValueProvider_iface
IRawElementProviderAdviseEvents IRawElementProviderAdviseEvents_iface
DWORD expected_tid
IRawElementProviderFragment * last_child
IRawElementProviderFragment * parent
enum ProviderOptions prov_opts
struct Provider_prop_override * prop_override
struct Provider_win_event_handler_data win_event_handler_data
IRawElementProviderSimple * prop_change_elprov
IProxyProviderWinEventSink IProxyProviderWinEventSink_iface
IRawElementProviderSimple * structure_change_elprov
VARIANT prop_change_value
SAFEARRAY * structure_change_rt_id
IRawElementProviderSimple * event_elprov
enum ConditionType ConditionType
struct UiaCondition ** ppConditions
enum TreeScope Scope
struct UiaCondition * pViewCondition
PROPERTYID * pProperties
enum AutomationElementMode automationElementMode
struct UiaCondition * pConditions
enum ConditionType ConditionType
enum ConditionType ConditionType
enum PropertyConditionFlags Flags
Definition: scsiwmi.h:51
HBRUSH hbrBackground
Definition: winuser.h:3278
HICON hIcon
Definition: winuser.h:3276
HINSTANCE hInstance
Definition: winuser.h:3275
HCURSOR hCursor
Definition: winuser.h:3277
int cbWndExtra
Definition: winuser.h:3274
UINT style
Definition: winuser.h:3271
LPCSTR lpszMenuName
Definition: winuser.h:3279
LPCSTR lpszClassName
Definition: winuser.h:3280
WNDPROC lpfnWndProc
Definition: winuser.h:3272
int cbClsExtra
Definition: winuser.h:3273
Definition: match.c:390
Definition: http.c:7252
ULONG exp_release_refcnt
struct Provider * elem_prov
struct node_provider_desc prov_desc
Definition: fci.c:127
Definition: parser.c:49
const GUID * iface_iid
Definition: tftpd.h:60
Definition: name.c:39
const WCHAR * prov_type[MAX_NODE_PROVIDERS]
struct node_provider_desc * nested_desc[MAX_NODE_PROVIDERS]
BOOL parent_link[MAX_NODE_PROVIDERS]
const WCHAR * prov_name[MAX_NODE_PROVIDERS]
Definition: _pair.h:47
struct Provider * prov
Definition: send.c:48
const char * str
Definition: uiautomation.c:38
Definition: parse.h:23
LONG right
Definition: windef.h:108
LONG bottom
Definition: windef.h:109
LONG top
Definition: windef.h:107
LONG left
Definition: windef.h:106
const GUID * iid
const GUID * clsid
enum UIAutomationType type
const GUID * prop_guid
const GUID * guid
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:726
HANDLE WINAPI DECLSPEC_HOTPATCH CreateEventW(IN LPSECURITY_ATTRIBUTES lpEventAttributes OPTIONAL, IN BOOL bManualReset, IN BOOL bInitialState, IN LPCWSTR lpName OPTIONAL)
Definition: synch.c:587
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:669
#define bsearch
#define DWORD_PTR
Definition: treelist.c:76
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
const uint16_t * LPCWSTR
Definition: typedefs.h:57
int32_t INT
Definition: typedefs.h:58
#define MAKELONG(a, b)
Definition: typedefs.h:249
#define CONTAINING_RECORD(address, type, field)
Definition: typedefs.h:260
uint32_t UINT32
Definition: typedefs.h:59
uint32_t ULONG
Definition: typedefs.h:59
#define HIWORD(l)
Definition: typedefs.h:247
static EFI_HANDLE * handles
Definition: uefidisk.c:66
HRESULT WINAPI UiaGetRuntimeId(HUIANODE huianode, SAFEARRAY **runtime_id)
Definition: uia_client.c:3045
HRESULT WINAPI UiaNodeFromProvider(IRawElementProviderSimple *elprov, HUIANODE *huianode)
Definition: uia_client.c:2114
HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cache_req, enum NormalizeState normalize_state, struct UiaCondition *normalize_cond, SAFEARRAY **out_req, BSTR *tree_struct)
Definition: uia_client.c:3450
HRESULT WINAPI UiaFind(HUIANODE huianode, struct UiaFindParams *find_params, struct UiaCacheRequest *cache_req, SAFEARRAY **out_req, SAFEARRAY **out_offsets, SAFEARRAY **out_tree_structs)
Definition: uia_client.c:3642
HRESULT WINAPI UiaNodeFromFocus(struct UiaCacheRequest *cache_req, SAFEARRAY **out_req, BSTR *tree_struct)
Definition: uia_client.c:2834
HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIANT *out_val)
Definition: uia_client.c:2909
BOOL WINAPI UiaNodeRelease(HUIANODE huianode)
Definition: uia_client.c:2876
HRESULT WINAPI UiaNavigate(HUIANODE huianode, enum NavigateDirection dir, struct UiaCondition *nav_condition, struct UiaCacheRequest *cache_req, SAFEARRAY **out_req, BSTR *tree_struct)
Definition: uia_client.c:3567
HRESULT WINAPI UiaGetRootNode(HUIANODE *huianode)
Definition: uia_client.c:2771
HRESULT WINAPI UiaHUiaNodeFromVariant(VARIANT *in_val, HUIANODE *huianode)
Definition: uia_client.c:3097
void WINAPI UiaRegisterProviderCallback(UiaProviderCallback *callback)
Definition: uia_client.c:3292
HRESULT WINAPI UiaNodeFromHandle(HWND hwnd, HUIANODE *huianode)
Definition: uia_client.c:2761
BOOL WINAPI UiaHasServerSideProvider(HWND hwnd)
Definition: uia_client.c:2781
static HRESULT uia_com_event_callback(struct uia_event *event, struct uia_event_args *args, SAFEARRAY *cache_req, BSTR tree_struct)
HRESULT WINAPI UiaRaiseAutomationEvent(IRawElementProviderSimple *elprov, EVENTID id)
Definition: uia_event.c:1953
HRESULT WINAPI UiaRemoveEvent(HUIAEVENT huiaevent)
Definition: uia_event.c:1712
HRESULT WINAPI UiaAddEvent(HUIANODE huianode, EVENTID event_id, UiaEventCallback *callback, enum TreeScope scope, PROPERTYID *prop_ids, int prop_ids_count, struct UiaCacheRequest *cache_req, HUIAEVENT *huiaevent)
Definition: uia_event.c:1675
HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd)
Definition: uia_event.c:1595
int WINAPI UiaLookupId(enum AutomationIdentifierType type, const GUID *guid)
Definition: uia_ids.c:627
HRESULT WINAPI UiaGetReservedMixedAttributeValue(IUnknown **value)
Definition: uia_main.c:274
HRESULT WINAPI UiaGetReservedNotSupportedValue(IUnknown **value)
Definition: uia_main.c:289
HRESULT WINAPI UiaHostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **provider)
Definition: uia_main.c:361
BOOL WINAPI UiaClientsAreListening(void)
Definition: uia_main.c:265
LRESULT WINAPI UiaReturnRawElementProvider(HWND hwnd, WPARAM wparam, LPARAM lparam, IRawElementProviderSimple *elprov)
static const struct prov_method_sequence nav_seq17[]
static const struct prov_method_sequence nav_seq14[]
static const struct prov_method_sequence treewalker_seq2[]
static void WINAPI multi_uia_event_callback(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
static void set_clientside_providers_for_hwnd(struct Provider *proxy_prov, struct Provider *nc_prov, struct Provider *hwnd_prov, HWND hwnd)
static HRESULT WINAPI ProviderFragment_SetFocus(IRawElementProviderFragment *iface)
static const struct prov_method_sequence find_seq8[]
static void test_node_provider_desc_(struct node_provider_desc *desc, BSTR desc_str, const char *file, int line)
static void destroy_test_hwnd(HWND hwnd, const char *class_name, const char *child_class_name)
static HRESULT WINAPI ProviderHwndOverride_GetOverrideProviderForHwnd(IRawElementProviderHwndOverride *iface, HWND hwnd, IRawElementProviderSimple **ret_val)
static HRESULT WINAPI Accessible_put_accValue(IAccessible *iface, VARIANT child_id, BSTR value)
Definition: uiautomation.c:987
#define SET_EXPECT(func)
Definition: uiautomation.c:341
static const struct prov_method_sequence treewalker_seq7[]
static HRESULT WINAPI Accessible2_get_groupPosition(IAccessible2 *iface, LONG *out_group_level, LONG *out_similar_items_in_group, LONG *out_position_in_group)
static CRITICAL_SECTION_DEBUG clientside_provider_callback_cs_debug
static const struct prov_method_sequence cache_req_seq5[]
static struct Accessible * impl_from_OleWindow(IOleWindow *iface)
static void test_node_hwnd_provider_(HUIANODE node, HWND hwnd, const char *file, int line)
static void set_provider_win_event_handler_win_event_expects(struct Provider *prov, DWORD exp_win_event_id, HWND exp_win_event_hwnd, LONG exp_win_event_obj_id, LONG exp_win_event_child_id)
static HRESULT WINAPI Accessible2_GetTypeInfo(IAccessible2 *iface, UINT iTInfo, LCID lcid, ITypeInfo **out_tinfo)
static void add_provider_desc(struct node_provider_desc *desc, const WCHAR *prov_type, const WCHAR *prov_name, BOOL parent_link)
static const struct str_id_pair uia_pattern_id_strs[]
Definition: uiautomation.c:219
static DWORD WINAPI uia_com_event_handler_win_event_test_thread(LPVOID param)
static void test_UiaClientsAreListening(void)
static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val)
static HRESULT WINAPI Accessible2_accSelect(IAccessible2 *iface, LONG select_flags, VARIANT child_id)
static struct Accessible Accessible_child2
static HRESULT WINAPI Accessible2_accLocation(IAccessible2 *iface, LONG *out_left, LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
static HRESULT WINAPI Accessible2_accNavigate(IAccessible2 *iface, LONG nav_direction, VARIANT child_id_start, VARIANT *out_var)
static struct Provider Provider_child
static HRESULT WINAPI Accessible_get_accRole(IAccessible *iface, VARIANT child_id, VARIANT *out_role)
Definition: uiautomation.c:776
static void push_expected_event(struct node_provider_desc *exp_node_desc)
static const struct prov_method_sequence node_from_hwnd7[]
static const struct prov_method_sequence treewalker_seq10[]
static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val)
static const struct prov_method_sequence get_elem_prop_seq[]
static HRESULT WINAPI ProviderAdviseEvents_QueryInterface(IRawElementProviderAdviseEvents *iface, REFIID riid, void **ppv)
static HRESULT WINAPI Accessible_GetTypeInfo(IAccessible *iface, UINT iTInfo, LCID lcid, ITypeInfo **out_tinfo)
Definition: uiautomation.c:649
static void initialize_provider_tree(BOOL initialize_nav_links)
static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com)
static HRESULT WINAPI ClientSideProvider_get_HostRawElementProvider(IRawElementProviderSimple *iface, IRawElementProviderSimple **ret_val)
static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface)
static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VARIANT child_id, BSTR *out_kbd_shortcut)
Definition: uiautomation.c:854
static const struct prov_method_sequence node_from_hwnd4[]
static const char * prov_method_str[]
static struct Accessible Accessible2
#define check_interface_marshal_proxy_creation(iface, iid, expect_proxy)
Definition: uiautomation.c:453
static DWORD WINAPI uia_reserved_val_iface_marshal_thread(LPVOID param)
static struct Provider Provider_proxy2
#define check_node_provider_desc(prov_desc, prov_type, prov_name, parent_link)
static HRESULT WINAPI Accessible2_get_relation(IAccessible2 *iface, LONG relation_idx, IAccessibleRelation **out_relation)
static DWORD WINAPI uia_com_event_handler_test_thread(LPVOID param)
#define test_provider_event_advise_added(prov, event_id, todo)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_DefaultAction(ILegacyIAccessibleProvider *iface, BSTR *out_default_action)
static const struct prov_method_sequence nav_seq2[]
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_ChildId(ILegacyIAccessibleProvider *iface, int *out_cid)
static const struct prov_method_sequence node_from_prov7[]
static ULONG WINAPI FocusChangedHandler_Release(IUIAutomationFocusChangedEventHandler *iface)
#define test_node_hwnd_provider(node, hwnd)
@ PROVIDER_CHILD_ID
@ PROVIDER_ID
@ PROVIDER2_ID
static void set_not_condition(struct UiaNotCondition *cond, struct UiaCondition *not_cond)
#define MAX_EVENT_QUEUE_COUNT
static void test_uia_com_focus_change_event_handler_win_event_handling(IUIAutomation *uia_iface, HWND test_hwnd, HWND test_child_hwnd)
static struct node_provider_desc * pop_event_queue_event(struct ExpectedEventQueue *queue)
static void test_provider_event_advise_added_(struct Provider *prov, int event_id, BOOL todo, const char *file, int line)
static void test_uia_prov_from_acc_properties(void)
static struct Provider Provider2
static const struct prov_method_sequence cache_req_seq7[]
static IUIAutomationElement * create_test_element_from_hwnd(IUIAutomation *uia_iface, HWND hwnd, BOOL block_hwnd_provs)
static IAccessible * msaa_acc_da_unwrap(IAccessible *acc)
static const struct str_id_pair uia_prop_id_strs[]
Definition: uiautomation.c:41
static const struct prov_method_sequence event_seq4[]
static void test_find_sa_results_(SAFEARRAY *tree_structs, SAFEARRAY *offsets, LONG exp_elems, const WCHAR **exp_tree_struct, int *exp_offset, const char *file, int line)
static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file, int line)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_KeyboardShortcut(ILegacyIAccessibleProvider *iface, BSTR *out_kbd_shortcut)
static struct Accessible * impl_from_ServiceProvider(IServiceProvider *iface)
static void test_UiaNavigate(void)
static void test_UiaGetRuntimeId(void)
static const struct prov_method_sequence element_find_seq2[]
static void reset_event_advise_values_for_hwnd_providers(struct Provider *main, struct Provider *hwnd, struct Provider *nc)
static const struct prov_method_sequence node_from_var_seq[]
static const struct prov_method_sequence nav_seq11[]
static const IUIAutomationFocusChangedEventHandlerVtbl FocusChangedHandlerVtbl
static ULONG WINAPI ServiceProvider_Release(IServiceProvider *iface)
static HRESULT WINAPI Accessible2_scrollTo(IAccessible2 *iface, enum IA2ScrollType scroll_type)
#define UIA_RUNTIME_ID_PREFIX
Definition: uiautomation.c:387
static SAFEARRAY * create_i4_safearray(void)
static ULONG WINAPI Object_AddRef(IUnknown *iface)
static ULONG WINAPI ProviderFragment_AddRef(IRawElementProviderFragment *iface)
static const struct prov_method_sequence get_runtime_id4[]
static HRESULT WINAPI ProviderFragment_QueryInterface(IRawElementProviderFragment *iface, REFIID riid, void **ppv)
static HWND create_test_hwnd(const char *class_name)
static void ok_method_sequence_(const struct prov_method_sequence *expected_list, const char *context, const char *file, int line)
static const IValueProviderVtbl ProviderValuePatternVtbl
static void test_uia_event_ProxyProviderWinEventHandler(void)
static CRITICAL_SECTION clientside_provider_callback_cs
static void set_event_data_struct(struct EventData *data, LONG exp_lbound0, LONG exp_lbound1, LONG exp_elems0, LONG exp_elems1, struct node_provider_desc *exp_node_desc, const WCHAR *exp_tree_struct)
static void test_UiaHostProviderFromHwnd(void)
static SAFEARRAY WINAPI * test_uia_provider_callback(HWND hwnd, enum ProviderType prov_type)
@ PARENT_HWND_NULL
@ PARENT_HWND_DESKTOP
@ PARENT_HWND_HWND
static HRESULT WINAPI ProviderFragment_get_FragmentRoot(IRawElementProviderFragment *iface, IRawElementProviderFragmentRoot **ret_val)
static void check_msaa_prov_acc_(IUnknown *elprov, IAccessible *acc, INT cid, int line)
static void check_uia_hwnd_expects_at_least(int proxy_cback_count, BOOL proxy_cback_todo, int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo, int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
#define NODE_CREATE_SEQ_OPTIONAL(prov)
static ULONG WINAPI AutomationEventHandler_Release(IUIAutomationEventHandler *iface)
static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id)
static const struct prov_method_sequence disconnect_prov4[]
static const struct prov_method_sequence element_find_seq1[]
static void set_multi_event_data(struct node_provider_desc *exp_node_desc)
static const struct uia_com_classes com_classes[]
static HRESULT WINAPI Accessible2_get_accHelp(IAccessible2 *iface, VARIANT child_id, BSTR *out_help)
static const struct prov_method_sequence get_pattern_prop_seq2[]
static HRESULT WINAPI Accessible2_get_relations(IAccessible2 *iface, LONG count, IAccessibleRelation **out_relations, LONG *out_relation_count)
static HRESULT WINAPI Accessible2_get_locale(IAccessible2 *iface, IA2Locale *out_locale)
static struct Accessible * impl_from_Accessible2(IAccessible2 *iface)
static struct Provider * impl_from_ProviderWinEventHandler(IProxyProviderWinEventHandler *iface)
static ULONG WINAPI Accessible2_AddRef(IAccessible2 *iface)
static HRESULT WINAPI AutomationEventHandler_HandleAutomationEvent(IUIAutomationEventHandler *iface, IUIAutomationElement *sender, EVENTID event_id)
static const struct prov_method_sequence get_prop_seq[]
static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov, int line)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetIAccessible(ILegacyIAccessibleProvider *iface, IAccessible **out_acc)
#define check_event_data(data, args, req_data, tree_struct)
#define check_uia_rect_val(v, rect)
#define check_node_provider_desc_todo(prov_desc, prov_type, prov_name, parent_link)
static const struct prov_method_sequence serverside_prov_seq[]
static const struct prov_method_sequence nav_seq3[]
static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count)
static struct Provider * impl_from_ProviderFragmentRoot(IRawElementProviderFragmentRoot *iface)
static void check_runtime_id_(int *exp_runtime_id, int exp_size, SAFEARRAY *runtime_id, const char *file, int line)
static void test_CUIAutomation_condition_ifaces(IUIAutomation *uia_iface)
static void test_UiaGetRootNode(void)
static BOOL iface_cmp(IUnknown *iface1, IUnknown *iface2)
Definition: uiautomation.c:425
static const struct prov_method_sequence reg_prov_cb7[]
static IRawElementProviderSimple * nc_prov
#define test_com_event_data(sender)
HRESULT WINAPI ProviderSimple_get_HostRawElementProvider(IRawElementProviderSimple *iface, IRawElementProviderSimple **ret_val)
static DWORD WINAPI uia_node_from_provider_test_com_thread(LPVOID param)
static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomationElement *elem)
static HRESULT WINAPI Accessible2_get_accSelection(IAccessible2 *iface, VARIANT *out_selection)
static void check_uia_hwnd_expects(int proxy_cback_count, BOOL proxy_cback_todo, int base_hwnd_cback_count, BOOL base_hwnd_cback_todo, int nc_cback_count, BOOL nc_cback_todo, int win_get_uia_obj_count, BOOL win_get_uia_obj_todo, int win_get_client_obj_count, BOOL win_get_client_obj_todo)
static const struct prov_method_sequence cache_req_seq8[]
static IRawElementProviderSimple * prov_root
static HRESULT WINAPI AutomationEventHandler_QueryInterface(IUIAutomationEventHandler *iface, REFIID riid, void **ppv)
static void check_node_provider_desc_(BSTR prov_desc, const WCHAR *prov_type, const WCHAR *prov_name, BOOL parent_link, BOOL todo, const char *file, int line)
static LRESULT WINAPI test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static HRESULT WINAPI Accessible2_get_accRole(IAccessible2 *iface, VARIANT child_id, VARIANT *out_role)
#define CALLED_COUNT(func)
Definition: uiautomation.c:359
static HRESULT WINAPI Accessible2_get_extendedRole(IAccessible2 *iface, BSTR *out_extended_role)
static void test_CUIAutomation_cache_request_iface(IUIAutomation *uia_iface)
static HRESULT WINAPI Accessible2_GetIDsOfNames(IAccessible2 *iface, REFIID riid, LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
static const struct prov_method_sequence reg_prov_cb12[]
static ULONG WINAPI ProviderLegacyIAccessiblePattern_Release(ILegacyIAccessibleProvider *iface)
static ULONG WINAPI ProviderWinEventHandler_AddRef(IProxyProviderWinEventHandler *iface)
static ULONG WINAPI FocusChangedHandler_AddRef(IUIAutomationFocusChangedEventHandler *iface)
static const struct prov_method_sequence get_runtime_id2[]
static HRESULT WINAPI Accessible_get_accDefaultAction(IAccessible *iface, VARIANT child_id, BSTR *out_default_action)
Definition: uiautomation.c:899
static const struct prov_method_sequence disconnect_prov1[]
static void post_event_message(HWND hwnd, int msg, WPARAM wparam, int prov_id, int lparam_lower)
static const struct prov_method_sequence find_seq4[]
static HRESULT WINAPI Accessible_get_accState(IAccessible *iface, VARIANT child_id, VARIANT *out_state)
Definition: uiautomation.c:794
static IRawElementProviderSimple * parent_proxy_prov
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_GetSelection(ILegacyIAccessibleProvider *iface, SAFEARRAY **out_selected)
static HWND create_child_test_hwnd(const char *class_name, HWND parent)
static void check_node_provider_desc_prefix_(BSTR prov_desc, DWORD pid, HWND prov_id, const char *file, int line)
static HRESULT WINAPI Accessible2_accHitTest(IAccessible2 *iface, LONG left, LONG top, VARIANT *out_child_id)
static HRESULT WINAPI Accessible_get_accHelpTopic(IAccessible *iface, BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
Definition: uiautomation.c:845
static HRESULT WINAPI ProviderFragment_get_BoundingRectangle(IRawElementProviderFragment *iface, struct UiaRect *ret_val)
static const struct prov_method_sequence node_from_prov1[]
static const struct prov_method_sequence event_seq5[]
static BOOL check_variant_i4(VARIANT *v, int val)
Definition: uiautomation.c:403
static const struct prov_method_sequence reg_prov_cb8[]
static const struct prov_method_sequence cache_req_seq10[]
static void test_UiaGetUpdatedCache(void)
static const struct prov_method_sequence event_seq1[]
static const struct UiaCondition UiaFalseCondition
static void test_uia_prov_from_acc_navigation(void)
static void check_uia_hwnd_expects_at_most(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count, int win_get_uia_obj_count, int win_get_client_obj_count)
static const struct prov_method_sequence default_hwnd_prov_props_seq[]
static SAFEARRAY * create_r8_safearray(void)
#define CHECK_EXPECT(func)
Definition: uiautomation.c:353
static HRESULT WINAPI Accessible2_get_nRelations(IAccessible2 *iface, LONG *out_nRelations)
static const struct prov_method_sequence get_pattern_prop_seq[]
static struct Provider Provider_hwnd Provider_nc Provider_proxy Provider_proxy2 Provider_override
#define check_node_provider_desc_prefix(prov_desc, pid, prov_id)
static HRESULT WINAPI Accessible2_get_states(IAccessible2 *iface, AccessibleStates *out_states)
static HRESULT WINAPI Accessible_get_accDescription(IAccessible *iface, VARIANT child_id, BSTR *out_description)
Definition: uiautomation.c:767
static void test_UiaHUiaNodeFromVariant(void)
static HRESULT WINAPI Accessible2_GetTypeInfoCount(IAccessible2 *iface, UINT *pctinfo)
static ULONG WINAPI ProviderAdviseEvents_Release(IRawElementProviderAdviseEvents *iface)
static void test_GetRootElement(IUIAutomation *uia_iface)
static const IAccessible2Vtbl Accessible2Vtbl
#define DEFINE_EXPECT(func)
Definition: uiautomation.c:338
static DWORD msg_wait_for_all_events(HANDLE *event_handles, int event_handle_count, DWORD timeout_val)
Definition: uiautomation.c:503
static const struct uia_element_property element_properties[]
static const struct prov_method_sequence disconnect_prov2[]
static void set_provider_method_event_data(struct Provider *prov, HANDLE event_handle, int method_id)
static const struct prov_method_sequence reg_prov_cb11[]
static void test_cache_req_sa_(SAFEARRAY *sa, LONG exp_lbound[2], LONG exp_elems[2], struct node_provider_desc *exp_node_desc, const char *file, int line)
static void test_hwnd_providers_event_advise_added_(struct Provider *main, struct Provider *hwnd, struct Provider *nc, int event_id, BOOL todo, const char *file, int line)
static ULONG WINAPI Object_Release(IUnknown *iface)
static HRESULT WINAPI ProviderAdviseEvents_AdviseEventRemoved(IRawElementProviderAdviseEvents *iface, EVENTID event_id, SAFEARRAY *prop_ids)
#define CHECK_ACC_METHOD_CALLED_AT_MOST(acc, method, num)
Definition: uiautomation.c:592
static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
static HRESULT WINAPI ProviderAdviseEvents_AdviseEventAdded(IRawElementProviderAdviseEvents *iface, EVENTID event_id, SAFEARRAY *prop_ids)
static struct Provider * impl_from_ProviderHwndOverride(IRawElementProviderHwndOverride *iface)
static const struct prov_method_sequence nav_seq12[]
static HRESULT WINAPI Accessible_put_accName(IAccessible *iface, VARIANT child_id, BSTR name)
Definition: uiautomation.c:978
static void set_provider_runtime_id(struct Provider *prov, int val, int val2)
static HRESULT WINAPI Accessible2_scrollToPoint(IAccessible2 *iface, enum IA2CoordinateType coordinate_type, LONG x, LONG y)
static IRawElementProviderSimple * base_hwnd_prov
static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links)
static void test_CUIAutomation_TreeWalker_ifaces(IUIAutomation *uia_iface)
static const struct prov_method_sequence get_prop_invalid_type_seq[]
static void test_UiaAddEvent(const char *name)
static struct ClientSideProvider * impl_from_ClientSideProvider(IRawElementProviderSimple *iface)
static void set_uia_hwnd_expects(int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count, int win_get_uia_obj_count, int win_get_client_obj_count)
#define test_hwnd_providers_event_advise_added(main, hwnd, nc, event_id, todo)
static const struct prov_method_sequence node_from_prov3[]
static void test_UiaNodeFromHandle_client_proc(void)
static HRESULT WINAPI ClientSideProvider_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
#define test_get_focused_elem(uia_iface, cache_req, exp_hr, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, nc_cback_count, win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, base_hwnd_cback_todo, nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo)
static void test_get_focused_elem_(IUIAutomation *uia_iface, IUIAutomationCacheRequest *cache_req, HRESULT exp_hr, struct node_provider_desc *exp_node_desc, int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count, int win_get_obj_count, int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo, BOOL nc_cback_todo, BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
#define MAX_NODE_PROVIDERS
static const struct prov_method_sequence get_cached_prop_val_seq2[]
#define ACC_METHOD_TRACE(acc, method)
Definition: uiautomation.c:331
static const struct prov_method_sequence treewalker_seq6[]
static void proxy_event_sink_clear(void)
static HRESULT WINAPI Accessible_get_accHelp(IAccessible *iface, VARIANT child_id, BSTR *out_help)
Definition: uiautomation.c:836
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_SetValue(ILegacyIAccessibleProvider *iface, LPCWSTR val)
static HRESULT WINAPI ProxyEventSink_AddStructureChangedEvent(IProxyProviderWinEventSink *iface, IRawElementProviderSimple *elprov, enum StructureChangeType structure_change_type, SAFEARRAY *runtime_id)
static HRESULT WINAPI FocusChangedHandler_HandleFocusChangedEvent(IUIAutomationFocusChangedEventHandler *iface, IUIAutomationElement *sender)
static void test_uia_element_arr_(IUIAutomationElementArray *elem_arr, struct exp_elem_desc *exp_elems, int exp_elems_count, const char *file, int line)
static LRESULT WINAPI child_test_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
static struct AutomationEventHandler * impl_from_AutomationEventHandler(IUIAutomationEventHandler *iface)
@ FRAG_GET_EMBEDDED_FRAGMENT_ROOTS
@ ADVISE_EVENTS_EVENT_REMOVED
@ ADVISE_EVENTS_EVENT_ADDED
@ FRAG_GET_FRAGMENT_ROOT
@ FRAG_NAVIGATE
@ HWND_OVERRIDE_GET_OVERRIDE_PROVIDER
@ PROV_GET_HOST_RAW_ELEMENT_PROVIDER
@ FRAG_GET_RUNTIME_ID
@ WINEVENT_HANDLER_RESPOND_TO_WINEVENT
@ PROV_GET_PATTERN_PROV
@ PROV_GET_PROPERTY_VALUE
@ PROV_GET_PROVIDER_OPTIONS
@ FRAG_GET_BOUNDING_RECT
@ FRAG_ROOT_GET_FOCUS
static struct ProxyEventSink * impl_from_ProxyEventSink(IProxyProviderWinEventSink *iface)
static void provider_add_child(struct Provider *prov, struct Provider *child)
static const struct prov_method_sequence node_from_prov5[]
static void test_uia_prov_from_acc_winevent_handler(HWND hwnd)
static const struct prov_method_sequence nav_seq16[]
HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface, PROPERTYID prop_id, VARIANT *ret_val)
static ULONG WINAPI OleWindow_AddRef(IOleWindow *iface)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_DoDefaultAction(ILegacyIAccessibleProvider *iface)
static HRESULT WINAPI Accessible2_QueryInterface(IAccessible2 *iface, REFIID riid, void **obj)
static ULONG WINAPI Accessible_Release(IAccessible *iface)
Definition: uiautomation.c:637
static void test_default_clientside_providers(void)
#define CHECK_ACC_METHOD_CALLED(acc, method)
Definition: uiautomation.c:574
static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_implemented, const char *file, int line)
Definition: uiautomation.c:441
static void test_UiaNodeFromProvider(void)
static ULONG WINAPI ProviderHwndOverride_AddRef(IRawElementProviderHwndOverride *iface)
static void launch_test_process(const char *name, const char *test_name)
static void test_IUIAutomationFocusChangedEventHandler(IUIAutomation *uia_iface)
static HRESULT WINAPI OleWindow_GetWindow(IOleWindow *iface, HWND *hwnd)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Description(ILegacyIAccessibleProvider *iface, BSTR *out_description)
static const struct prov_method_sequence treewalker_seq5[]
static void test_CUIAutomation_value_conversion(IUIAutomation *uia_iface)
static ULONG WINAPI ClientSideProvider_AddRef(IRawElementProviderSimple *iface)
static HRESULT WINAPI Accessible2_get_windowHandle(IAccessible2 *iface, HWND *out_hwnd)
static IAccessibleVtbl AccessibleVtbl
Definition: uiautomation.c:996
static const IRawElementProviderFragmentRootVtbl ProviderFragmentRootVtbl
static void test_CUIAutomation(void)
static HRESULT WINAPI ProviderValuePattern_QueryInterface(IValueProvider *iface, REFIID riid, void **ppv)
static ULONG WINAPI ProxyEventSink_AddRef(IProxyProviderWinEventSink *iface)
static HRESULT WINAPI Accessible_accHitTest(IAccessible *iface, LONG left, LONG top, VARIANT *out_child_id)
Definition: uiautomation.c:961
static HRESULT WINAPI Accessible2_accDoDefaultAction(IAccessible2 *iface, VARIANT child_id)
static IRawElementProviderSimple * create_temporary_clientside_provider(HWND hwnd, enum ProviderType prov_type)
#define NODE_CREATE_SEQ2(prov)
static const struct prov_method_sequence reg_prov_cb5[]
#define test_node_from_focus(cache_req, exp_node_desc, proxy_cback_count, base_hwnd_cback_count, nc_cback_count, win_get_obj_count, child_win_get_obj_count, proxy_cback_todo, base_hwnd_cback_todo, nc_cback_todo, win_get_obj_todo, child_win_get_obj_todo)
static struct Provider * impl_from_ProviderLegacyIAccessiblePattern(ILegacyIAccessibleProvider *iface)
static int sequence_size
static const IProxyProviderWinEventSinkVtbl ProxyEventSinkVtbl
#define check_uia_rect_rect_val(rect, uia_rect)
static DWORD WINAPI uia_add_event_test_thread(LPVOID param)
static const struct prov_method_sequence get_runtime_id5[]
static const struct prov_method_sequence node_from_prov8[]
static void test_UiaNodeFromFocus(void)
static HRESULT WINAPI Accessible2_get_indexInParent(IAccessible2 *iface, LONG *out_idx_in_parent)
static BOOL get_provider_desc(BSTR prov_desc, const WCHAR *prov_type, WCHAR *out_name)
static void set_and_or_condition(struct UiaAndOrCondition *cond, int cond_type, struct UiaCondition **conds, int cond_count)
static BOOL wait_for_clientside_callbacks(DWORD total_timeout)
static const struct uia_hwnd_control_type_test hwnd_control_type_test[]
#define test_uia_event_win_event_mapping(win_event, hwnd, obj_id, child_id, event_handles, event_handle_count, expect_event1, expect_event2, todo)
static HRESULT WINAPI Accessible2_get_accFocus(IAccessible2 *iface, VARIANT *pchild_id)
static HRESULT WINAPI Accessible_get_accParent(IAccessible *iface, IDispatch **out_parent)
Definition: uiautomation.c:671
HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *iface, enum ProviderOptions *ret_val)
static HRESULT WINAPI Accessible2_Invoke(IAccessible2 *iface, DISPID disp_id_member, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params, VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
static const struct prov_method_sequence reg_prov_cb13[]
HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface, PATTERNID pattern_id, IUnknown **ret_val)
#define test_find_sa_results(tree_structs, offsets, exp_elems, exp_tree_struct, exp_offsets)
static const struct prov_method_sequence node_from_hwnd9[]
#define NODE_CREATE_SEQ(prov)
#define test_cache_req_sa(sa, exp_lbound, exp_elems, exp_node_desc)
static ULONG WINAPI Accessible_AddRef(IAccessible *iface)
Definition: uiautomation.c:631
#define check_runtime_id(exp_runtime_id, exp_size, runtime_id)
static IUnknownVtbl ObjectVtbl
static void test_ElementFromHandle(IUIAutomation *uia_iface, BOOL is_cui8)
static ULONG WINAPI ProviderFragmentRoot_Release(IRawElementProviderFragmentRoot *iface)
static const struct prov_method_sequence cache_req_seq4[]
static DWORD
Definition: uiautomation.c:33
static IAccessible * acc_client
static HRESULT WINAPI Accessible2_get_nExtendedStates(IAccessible2 *iface, LONG *out_nExtendedStates)
static const IUIAutomationEventHandlerVtbl AutomationEventHandlerVtbl
static void test_UiaFind(void)
static void set_provider_nav_ifaces(struct Provider *prov, struct Provider *parent, struct Provider *frag_root, struct Provider *prev_sibling, struct Provider *next_sibling, struct Provider *first_child, struct Provider *last_child)
static const struct prov_method_sequence find_seq1[]
static HRESULT WINAPI Accessible2_put_accName(IAccessible2 *iface, VARIANT child_id, BSTR name)
static void test_UiaRemoveEvent_args(HUIANODE node)
static HRESULT WINAPI Object_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
static struct Provider Provider
static const struct prov_method_sequence reg_prov_cb6[]
static HRESULT WINAPI Accessible_accDoDefaultAction(IAccessible *iface, VARIANT child_id)
Definition: uiautomation.c:970
static const struct prov_method_sequence node_from_prov6[]
static ULONG WINAPI ProviderAdviseEvents_AddRef(IRawElementProviderAdviseEvents *iface)
static HRESULT WINAPI Accessible2_get_accChildCount(IAccessible2 *iface, LONG *out_count)
static struct Provider * event_test_provs[]
static const struct prov_method_sequence get_elem_cache_seq[]
static void set_method_event_handle_for_providers(struct Provider *main, struct Provider *hwnd, struct Provider *nc, HANDLE *handles, int method)
static HRESULT WINAPI Accessible_GetTypeInfoCount(IAccessible *iface, UINT *pctinfo)
Definition: uiautomation.c:643
static const struct prov_method_sequence node_from_prov2[]
static ULONG WINAPI ProviderHwndOverride_Release(IRawElementProviderHwndOverride *iface)
static IRawElementProviderSimpleVtbl ClientSideProviderVtbl
#define CHECK_ACC_METHOD_CALLED_AT_LEAST(acc, method, num)
Definition: uiautomation.c:586
static void test_UiaHasServerSideProvider(void)
static HRESULT WINAPI FocusChangedHandler_QueryInterface(IUIAutomationFocusChangedEventHandler *iface, REFIID riid, void **ppv)
static HRESULT WINAPI Accessible2_get_uniqueID(IAccessible2 *iface, LONG *out_unique_id)
#define NAVDIR_INTERNAL_HWND
Definition: uiautomation.c:386
static const struct str_id_pair uia_nav_dir_strs[]
Definition: uiautomation.c:256
static const struct prov_method_sequence get_elem_arr_prop_seq[]
static HRESULT WINAPI Accessible2_get_accDefaultAction(IAccessible2 *iface, VARIANT child_id, BSTR *out_default_action)
#define ACC_METHOD_TRACE2(acc, cid, method)
Definition: uiautomation.c:334
static const struct msaa_state_uia_prop msaa_state_uia_props[]
static ULONG WINAPI ProviderWinEventHandler_Release(IProxyProviderWinEventHandler *iface)
static const struct prov_method_sequence get_runtime_id3[]
static void check_event_data_(struct EventData *data, struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct, const char *file, int line)
static BOOL method_sequences_enabled
static void add_method_call(struct Provider *prov, int method)
#define CHECK_ACC_METHOD_EXPECT(acc, method)
Definition: uiautomation.c:568
static const ILegacyIAccessibleProviderVtbl ProviderLegacyIAccessiblePatternVtbl
static IRawElementProviderSimple * child_win_prov_root
static const struct prov_method_sequence event_seq3[]
static struct Accessible Accessible_child
static DWORD WINAPI uia_node_from_handle_test_thread(LPVOID param)
static void set_accessible_props(struct Accessible *acc, INT role, INT state, LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height)
static HRESULT WINAPI Accessible_get_accSelection(IAccessible *iface, VARIANT *out_selection)
Definition: uiautomation.c:891
static struct Provider Provider_nc
static CONDITION_VARIABLE * clientside_provider_callback_cv
static void test_uia_event_win_event_mapping_(DWORD win_event, HWND hwnd, LONG obj_id, LONG child_id, HANDLE *event_handles, int event_handle_count, BOOL expect_event1, BOOL expect_event2, BOOL todo, const char *file, int line)
static const struct prov_method_sequence node_from_hwnd6[]
static void flush_method_sequence(void)
static const struct prov_method_sequence node_from_hwnd1[]
static struct Provider * impl_from_ProviderValuePattern(IValueProvider *iface)
static HRESULT WINAPI Accessible2_get_localizedExtendedRole(IAccessible2 *iface, BSTR *out_localized_extended_role)
static void check_fragment_acc_(IRawElementProviderFragment *elfrag, IAccessible *acc, INT cid, int line)
static const struct prov_method_sequence cache_req_seq1[]
static SAFEARRAY WINAPI * uia_com_win_event_clientside_provider_callback(HWND hwnd, enum ProviderType prov_type)
static const WCHAR * uia_bstr_prop_str
static const struct prov_method_sequence cache_req_seq6[]
static void test_com_event_data_(IUIAutomationElement *sender, const char *file, int line)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Name(ILegacyIAccessibleProvider *iface, BSTR *out_name)
static const struct uia_lookup_id uia_property_lookup_ids[]
static void init_node_provider_desc(struct node_provider_desc *desc, DWORD pid, HWND hwnd)
static const char * get_str_from_id_pair(int id, const struct str_id_pair *id_pair, int id_pair_size)
Definition: uiautomation.c:313
#define test_node_hwnd_provider_navigation(node, dir, exp_dest_hwnd)
static const struct msaa_role_uia_type msaa_role_uia_types[]
static const ULONG uia_i4_arr_prop_val[]
static HRESULT WINAPI Accessible2_get_accKeyboardShortcut(IAccessible2 *iface, VARIANT child_id, BSTR *out_kbd_shortcut)
static int sequence_cnt
static const struct prov_method_sequence get_bounding_rect_seq[]
static const struct prov_method_sequence find_seq7[]
static void test_GetFocusedElement(IUIAutomation *uia_iface)
static const struct prov_method_sequence find_seq3[]
static const struct uia_lookup_id uia_pattern_lookup_ids[]
static const struct prov_method_sequence node_from_prov4[]
static const struct prov_method_sequence nav_seq13[]
#define CHECK_CALLED(func)
Definition: uiautomation.c:362
#define check_fragment_acc(fragment, acc, cid)
static const IRawElementProviderAdviseEventsVtbl ProviderAdviseEventsVtbl
static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
static ULONG WINAPI ProxyEventSink_Release(IProxyProviderWinEventSink *iface)
static void test_UiaNodeFromHandle(const char *name)
static void test_Element_Find(IUIAutomation *uia_iface)
static HRESULT WINAPI Accessible_accLocation(IAccessible *iface, LONG *out_left, LONG *out_top, LONG *out_width, LONG *out_height, VARIANT child_id)
Definition: uiautomation.c:917
#define ok_method_sequence(exp, context)
static IRawElementProviderSimple * proxy_prov
static const struct prov_method_sequence get_cached_prop_val_seq3[]
static ULONG WINAPI Accessible2_Release(IAccessible2 *iface)
static const struct prov_method_sequence reg_prov_cb9[]
static const struct prov_method_sequence find_seq11[]
static const struct prov_method_sequence node_from_hwnd3[]
static const struct prov_method_sequence nav_seq7[]
static ULONG WINAPI OleWindow_Release(IOleWindow *iface)
ULONG WINAPI ProviderSimple_AddRef(IRawElementProviderSimple *iface)
static struct Provider * impl_from_ProviderSimple(IRawElementProviderSimple *iface)
static HRESULT WINAPI ProviderFragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface, SAFEARRAY **ret_val)
static const struct prov_method_sequence node_from_hwnd8[]
static HRESULT WINAPI Accessible_accNavigate(IAccessible *iface, LONG nav_direction, VARIANT child_id_start, VARIANT *out_var)
Definition: uiautomation.c:937
#define test_uia_element_arr(elem_arr, exp_elems, exp_elems_count)
static struct Provider Provider_child2
static struct FocusChangedHandler * impl_from_FocusChangedHandler(IUIAutomationFocusChangedEventHandler *iface)
static HRESULT WINAPI Accessible_get_accChildCount(IAccessible *iface, LONG *out_count)
Definition: uiautomation.c:684
static void test_node_from_focus_(struct UiaCacheRequest *cache_req, struct node_provider_desc *exp_node_desc, int proxy_cback_count, int base_hwnd_cback_count, int nc_cback_count, int win_get_obj_count, int child_win_get_obj_count, BOOL proxy_cback_todo, BOOL base_hwnd_cback_todo, BOOL nc_cback_todo, BOOL win_get_obj_todo, BOOL child_win_get_obj_todo, const char *file, int line)
static const struct prov_method_sequence find_seq9[]
static struct Provider Provider_hwnd
static const struct prov_method_sequence treewalker_seq4[]
#define check_msaa_prov_acc(elprov, acc, cid)
static void test_CUIAutomation_event_handlers(IUIAutomation *uia_iface)
static const double uia_r8_prop_val
static void set_property_condition(struct UiaPropertyCondition *cond, int prop_id, VARIANT *val, int flags)
static void test_uia_prov_from_acc_ia2(void)
static void WINAPI uia_event_callback2(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
static HRESULT WINAPI Accessible2_get_accValue(IAccessible2 *iface, VARIANT child_id, BSTR *out_value)
static ULONG WINAPI ProviderFragment_Release(IRawElementProviderFragment *iface)
static const struct prov_method_sequence nav_seq9[]
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Help(ILegacyIAccessibleProvider *iface, BSTR *out_help)
@ METHOD_TODO
@ METHOD_OPTIONAL
static const char * get_prov_method_str(int method)
@ WM_UIA_TEST_RAISE_EVENT_RT_ID
@ WM_UIA_TEST_RESET_EVENT_PROVIDERS
@ WM_UIA_TEST_RAISE_EVENT
@ WM_UIA_TEST_SET_EVENT_PROVIDER_DATA
@ WM_UIA_TEST_CHECK_EVENT_ADVISE_REMOVED
@ WM_UIA_TEST_CHECK_EVENT_ADVISE_ADDED
static const struct prov_method_sequence find_seq2[]
static HRESULT WINAPI Accessible2_get_accName(IAccessible2 *iface, VARIANT child_id, BSTR *out_name)
static void push_event_queue_event(struct ExpectedEventQueue *queue, struct node_provider_desc *exp_node_desc)
#define check_msaa_prov_host_elem_prov(elem, exp_host_prov)
static const struct str_id_pair uia_event_id_strs[]
Definition: uiautomation.c:264
static HRESULT WINAPI Accessible2_get_accHelpTopic(IAccessible2 *iface, BSTR *out_help_file, VARIANT child_id, LONG *out_topic_id)
static void test_UiaAddEvent_client_proc(void)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_QueryInterface(ILegacyIAccessibleProvider *iface, REFIID riid, void **ppv)
static HRESULT WINAPI ProviderWinEventHandler_QueryInterface(IProxyProviderWinEventHandler *iface, REFIID riid, void **ppv)
static ULONG WINAPI ProviderFragmentRoot_AddRef(IRawElementProviderFragmentRoot *iface)
static const IRawElementProviderSimple * uia_unk_arr_prop_val[]
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Value(ILegacyIAccessibleProvider *iface, BSTR *out_value)
static HRESULT WINAPI ClientSideProvider_GetPatternProvider(IRawElementProviderSimple *iface, PATTERNID pattern_id, IUnknown **ret_val)
static const struct prov_method_sequence win_event_handler_seq[]
static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *file, int line)
static void test_UiaLookupId(void)
static struct Provider * impl_from_ProviderAdviseEvents(IRawElementProviderAdviseEvents *iface)
static HRESULT WINAPI ServiceProvider_QueryInterface(IServiceProvider *iface, REFIID riid, void **obj)
static HRESULT WINAPI Accessible_Invoke(IAccessible *iface, DISPID disp_id_member, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *disp_params, VARIANT *var_result, EXCEPINFO *excep_info, UINT *arg_err)
Definition: uiautomation.c:663
static void variant_init_bool(VARIANT *v, BOOL val)
Definition: uiautomation.c:419
static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID riid, void **obj)
Definition: uiautomation.c:603
static void set_elem_desc(struct exp_elem_desc *desc, struct Provider *prov, HWND hwnd, DWORD pid, ULONG exp_refcnt, ULONG exp_release_refcnt)
static void test_uia_node_from_prov_com_threading(void)
static void test_UiaRaiseAutomationEvent_args(void)
static const struct prov_method_sequence treewalker_seq1[]
static HRESULT WINAPI ClientSideProvider_get_ProviderOptions(IRawElementProviderSimple *iface, enum ProviderOptions *ret_val)
static BOOL get_nested_provider_desc(BSTR prov_desc, const WCHAR *prov_type, BOOL parent_link, WCHAR *out_desc)
static HRESULT WINAPI ProviderWinEventHandler_RespondToWinEvent(IProxyProviderWinEventHandler *iface, DWORD event_id, HWND hwnd, LONG obj_id, LONG child_id, IProxyProviderWinEventSink *event_sink)
HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, REFIID riid, void **ppv)
static HRESULT WINAPI ProviderFragment_GetRuntimeId(IRawElementProviderFragment *iface, SAFEARRAY **ret_val)
static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pchild_id)
Definition: uiautomation.c:863
static void set_event_data(LONG exp_lbound0, LONG exp_lbound1, LONG exp_elems0, LONG exp_elems1, struct node_provider_desc *exp_node_desc, const WCHAR *exp_tree_struct)
static const struct prov_method_sequence get_bounding_rect_seq3[]
static HRESULT WINAPI ProviderFragment_Navigate(IRawElementProviderFragment *iface, enum NavigateDirection direction, IRawElementProviderFragment **ret_val)
static const struct prov_method_sequence get_cached_prop_val_seq[]
static HRESULT WINAPI Accessible2_get_accChild(IAccessible2 *iface, VARIANT child_id, IDispatch **out_child)
#define SET_ACC_METHOD_EXPECT(acc, method)
Definition: uiautomation.c:556
static HRESULT WINAPI Accessible2_get_accParent(IAccessible2 *iface, IDispatch **out_parent)
static void test_Element_cache_methods(IUIAutomation *uia_iface)
static const struct prov_method_sequence nav_seq1[]
static void check_for_method_call_event(struct Provider *prov, int method)
static void test_UiaProviderFromIAccessible(void)
static const struct prov_method_sequence nav_seq4[]
static const struct prov_method_sequence node_from_hwnd2[]
#define CHECK_ACC_METHOD_CALLED_MULTI(acc, method, num)
Definition: uiautomation.c:580
static HRESULT WINAPI Accessible_GetIDsOfNames(IAccessible *iface, REFIID riid, LPOLESTR *rg_names, UINT name_count, LCID lcid, DISPID *rg_disp_id)
Definition: uiautomation.c:656
static void WINAPI uia_event_callback(struct UiaEventArgs *args, SAFEARRAY *req_data, BSTR tree_struct)
#define NODE_CREATE_SEQ3(prov)
static HRESULT WINAPI Accessible_get_accValue(IAccessible *iface, VARIANT child_id, BSTR *out_value)
Definition: uiautomation.c:758
static void set_provider_win_event_handler_respond_prov(struct Provider *prov, IRawElementProviderSimple *responder_prov, int responder_event)
static const struct prov_method_sequence get_empty_bounding_rect_seq[]
static HRESULT WINAPI Accessible2_role(IAccessible2 *iface, LONG *out_role)
static void create_base_hwnd_test_node(HWND hwnd, BOOL child_hwnd, struct Provider *main, struct Provider *nc, HUIANODE *ret_node)
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_State(ILegacyIAccessibleProvider *iface, DWORD *out_state)
static void add_nested_provider_desc(struct node_provider_desc *desc, const WCHAR *prov_type, const WCHAR *prov_name, BOOL parent_link, struct node_provider_desc *nested_desc)
static const struct prov_method_sequence nav_seq6[]
static int __cdecl str_id_pair_compare(const void *a, const void *b)
Definition: uiautomation.c:303
static struct Provider Provider_proxy
static HRESULT WINAPI Accessible_get_accName(IAccessible *iface, VARIANT child_id, BSTR *out_name)
Definition: uiautomation.c:740
static BOOL check_variant_bool(VARIANT *v, BOOL val)
Definition: uiautomation.c:411
static void initialize_provider_advise_events_ids(struct Provider *prov)
ULONG WINAPI ProviderSimple_Release(IRawElementProviderSimple *iface)
static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface, HWND test_hwnd, HWND test_child_hwnd)
static const struct prov_method_sequence cache_req_seq3[]
static const struct prov_method_sequence node_from_hwnd10[]
static void test_UiaAddEvent_args(HUIANODE node)
static void test_UiaRegisterProviderCallback(void)
static HRESULT WINAPI Accessible2_get_accDescription(IAccessible2 *iface, VARIANT child_id, BSTR *out_description)
static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_id, IDispatch **out_child)
Definition: uiautomation.c:699
static const struct prov_method_sequence node_from_hwnd5[]
static ULONG WINAPI ProviderLegacyIAccessiblePattern_AddRef(ILegacyIAccessibleProvider *iface)
static HRESULT WINAPI Accessible2_get_localizedExtendedStates(IAccessible2 *iface, LONG count, BSTR **out_localized_extended_states, LONG *out_localized_extended_states_count)
#define CHECK_CALLED_AT_LEAST(func, num)
Definition: uiautomation.c:374
static struct Provider * impl_from_ProviderFragment(IRawElementProviderFragment *iface)
static const struct prov_method_sequence nav_seq10[]
#define CHECK_CALLED_MULTI(func, num)
Definition: uiautomation.c:368
static LONG
Definition: uiautomation.c:33
static ULONG WINAPI ServiceProvider_AddRef(IServiceProvider *iface)
static const struct prov_method_sequence event_seq6[]
static const IServiceProviderVtbl ServiceProviderVtbl
static HRESULT WINAPI ProviderFragmentRoot_GetFocus(IRawElementProviderFragmentRoot *iface, IRawElementProviderFragment **ret_val)
static HRESULT WINAPI ProxyEventSink_AddAutomationPropertyChangedEvent(IProxyProviderWinEventSink *iface, IRawElementProviderSimple *elprov, PROPERTYID prop_id, VARIANT new_value)
static const struct prov_method_sequence nav_seq15[]
static const IOleWindowVtbl OleWindowVtbl
static void test_uia_reserved_value_ifaces(void)
static const struct prov_method_sequence nav_seq8[]
static const struct prov_method_sequence reg_prov_cb2[]
IRawElementProviderSimpleVtbl ProviderSimpleVtbl
static const struct uia_lookup_id uia_control_type_lookup_ids[]
static HRESULT WINAPI ClientSideProvider_GetPropertyValue(IRawElementProviderSimple *iface, PROPERTYID prop_id, VARIANT *ret_val)
static const struct prov_method_sequence cache_req_seq9[]
static HRESULT WINAPI Accessible2_put_accValue(IAccessible2 *iface, VARIANT child_id, BSTR value)
static const struct uia_lookup_id uia_event_lookup_ids[]
static const struct prov_method_sequence get_runtime_id1[]
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_get_Role(ILegacyIAccessibleProvider *iface, DWORD *out_role)
static HRESULT WINAPI ProviderFragmentRoot_ElementProviderFromPoint(IRawElementProviderFragmentRoot *iface, double x, double y, IRawElementProviderFragment **ret_val)
static void test_uia_prov_from_acc_fragment_root(HWND hwnd)
static const struct prov_method_sequence find_seq6[]
static HRESULT WINAPI Accessible2_get_attributes(IAccessible2 *iface, BSTR *out_attributes)
static void set_find_params(struct UiaFindParams *params, int max_depth, BOOL find_first, BOOL exclude_root, struct UiaCondition *find_cond)
#define PROV_METHOD_TRACE(prov, method)
Definition: uiautomation.c:324
static HRESULT WINAPI Accessible2_get_accState(IAccessible2 *iface, VARIANT child_id, VARIANT *out_state)
static HRESULT WINAPI ProviderHwndOverride_QueryInterface(IRawElementProviderHwndOverride *iface, REFIID riid, void **ppv)
static void set_uia_rect(struct UiaRect *rect, double left, double top, double width, double height)
#define NODE_CREATE_SEQ2_OPTIONAL(prov)
#define DEFINE_PROVIDER(name)
static const struct prov_method_sequence treewalker_seq3[]
static const IRawElementProviderFragmentVtbl ProviderFragmentVtbl
static struct Provider * get_event_test_prov(int idx)
static const struct prov_method_sequence disconnect_prov3[]
static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID param)
#define test_implements_interface(unk, iid, exp_implemented)
Definition: uiautomation.c:439
static SAFEARRAY * create_unk_safearray(void)
static const struct prov_method_sequence reg_prov_cb1[]
static struct prov_method_sequence * sequence
static ULONG WINAPI ClientSideProvider_Release(IRawElementProviderSimple *iface)
static const struct prov_method_sequence cache_req_seq2[]
static void test_UiaGetPropertyValue(void)
static const struct prov_method_sequence element_find_start_seq[]
#define TIME_SINCE_LAST_CALLBACK_TIMEOUT
static HRESULT WINAPI ProxyEventSink_AddAutomationEvent(IProxyProviderWinEventSink *iface, IRawElementProviderSimple *elprov, EVENTID event_id)
static const struct prov_method_sequence reg_prov_cb3[]
static struct Accessible * impl_from_Accessible(IAccessible *iface)
Definition: uiautomation.c:598
static const struct prov_method_sequence reg_prov_cb10[]
static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl
static DWORD WINAPI interface_marshal_proxy_thread(LPVOID param)
static const struct prov_method_sequence find_seq10[]
static const struct UiaCondition UiaTrueCondition
static void test_node_hwnd_provider_navigation_(HUIANODE node, int nav_dir, HWND exp_dest_hwnd, const char *file, int line)
static const struct prov_method_sequence event_seq2[]
#define SET_EXPECT_MULTI(func, num)
Definition: uiautomation.c:344
static void set_cache_request(struct UiaCacheRequest *req, struct UiaCondition *view_cond, int scope, PROPERTYID *prop_ids, int prop_ids_count, PATTERNID *pattern_ids, int pattern_ids_count, int elem_mode)
static HRESULT WINAPI ServiceProvider_QueryService(IServiceProvider *iface, REFGUID service_guid, REFIID riid, void **obj)
#define CHECK_CALLED_AT_MOST(func, num)
Definition: uiautomation.c:380
#define SET_ACC_METHOD_EXPECT_MULTI(acc, method, num)
Definition: uiautomation.c:559
static const double uia_r8_arr_prop_val[]
static HRESULT WINAPI ProviderFragmentRoot_QueryInterface(IRawElementProviderFragmentRoot *iface, REFIID riid, void **ppv)
static const struct prov_method_sequence treewalker_seq9[]
static const struct prov_method_sequence treewalker_seq8[]
static const ULONG uia_i4_prop_val
static HRESULT WINAPI ProviderLegacyIAccessiblePattern_Select(ILegacyIAccessibleProvider *iface, LONG select_flags)
#define PROV_METHOD_TRACE2(prov, method, arg, str_table)
Definition: uiautomation.c:327
static HRESULT WINAPI ProxyEventSink_QueryInterface(IProxyProviderWinEventSink *iface, REFIID riid, void **obj)
static HRESULT WINAPI ProviderValuePattern_SetValue(IValueProvider *iface, LPCWSTR val)
static HRESULT WINAPI Accessible2_get_extendedStates(IAccessible2 *iface, LONG count, BSTR **out_extended_states, LONG *out_extended_states_count)
static const struct prov_method_sequence get_bounding_rect_seq2[]
static const struct prov_method_sequence nav_seq5[]
static void push_expected_com_event(struct node_provider_desc *exp_node_desc)
static const struct prov_method_sequence reg_prov_cb4[]
static const IProxyProviderWinEventHandlerVtbl ProviderWinEventHandlerVtbl
static const struct prov_method_sequence find_seq5[]
static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line)
static HRESULT WINAPI Accessible_accSelect(IAccessible *iface, LONG select_flags, VARIANT child_id)
Definition: uiautomation.c:908
static void set_com_event_data(struct node_provider_desc *exp_node_desc)
static HRESULT WINAPI OleWindow_ContextSensitiveHelp(IOleWindow *iface, BOOL f_enter_mode)
static HRESULT WINAPI OleWindow_QueryInterface(IOleWindow *iface, REFIID riid, void **obj)
static ULONG WINAPI AutomationEventHandler_AddRef(IUIAutomationEventHandler *iface)
static SAFEARRAY * get_safearray_for_elprov(IRawElementProviderSimple *elprov)
static struct EventData EventData2
static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface)
AutomationElementMode
@ AutomationElementMode_Full
@ AutomationElementMode_None
PropertyConditionFlags
@ PropertyConditionFlags_None
@ TreeScope_Parent
@ TreeScope_Descendants
@ TreeScope_Children
@ TreeScope_Subtree
@ TreeScope_Ancestors
@ TreeScope_Element
int PATTERNID
ProviderOptions
@ ProviderOptions_ClientSideProvider
@ ProviderOptions_NonClientAreaProvider
@ ProviderOptions_OverrideProvider
@ ProviderOptions_ServerSideProvider
@ ProviderOptions_UseComThreading
int EVENTID
int PROPERTYID
NavigateDirection
@ NavigateDirection_NextSibling
@ NavigateDirection_PreviousSibling
@ NavigateDirection_Parent
@ NavigateDirection_LastChild
@ NavigateDirection_FirstChild
StructureChangeType
@ StructureChangeType_ChildrenInvalidated
#define UIA_E_ELEMENTNOTAVAILABLE
@ ProviderType_BaseHwnd
@ ProviderType_Proxy
@ ProviderType_NonClientArea
@ NormalizeState_View
@ NormalizeState_Custom
@ NormalizeState_None
#define UiaRootObjectId
#define UiaAppendRuntimeId
#define UIA_PFIA_DEFAULT
@ ConditionType_Not
@ ConditionType_True
@ ConditionType_Or
@ ConditionType_Property
@ ConditionType_False
@ ConditionType_And
@ AutomationIdentifierType_Pattern
@ AutomationIdentifierType_Event
@ AutomationIdentifierType_Property
@ AutomationIdentifierType_ControlType
Definition: dlist.c:348
Definition: pdh_main.c:96
HRESULT WINAPI DECLSPEC_HOTPATCH VariantClear(VARIANTARG *pVarg)
Definition: variant.c:648
void WINAPI VariantInit(VARIANTARG *pVarg)
Definition: variant.c:568
HRESULT WINAPI VariantCopy(VARIANTARG *pvargDest, VARIANTARG *pvargSrc)
Definition: variant.c:748
_Must_inspect_result_ _In_ WDFCOLLECTION _In_ WDFOBJECT Object
void WINAPI NotifyWinEvent(DWORD, HWND, LONG, LONG)
Definition: hook.c:325
#define OBJID_CLIENT
Definition: winable.h:19
#define OBJID_WINDOW
Definition: winable.h:15
#define CHILDID_SELF
Definition: winable.h:14
DWORD WINAPI GetLastError(void)
Definition: except.c:1042
DWORD WINAPI GetCurrentThreadId(void)
Definition: thread.c:459
void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION)
DWORD WINAPI GetCurrentProcessId(void)
Definition: proc.c:1156
DWORD WINAPI GetWindowThreadProcessId(HWND hWnd, PDWORD lpdwProcessId)
void WINAPI EnterCriticalSection(LPCRITICAL_SECTION)
#define WAIT_OBJECT_0
Definition: winbase.h:383
_In_ LONG _In_ HWND hwnd
Definition: winddi.h:4023
_In_ ULONG_PTR _In_ ULONG _Out_ ULONG_PTR * pid
Definition: winddi.h:3837
#define HRESULT
Definition: msvc.h:7
#define WINAPI
Definition: msvc.h:6
#define REGDB_E_CLASSNOTREG
Definition: winerror.h:3801
#define S_FALSE
Definition: winerror.h:3451
#define E_NOINTERFACE
Definition: winerror.h:3479
#define E_POINTER
Definition: winerror.h:3480
#define ERROR_TIMEOUT
Definition: winerror.h:1286
HWND WINAPI GetFocus(void)
Definition: window.c:1863
#define GW_OWNER
Definition: winuser.h:777
#define SW_HIDE
Definition: winuser.h:779
BOOL WINAPI TranslateMessage(_In_ const MSG *)
HWND WINAPI CreateWindowExA(_In_ DWORD dwExStyle, _In_opt_ LPCSTR lpClassName, _In_opt_ LPCSTR lpWindowName, _In_ DWORD dwStyle, _In_ int X, _In_ int Y, _In_ int nWidth, _In_ int nHeight, _In_opt_ HWND hWndParent, _In_opt_ HMENU hMenu, _In_opt_ HINSTANCE hInstance, _In_opt_ LPVOID lpParam)
BOOL WINAPI ShowWindow(_In_ HWND, _In_ int)
BOOL WINAPI UnregisterClassA(_In_ LPCSTR, HINSTANCE)
LRESULT WINAPI DefWindowProcA(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
BOOL WINAPI PostMessageW(_In_opt_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define CreateWindowA(a, b, c, d, e, f, g, h, i, j, k)
Definition: winuser.h:4469
BOOL WINAPI GetWindowRect(_In_ HWND, _Out_ LPRECT)
#define WS_EX_APPWINDOW
Definition: winuser.h:383
int WINAPIV wsprintfW(_Out_ LPWSTR, _In_ _Printf_format_string_ LPCWSTR,...)
#define SW_MINIMIZE
Definition: winuser.h:787
#define STATE_SYSTEM_FOCUSED
Definition: winuser.h:2971
#define WS_EX_TOOLWINDOW
Definition: winuser.h:404
#define GA_PARENT
Definition: winuser.h:2892
#define QS_ALLINPUT
Definition: winuser.h:914
#define WM_GETTEXT
Definition: winuser.h:1646
DWORD WINAPI MsgWaitForMultipleObjects(_In_ DWORD nCount, _In_reads_opt_(nCount) CONST HANDLE *pHandles, _In_ BOOL fWaitAll, _In_ DWORD dwMilliseconds, _In_ DWORD dwWakeMask)
int WINAPI MapWindowPoints(_In_opt_ HWND hWndFrom, _In_opt_ HWND hWndTo, _Inout_updates_(cPoints) LPPOINT lpPoints, _In_ UINT cPoints)
HWND WINAPI GetDesktopWindow(void)
Definition: window.c:628
BOOL WINAPI GetClientRect(_In_ HWND, _Out_ LPRECT)
ATOM WINAPI RegisterClassA(_In_ CONST WNDCLASSA *)
#define STATE_SYSTEM_FOCUSABLE
Definition: winuser.h:2989
HWND WINAPI SetFocus(_In_opt_ HWND)
BOOL WINAPI PeekMessageW(_Out_ LPMSG, _In_opt_ HWND, _In_ UINT, _In_ UINT, _In_ UINT)
#define PM_REMOVE
Definition: winuser.h:1207
#define STATE_SYSTEM_INVISIBLE
Definition: winuser.h:2984
#define STATE_SYSTEM_OFFSCREEN
Definition: winuser.h:2985
HWND WINAPI GetParent(_In_ HWND)
HWND WINAPI GetWindow(_In_ HWND, _In_ UINT)
int WINAPI GetClassNameW(_In_ HWND hWnd, _Out_writes_to_(nMaxCount, return) LPWSTR lpClassName, _In_ int nMaxCount)
LRESULT WINAPI DispatchMessageW(_In_ const MSG *)
#define SW_SHOW
Definition: winuser.h:786
HWND WINAPI FindWindowA(_In_opt_ LPCSTR, _In_opt_ LPCSTR)
BOOL WINAPI IsWindowVisible(_In_ HWND)
BOOL WINAPI DestroyWindow(_In_ HWND)
HWND WINAPI GetAncestor(_In_ HWND, _In_ UINT)
Definition: window.c:929
LRESULT WINAPI SendMessageW(_In_ HWND, _In_ UINT, _In_ WPARAM, _In_ LPARAM)
#define STATE_SYSTEM_PROTECTED
Definition: winuser.h:2998