2 * Copyright 2022 Connor McAdams for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "uia_private.h"
22 #include "wine/debug.h"
24 #include "wine/iaccessible2.h"
26 WINE_DEFAULT_DEBUG_CHANNEL(uiautomation
);
28 DEFINE_GUID(SID_AccFromDAWrapper
, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
30 /* Returns S_OK if flag is set, S_FALSE if it is not. */
31 static HRESULT
msaa_check_acc_state_hres(IAccessible
*acc
, VARIANT cid
, ULONG flag
)
37 hr
= IAccessible_get_accState(acc
, cid
, &v
);
39 hr
= ((V_VT(&v
) == VT_I4
) && (V_I4(&v
) & flag
)) ? S_OK
: S_FALSE
;
44 static BOOL
msaa_check_acc_state(IAccessible
*acc
, VARIANT cid
, ULONG flag
)
46 return msaa_check_acc_state_hres(acc
, cid
, flag
) == S_OK
;
49 static HRESULT
msaa_acc_get_service(IAccessible
*acc
, REFGUID sid
, REFIID riid
, void **service
)
55 hr
= IAccessible_QueryInterface(acc
, &IID_IServiceProvider
, (void **)&sp
);
59 hr
= IServiceProvider_QueryService(sp
, sid
, riid
, (void **)service
);
60 IServiceProvider_Release(sp
);
64 static IAccessible2
*msaa_acc_get_ia2(IAccessible
*acc
)
66 IAccessible2
*ia2
= NULL
;
69 hr
= msaa_acc_get_service(acc
, &IID_IAccessible2
, &IID_IAccessible2
, (void **)&ia2
);
70 if (SUCCEEDED(hr
) && ia2
)
73 hr
= IAccessible_QueryInterface(acc
, &IID_IAccessible2
, (void **)&ia2
);
74 if (SUCCEEDED(hr
) && ia2
)
80 static IAccessible
*msaa_acc_da_unwrap(IAccessible
*acc
)
85 hr
= msaa_acc_get_service(acc
, &SID_AccFromDAWrapper
, &IID_IAccessible
, (void **)&acc2
);
86 if (SUCCEEDED(hr
) && acc2
)
89 IAccessible_AddRef(acc
);
93 static BOOL
msaa_acc_is_oleacc_proxy(IAccessible
*acc
)
98 hr
= msaa_acc_get_service(acc
, &IIS_IsOleaccProxy
, &IID_IUnknown
, (void **)&unk
);
99 if (SUCCEEDED(hr
) && unk
)
101 IUnknown_Release(unk
);
109 * Compare role, state, child count, and location properties of the two
110 * IAccessibles. If all four are successfully retrieved and are equal, this is
111 * considered a match.
113 static HRESULT
msaa_acc_prop_match(IAccessible
*acc
, IAccessible
*acc2
)
115 BOOL role_match
, state_match
, child_count_match
, location_match
;
116 LONG child_count
[2], left
[2], top
[2], width
[2], height
[2];
120 role_match
= state_match
= child_count_match
= location_match
= FALSE
;
121 variant_init_i4(&cid
, CHILDID_SELF
);
122 hr
= IAccessible_get_accRole(acc
, cid
, &v
);
123 if (SUCCEEDED(hr
) && (V_VT(&v
) == VT_I4
))
126 hr
= IAccessible_get_accRole(acc2
, cid
, &v2
);
127 if (SUCCEEDED(hr
) && (V_VT(&v2
) == VT_I4
))
129 if (V_I4(&v
) != V_I4(&v2
))
137 hr
= IAccessible_get_accState(acc
, cid
, &v
);
138 if (SUCCEEDED(hr
) && (V_VT(&v
) == VT_I4
))
141 hr
= IAccessible_get_accState(acc2
, cid
, &v2
);
142 if (SUCCEEDED(hr
) && (V_VT(&v2
) == VT_I4
))
144 if (V_I4(&v
) != V_I4(&v2
))
151 hr
= IAccessible_get_accChildCount(acc
, &child_count
[0]);
152 hr2
= IAccessible_get_accChildCount(acc2
, &child_count
[1]);
153 if (SUCCEEDED(hr
) && SUCCEEDED(hr2
))
155 if (child_count
[0] != child_count
[1])
158 child_count_match
= TRUE
;
161 hr
= IAccessible_accLocation(acc
, &left
[0], &top
[0], &width
[0], &height
[0], cid
);
164 hr
= IAccessible_accLocation(acc2
, &left
[1], &top
[1], &width
[1], &height
[1], cid
);
167 if ((left
[0] != left
[1]) || (top
[0] != top
[1]) || (width
[0] != width
[1]) ||
168 (height
[0] != height
[1]))
171 location_match
= TRUE
;
175 if (role_match
&& state_match
&& child_count_match
&& location_match
)
181 static BOOL
msaa_acc_iface_cmp(IAccessible
*acc
, IAccessible
*acc2
)
183 IUnknown
*unk
, *unk2
;
186 acc
= msaa_acc_da_unwrap(acc
);
187 acc2
= msaa_acc_da_unwrap(acc2
);
188 IAccessible_QueryInterface(acc
, &IID_IUnknown
, (void**)&unk
);
189 IAccessible_QueryInterface(acc2
, &IID_IUnknown
, (void**)&unk2
);
190 matched
= (unk
== unk2
);
192 IAccessible_Release(acc
);
193 IUnknown_Release(unk
);
194 IAccessible_Release(acc2
);
195 IUnknown_Release(unk2
);
200 static BOOL
msaa_acc_compare(IAccessible
*acc
, IAccessible
*acc2
)
202 IAccessible2
*ia2
[2] = { NULL
, NULL
};
203 IUnknown
*unk
, *unk2
;
204 BOOL matched
= FALSE
;
210 acc
= msaa_acc_da_unwrap(acc
);
211 acc2
= msaa_acc_da_unwrap(acc2
);
212 IAccessible_QueryInterface(acc
, &IID_IUnknown
, (void**)&unk
);
213 IAccessible_QueryInterface(acc2
, &IID_IUnknown
, (void**)&unk2
);
220 ia2
[0] = msaa_acc_get_ia2(acc
);
221 ia2
[1] = msaa_acc_get_ia2(acc2
);
222 if (!ia2
[0] != !ia2
[1])
226 hr
= IAccessible2_get_uniqueID(ia2
[0], &unique_id
[0]);
229 hr
= IAccessible2_get_uniqueID(ia2
[1], &unique_id
[1]);
232 if (unique_id
[0] == unique_id
[1])
240 hr
= msaa_acc_prop_match(acc
, acc2
);
246 variant_init_i4(&cid
, CHILDID_SELF
);
247 hr
= IAccessible_get_accName(acc
, cid
, &name
[0]);
250 hr
= IAccessible_get_accName(acc2
, cid
, &name
[1]);
253 if (!name
[0] && !name
[1])
255 else if (!name
[0] || !name
[1])
259 if (!wcscmp(name
[0], name
[1]))
265 SysFreeString(name
[1]);
268 SysFreeString(name
[0]);
272 IUnknown_Release(unk
);
273 IUnknown_Release(unk2
);
274 IAccessible_Release(acc
);
275 IAccessible_Release(acc2
);
277 IAccessible2_Release(ia2
[0]);
279 IAccessible2_Release(ia2
[1]);
284 static HRESULT
msaa_acc_get_parent(IAccessible
*acc
, IAccessible
**parent
)
286 IDispatch
*disp
= NULL
;
290 hr
= IAccessible_get_accParent(acc
, &disp
);
291 if (FAILED(hr
) || !disp
)
294 hr
= IDispatch_QueryInterface(disp
, &IID_IAccessible
, (void**)parent
);
295 IDispatch_Release(disp
);
299 #define DIR_FORWARD 0
300 #define DIR_REVERSE 1
301 static HRESULT
msaa_acc_get_next_child(IAccessible
*acc
, LONG start_pos
, LONG direction
,
302 IAccessible
**child
, LONG
*child_id
, LONG
*child_pos
, BOOL check_visible
)
304 LONG child_count
, cur_pos
;
314 hr
= IAccessible_get_accChildCount(acc
, &child_count
);
315 if (FAILED(hr
) || (cur_pos
> child_count
))
318 variant_init_i4(&cid
, cur_pos
);
319 hr
= IAccessible_get_accChild(acc
, cid
, &disp
);
325 if (!check_visible
|| !msaa_check_acc_state(acc
, cid
, STATE_SYSTEM_INVISIBLE
))
328 *child_id
= *child_pos
= cur_pos
;
329 IAccessible_AddRef(acc
);
335 IAccessible
*acc_child
= NULL
;
337 hr
= IDispatch_QueryInterface(disp
, &IID_IAccessible
, (void **)&acc_child
);
338 IDispatch_Release(disp
);
342 variant_init_i4(&cid
, CHILDID_SELF
);
343 if (!check_visible
|| !msaa_check_acc_state(acc_child
, cid
, STATE_SYSTEM_INVISIBLE
))
346 *child_id
= CHILDID_SELF
;
347 *child_pos
= cur_pos
;
351 IAccessible_Release(acc_child
);
354 if (direction
== DIR_FORWARD
)
359 if ((cur_pos
> child_count
) || (cur_pos
<= 0))
366 static HRESULT
msaa_acc_get_child_pos(IAccessible
*acc
, IAccessible
**out_parent
,
369 LONG child_count
, child_id
, child_pos
, match_pos
;
370 IAccessible
*child
, *parent
, *match
, **children
;
376 hr
= msaa_acc_get_parent(acc
, &parent
);
377 if (FAILED(hr
) || !parent
)
380 hr
= IAccessible_get_accChildCount(parent
, &child_count
);
381 if (FAILED(hr
) || !child_count
)
383 IAccessible_Release(parent
);
387 children
= calloc(child_count
, sizeof(*children
));
389 return E_OUTOFMEMORY
;
392 for (i
= 0; i
< child_count
; i
++)
394 hr
= msaa_acc_get_next_child(parent
, i
+ 1, DIR_FORWARD
, &child
, &child_id
, &child_pos
, FALSE
);
395 if (FAILED(hr
) || !child
)
401 IAccessible_Release(child
);
404 for (i
= 0; i
< child_count
; i
++)
409 if (msaa_acc_compare(acc
, children
[i
]))
416 /* Can't have more than one IAccessible match. */
429 *out_parent
= parent
;
430 *out_child_pos
= match_pos
;
433 IAccessible_Release(parent
);
435 for (i
= 0; i
< child_count
; i
++)
438 IAccessible_Release(children
[i
]);
446 static LONG
msaa_role_to_uia_control_type(LONG role
)
450 case ROLE_SYSTEM_TITLEBAR
: return UIA_TitleBarControlTypeId
;
451 case ROLE_SYSTEM_MENUBAR
: return UIA_MenuBarControlTypeId
;
452 case ROLE_SYSTEM_SCROLLBAR
: return UIA_ScrollBarControlTypeId
;
453 case ROLE_SYSTEM_INDICATOR
:
454 case ROLE_SYSTEM_GRIP
: return UIA_ThumbControlTypeId
;
455 case ROLE_SYSTEM_APPLICATION
:
456 case ROLE_SYSTEM_WINDOW
: return UIA_WindowControlTypeId
;
457 case ROLE_SYSTEM_MENUPOPUP
: return UIA_MenuControlTypeId
;
458 case ROLE_SYSTEM_TOOLTIP
: return UIA_ToolTipControlTypeId
;
459 case ROLE_SYSTEM_DOCUMENT
: return UIA_DocumentControlTypeId
;
460 case ROLE_SYSTEM_PANE
: return UIA_PaneControlTypeId
;
461 case ROLE_SYSTEM_GROUPING
: return UIA_GroupControlTypeId
;
462 case ROLE_SYSTEM_SEPARATOR
: return UIA_SeparatorControlTypeId
;
463 case ROLE_SYSTEM_TOOLBAR
: return UIA_ToolBarControlTypeId
;
464 case ROLE_SYSTEM_STATUSBAR
: return UIA_StatusBarControlTypeId
;
465 case ROLE_SYSTEM_TABLE
: return UIA_TableControlTypeId
;
466 case ROLE_SYSTEM_COLUMNHEADER
:
467 case ROLE_SYSTEM_ROWHEADER
: return UIA_HeaderControlTypeId
;
468 case ROLE_SYSTEM_CELL
: return UIA_DataItemControlTypeId
;
469 case ROLE_SYSTEM_LINK
: return UIA_HyperlinkControlTypeId
;
470 case ROLE_SYSTEM_LIST
: return UIA_ListControlTypeId
;
471 case ROLE_SYSTEM_LISTITEM
: return UIA_ListItemControlTypeId
;
472 case ROLE_SYSTEM_OUTLINE
: return UIA_TreeControlTypeId
;
473 case ROLE_SYSTEM_OUTLINEITEM
: return UIA_TreeItemControlTypeId
;
474 case ROLE_SYSTEM_PAGETAB
: return UIA_TabItemControlTypeId
;
475 case ROLE_SYSTEM_GRAPHIC
: return UIA_ImageControlTypeId
;
476 case ROLE_SYSTEM_STATICTEXT
: return UIA_TextControlTypeId
;
477 case ROLE_SYSTEM_TEXT
: return UIA_EditControlTypeId
;
478 case ROLE_SYSTEM_CLOCK
:
479 case ROLE_SYSTEM_BUTTONDROPDOWNGRID
:
480 case ROLE_SYSTEM_PUSHBUTTON
: return UIA_ButtonControlTypeId
;
481 case ROLE_SYSTEM_CHECKBUTTON
: return UIA_CheckBoxControlTypeId
;
482 case ROLE_SYSTEM_RADIOBUTTON
: return UIA_RadioButtonControlTypeId
;
483 case ROLE_SYSTEM_COMBOBOX
: return UIA_ComboBoxControlTypeId
;
484 case ROLE_SYSTEM_PROGRESSBAR
: return UIA_ProgressBarControlTypeId
;
485 case ROLE_SYSTEM_SLIDER
: return UIA_SliderControlTypeId
;
486 case ROLE_SYSTEM_SPINBUTTON
: return UIA_SpinnerControlTypeId
;
487 case ROLE_SYSTEM_BUTTONMENU
:
488 case ROLE_SYSTEM_MENUITEM
: return UIA_MenuItemControlTypeId
;
489 case ROLE_SYSTEM_PAGETABLIST
: return UIA_TabControlTypeId
;
490 case ROLE_SYSTEM_BUTTONDROPDOWN
:
491 case ROLE_SYSTEM_SPLITBUTTON
: return UIA_SplitButtonControlTypeId
;
492 case ROLE_SYSTEM_SOUND
:
493 case ROLE_SYSTEM_CURSOR
:
494 case ROLE_SYSTEM_CARET
:
495 case ROLE_SYSTEM_ALERT
:
496 case ROLE_SYSTEM_CLIENT
:
497 case ROLE_SYSTEM_CHART
:
498 case ROLE_SYSTEM_DIALOG
:
499 case ROLE_SYSTEM_BORDER
:
500 case ROLE_SYSTEM_COLUMN
:
501 case ROLE_SYSTEM_ROW
:
502 case ROLE_SYSTEM_HELPBALLOON
:
503 case ROLE_SYSTEM_CHARACTER
:
504 case ROLE_SYSTEM_PROPERTYPAGE
:
505 case ROLE_SYSTEM_DROPLIST
:
506 case ROLE_SYSTEM_DIAL
:
507 case ROLE_SYSTEM_HOTKEYFIELD
:
508 case ROLE_SYSTEM_DIAGRAM
:
509 case ROLE_SYSTEM_ANIMATION
:
510 case ROLE_SYSTEM_EQUATION
:
511 case ROLE_SYSTEM_WHITESPACE
:
512 case ROLE_SYSTEM_IPADDRESS
:
513 case ROLE_SYSTEM_OUTLINEBUTTON
:
514 WARN("No UIA control type mapping for MSAA role %ld\n", role
);
518 FIXME("UIA control type mapping unimplemented for MSAA role %ld\n", role
);
526 * UiaProviderFromIAccessible IRawElementProviderSimple interface.
528 struct msaa_provider
{
529 IRawElementProviderSimple IRawElementProviderSimple_iface
;
530 IRawElementProviderFragment IRawElementProviderFragment_iface
;
531 IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface
;
532 ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface
;
533 IProxyProviderWinEventHandler IProxyProviderWinEventHandler_iface
;
542 BOOL root_acc_check_ran
;
549 static BOOL
msaa_check_root_acc(struct msaa_provider
*msaa_prov
)
554 if (msaa_prov
->root_acc_check_ran
)
555 return msaa_prov
->is_root_acc
;
557 msaa_prov
->root_acc_check_ran
= TRUE
;
558 if (V_I4(&msaa_prov
->cid
) != CHILDID_SELF
|| msaa_prov
->parent
)
561 hr
= AccessibleObjectFromWindow(msaa_prov
->hwnd
, OBJID_CLIENT
, &IID_IAccessible
, (void **)&acc
);
565 if (msaa_acc_compare(msaa_prov
->acc
, acc
))
566 msaa_prov
->is_root_acc
= TRUE
;
568 IAccessible_Release(acc
);
569 return msaa_prov
->is_root_acc
;
572 static inline struct msaa_provider
*impl_from_msaa_provider(IRawElementProviderSimple
*iface
)
574 return CONTAINING_RECORD(iface
, struct msaa_provider
, IRawElementProviderSimple_iface
);
577 HRESULT WINAPI
msaa_provider_QueryInterface(IRawElementProviderSimple
*iface
, REFIID riid
, void **ppv
)
579 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
582 if (IsEqualIID(riid
, &IID_IRawElementProviderSimple
) || IsEqualIID(riid
, &IID_IUnknown
))
584 else if (IsEqualIID(riid
, &IID_IRawElementProviderFragment
))
585 *ppv
= &msaa_prov
->IRawElementProviderFragment_iface
;
586 else if (IsEqualIID(riid
, &IID_IRawElementProviderFragmentRoot
))
587 *ppv
= &msaa_prov
->IRawElementProviderFragmentRoot_iface
;
588 else if (IsEqualIID(riid
, &IID_ILegacyIAccessibleProvider
))
589 *ppv
= &msaa_prov
->ILegacyIAccessibleProvider_iface
;
590 else if (IsEqualIID(riid
, &IID_IProxyProviderWinEventHandler
))
591 *ppv
= &msaa_prov
->IProxyProviderWinEventHandler_iface
;
593 return E_NOINTERFACE
;
595 IRawElementProviderSimple_AddRef(iface
);
599 ULONG WINAPI
msaa_provider_AddRef(IRawElementProviderSimple
*iface
)
601 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
602 ULONG refcount
= InterlockedIncrement(&msaa_prov
->refcount
);
604 TRACE("%p, refcount %ld\n", iface
, refcount
);
609 ULONG WINAPI
msaa_provider_Release(IRawElementProviderSimple
*iface
)
611 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
612 ULONG refcount
= InterlockedDecrement(&msaa_prov
->refcount
);
614 TRACE("%p, refcount %ld\n", iface
, refcount
);
618 IAccessible_Release(msaa_prov
->acc
);
619 if (msaa_prov
->parent
)
620 IAccessible_Release(msaa_prov
->parent
);
622 IAccessible2_Release(msaa_prov
->ia2
);
629 HRESULT WINAPI
msaa_provider_get_ProviderOptions(IRawElementProviderSimple
*iface
,
630 enum ProviderOptions
*ret_val
)
632 TRACE("%p, %p\n", iface
, ret_val
);
633 *ret_val
= ProviderOptions_ServerSideProvider
| ProviderOptions_UseComThreading
;
637 HRESULT WINAPI
msaa_provider_GetPatternProvider(IRawElementProviderSimple
*iface
,
638 PATTERNID pattern_id
, IUnknown
**ret_val
)
640 TRACE("%p, %d, %p\n", iface
, pattern_id
, ret_val
);
645 case UIA_LegacyIAccessiblePatternId
:
646 return IRawElementProviderSimple_QueryInterface(iface
, &IID_IUnknown
, (void **)ret_val
);
649 FIXME("Unimplemented patternId %d\n", pattern_id
);
656 HRESULT WINAPI
msaa_provider_GetPropertyValue(IRawElementProviderSimple
*iface
,
657 PROPERTYID prop_id
, VARIANT
*ret_val
)
659 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
663 TRACE("%p, %d, %p\n", iface
, prop_id
, ret_val
);
665 VariantInit(ret_val
);
669 case UIA_ProviderDescriptionPropertyId
:
670 V_VT(ret_val
) = VT_BSTR
;
671 V_BSTR(ret_val
) = SysAllocString(L
"Wine: MSAA Proxy");
674 case UIA_ControlTypePropertyId
:
675 if (!msaa_prov
->control_type
)
677 hr
= IAccessible_get_accRole(msaa_prov
->acc
, msaa_prov
->cid
, &v
);
678 if (SUCCEEDED(hr
) && (V_VT(&v
) == VT_I4
))
679 msaa_prov
->control_type
= msaa_role_to_uia_control_type(V_I4(&v
));
682 if (msaa_prov
->control_type
)
683 variant_init_i4(ret_val
, msaa_prov
->control_type
);
687 case UIA_HasKeyboardFocusPropertyId
:
688 hr
= msaa_check_acc_state_hres(msaa_prov
->acc
, msaa_prov
->cid
, STATE_SYSTEM_FOCUSED
);
692 variant_init_bool(ret_val
, hr
== S_OK
);
695 case UIA_IsKeyboardFocusablePropertyId
:
696 hr
= msaa_check_acc_state_hres(msaa_prov
->acc
, msaa_prov
->cid
, STATE_SYSTEM_FOCUSABLE
);
700 variant_init_bool(ret_val
, hr
== S_OK
);
703 case UIA_IsEnabledPropertyId
:
704 hr
= msaa_check_acc_state_hres(msaa_prov
->acc
, msaa_prov
->cid
, STATE_SYSTEM_UNAVAILABLE
);
708 variant_init_bool(ret_val
, hr
== S_FALSE
);
711 case UIA_IsPasswordPropertyId
:
712 hr
= msaa_check_acc_state_hres(msaa_prov
->acc
, msaa_prov
->cid
, STATE_SYSTEM_PROTECTED
);
716 variant_init_bool(ret_val
, hr
== S_OK
);
719 case UIA_NamePropertyId
:
723 hr
= IAccessible_get_accName(msaa_prov
->acc
, msaa_prov
->cid
, &name
);
724 if (SUCCEEDED(hr
) && name
)
726 V_VT(ret_val
) = VT_BSTR
;
727 V_BSTR(ret_val
) = name
;
732 case UIA_IsOffscreenPropertyId
:
734 RECT rect
[2] = { 0 };
738 variant_init_bool(ret_val
, FALSE
);
739 if (msaa_check_acc_state(msaa_prov
->acc
, msaa_prov
->cid
, STATE_SYSTEM_OFFSCREEN
))
741 variant_init_bool(ret_val
, TRUE
);
745 hr
= IAccessible_accLocation(msaa_prov
->acc
, &rect
[0].left
, &rect
[0].top
, &width
, &height
, msaa_prov
->cid
);
749 rect
[0].right
= rect
[0].left
+ width
;
750 rect
[0].bottom
= rect
[0].top
+ height
;
751 SetLastError(NOERROR
);
752 if (!GetClientRect(msaa_prov
->hwnd
, &rect
[1]))
754 if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE
)
755 variant_init_bool(ret_val
, TRUE
);
759 SetLastError(NOERROR
);
760 if (!MapWindowPoints(msaa_prov
->hwnd
, NULL
, (POINT
*)&rect
[1], 2) && GetLastError())
762 if (GetLastError() == ERROR_INVALID_WINDOW_HANDLE
)
763 variant_init_bool(ret_val
, TRUE
);
767 variant_init_bool(ret_val
, !IntersectRect(&intersect_rect
, &rect
[0], &rect
[1]));
772 FIXME("Unimplemented propertyId %d\n", prop_id
);
779 HRESULT WINAPI
msaa_provider_get_HostRawElementProvider(IRawElementProviderSimple
*iface
,
780 IRawElementProviderSimple
**ret_val
)
782 struct msaa_provider
*msaa_prov
= impl_from_msaa_provider(iface
);
784 TRACE("%p, %p\n", iface
, ret_val
);
787 if (msaa_check_root_acc(msaa_prov
))
788 return UiaHostProviderFromHwnd(msaa_prov
->hwnd
, ret_val
);
793 static const IRawElementProviderSimpleVtbl msaa_provider_vtbl
= {
794 msaa_provider_QueryInterface
,
795 msaa_provider_AddRef
,
796 msaa_provider_Release
,
797 msaa_provider_get_ProviderOptions
,
798 msaa_provider_GetPatternProvider
,
799 msaa_provider_GetPropertyValue
,
800 msaa_provider_get_HostRawElementProvider
,
804 * IRawElementProviderFragment interface for UiaProviderFromIAccessible
807 static inline struct msaa_provider
*impl_from_msaa_fragment(IRawElementProviderFragment
*iface
)
809 return CONTAINING_RECORD(iface
, struct msaa_provider
, IRawElementProviderFragment_iface
);
812 static HRESULT WINAPI
msaa_fragment_QueryInterface(IRawElementProviderFragment
*iface
, REFIID riid
,
815 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment(iface
);
816 return IRawElementProviderSimple_QueryInterface(&msaa_prov
->IRawElementProviderSimple_iface
, riid
, ppv
);
819 static ULONG WINAPI
msaa_fragment_AddRef(IRawElementProviderFragment
*iface
)
821 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment(iface
);
822 return IRawElementProviderSimple_AddRef(&msaa_prov
->IRawElementProviderSimple_iface
);
825 static ULONG WINAPI
msaa_fragment_Release(IRawElementProviderFragment
*iface
)
827 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment(iface
);
828 return IRawElementProviderSimple_Release(&msaa_prov
->IRawElementProviderSimple_iface
);
831 static HRESULT WINAPI
msaa_fragment_Navigate(IRawElementProviderFragment
*iface
,
832 enum NavigateDirection direction
, IRawElementProviderFragment
**ret_val
)
834 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment(iface
);
835 LONG child_count
, child_id
, child_pos
;
836 IRawElementProviderSimple
*elprov
;
840 TRACE("%p, %d, %p\n", iface
, direction
, ret_val
);
845 case NavigateDirection_Parent
:
846 if (msaa_check_root_acc(msaa_prov
))
849 if (V_I4(&msaa_prov
->cid
) == CHILDID_SELF
)
851 hr
= msaa_acc_get_parent(msaa_prov
->acc
, &acc
);
852 if (FAILED(hr
) || !acc
)
856 acc
= msaa_prov
->acc
;
858 hr
= create_msaa_provider(acc
, CHILDID_SELF
, NULL
, FALSE
, FALSE
, &elprov
);
861 struct msaa_provider
*prov
= impl_from_msaa_provider(elprov
);
862 *ret_val
= &prov
->IRawElementProviderFragment_iface
;
865 if (acc
!= msaa_prov
->acc
)
866 IAccessible_Release(acc
);
870 case NavigateDirection_FirstChild
:
871 case NavigateDirection_LastChild
:
872 if (V_I4(&msaa_prov
->cid
) != CHILDID_SELF
)
875 hr
= IAccessible_get_accChildCount(msaa_prov
->acc
, &child_count
);
876 if (FAILED(hr
) || !child_count
)
879 if (direction
== NavigateDirection_FirstChild
)
880 hr
= msaa_acc_get_next_child(msaa_prov
->acc
, 1, DIR_FORWARD
, &acc
, &child_id
,
883 hr
= msaa_acc_get_next_child(msaa_prov
->acc
, child_count
, DIR_REVERSE
, &acc
, &child_id
,
886 if (FAILED(hr
) || !acc
)
889 hr
= create_msaa_provider(acc
, child_id
, NULL
, FALSE
, FALSE
, &elprov
);
892 struct msaa_provider
*prov
= impl_from_msaa_provider(elprov
);
894 *ret_val
= &prov
->IRawElementProviderFragment_iface
;
895 prov
->parent
= msaa_prov
->acc
;
896 IAccessible_AddRef(msaa_prov
->acc
);
897 if (acc
!= msaa_prov
->acc
)
898 prov
->child_pos
= child_pos
;
900 prov
->child_pos
= child_id
;
902 IAccessible_Release(acc
);
906 case NavigateDirection_NextSibling
:
907 case NavigateDirection_PreviousSibling
:
908 if (msaa_check_root_acc(msaa_prov
))
911 if (!msaa_prov
->parent
)
913 if (V_I4(&msaa_prov
->cid
) != CHILDID_SELF
)
915 msaa_prov
->parent
= msaa_prov
->acc
;
916 IAccessible_AddRef(msaa_prov
->acc
);
917 msaa_prov
->child_pos
= V_I4(&msaa_prov
->cid
);
921 hr
= msaa_acc_get_child_pos(msaa_prov
->acc
, &acc
, &child_pos
);
922 if (FAILED(hr
) || !acc
)
924 msaa_prov
->parent
= acc
;
925 msaa_prov
->child_pos
= child_pos
;
929 if (direction
== NavigateDirection_NextSibling
)
930 hr
= msaa_acc_get_next_child(msaa_prov
->parent
, msaa_prov
->child_pos
+ 1, DIR_FORWARD
,
931 &acc
, &child_id
, &child_pos
, TRUE
);
933 hr
= msaa_acc_get_next_child(msaa_prov
->parent
, msaa_prov
->child_pos
- 1, DIR_REVERSE
,
934 &acc
, &child_id
, &child_pos
, TRUE
);
936 if (FAILED(hr
) || !acc
)
939 hr
= create_msaa_provider(acc
, child_id
, NULL
, FALSE
, FALSE
, &elprov
);
942 struct msaa_provider
*prov
= impl_from_msaa_provider(elprov
);
944 *ret_val
= &prov
->IRawElementProviderFragment_iface
;
945 prov
->parent
= msaa_prov
->parent
;
946 IAccessible_AddRef(msaa_prov
->parent
);
947 if (acc
!= msaa_prov
->acc
)
948 prov
->child_pos
= child_pos
;
950 prov
->child_pos
= child_id
;
952 IAccessible_Release(acc
);
957 FIXME("Invalid NavigateDirection %d\n", direction
);
964 static HRESULT WINAPI
msaa_fragment_GetRuntimeId(IRawElementProviderFragment
*iface
,
967 FIXME("%p, %p: stub!\n", iface
, ret_val
);
972 static HRESULT WINAPI
msaa_fragment_get_BoundingRectangle(IRawElementProviderFragment
*iface
,
973 struct UiaRect
*ret_val
)
975 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment(iface
);
976 LONG left
, top
, width
, height
;
979 TRACE("%p, %p\n", iface
, ret_val
);
981 memset(ret_val
, 0, sizeof(*ret_val
));
984 * If this IAccessible is at the root of its HWND, the BaseHwnd provider
985 * will supply the bounding rectangle.
987 if (msaa_check_root_acc(msaa_prov
))
990 if (msaa_check_acc_state(msaa_prov
->acc
, msaa_prov
->cid
, STATE_SYSTEM_OFFSCREEN
))
993 hr
= IAccessible_accLocation(msaa_prov
->acc
, &left
, &top
, &width
, &height
, msaa_prov
->cid
);
997 ret_val
->left
= left
;
999 ret_val
->width
= width
;
1000 ret_val
->height
= height
;
1005 static HRESULT WINAPI
msaa_fragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment
*iface
,
1006 SAFEARRAY
**ret_val
)
1008 FIXME("%p, %p: stub!\n", iface
, ret_val
);
1013 static HRESULT WINAPI
msaa_fragment_SetFocus(IRawElementProviderFragment
*iface
)
1015 FIXME("%p: stub!\n", iface
);
1019 static HRESULT WINAPI
msaa_fragment_get_FragmentRoot(IRawElementProviderFragment
*iface
,
1020 IRawElementProviderFragmentRoot
**ret_val
)
1022 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment(iface
);
1023 IRawElementProviderSimple
*elprov
;
1027 TRACE("%p, %p\n", iface
, ret_val
);
1030 hr
= AccessibleObjectFromWindow(msaa_prov
->hwnd
, OBJID_CLIENT
, &IID_IAccessible
, (void **)&acc
);
1031 if (FAILED(hr
) || !acc
)
1034 hr
= create_msaa_provider(acc
, CHILDID_SELF
, msaa_prov
->hwnd
, TRUE
, TRUE
, &elprov
);
1035 IAccessible_Release(acc
);
1039 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragmentRoot
, (void **)ret_val
);
1040 IRawElementProviderSimple_Release(elprov
);
1045 static const IRawElementProviderFragmentVtbl msaa_fragment_vtbl
= {
1046 msaa_fragment_QueryInterface
,
1047 msaa_fragment_AddRef
,
1048 msaa_fragment_Release
,
1049 msaa_fragment_Navigate
,
1050 msaa_fragment_GetRuntimeId
,
1051 msaa_fragment_get_BoundingRectangle
,
1052 msaa_fragment_GetEmbeddedFragmentRoots
,
1053 msaa_fragment_SetFocus
,
1054 msaa_fragment_get_FragmentRoot
,
1058 * IRawElementProviderFragmentRoot interface for UiaProviderFromIAccessible
1061 static inline struct msaa_provider
*impl_from_msaa_fragment_root(IRawElementProviderFragmentRoot
*iface
)
1063 return CONTAINING_RECORD(iface
, struct msaa_provider
, IRawElementProviderFragmentRoot_iface
);
1066 static HRESULT WINAPI
msaa_fragment_root_QueryInterface(IRawElementProviderFragmentRoot
*iface
, REFIID riid
,
1069 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment_root(iface
);
1070 return IRawElementProviderSimple_QueryInterface(&msaa_prov
->IRawElementProviderSimple_iface
, riid
, ppv
);
1073 static ULONG WINAPI
msaa_fragment_root_AddRef(IRawElementProviderFragmentRoot
*iface
)
1075 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment_root(iface
);
1076 return IRawElementProviderSimple_AddRef(&msaa_prov
->IRawElementProviderSimple_iface
);
1079 static ULONG WINAPI
msaa_fragment_root_Release(IRawElementProviderFragmentRoot
*iface
)
1081 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment_root(iface
);
1082 return IRawElementProviderSimple_Release(&msaa_prov
->IRawElementProviderSimple_iface
);
1085 static HRESULT WINAPI
msaa_fragment_root_ElementProviderFromPoint(IRawElementProviderFragmentRoot
*iface
,
1086 double x
, double y
, IRawElementProviderFragment
**ret_val
)
1088 FIXME("%p, %f, %f, %p: stub!\n", iface
, x
, y
, ret_val
);
1093 static HRESULT
msaa_acc_get_focus(struct msaa_provider
*prov
, struct msaa_provider
**out_prov
)
1095 IRawElementProviderSimple
*elprov
;
1096 IAccessible
*focus_acc
= NULL
;
1097 INT focus_cid
= CHILDID_SELF
;
1104 if (V_I4(&prov
->cid
) != CHILDID_SELF
)
1108 hr
= IAccessible_get_accFocus(prov
->acc
, &v
);
1109 if (FAILED(hr
) || (V_VT(&v
) != VT_I4
&& V_VT(&v
) != VT_DISPATCH
))
1115 if (V_VT(&v
) == VT_I4
)
1117 IDispatch
*disp
= NULL
;
1119 if (V_I4(&v
) == CHILDID_SELF
)
1122 hr
= IAccessible_get_accChild(prov
->acc
, v
, &disp
);
1129 focus_acc
= prov
->acc
;
1130 IAccessible_AddRef(focus_acc
);
1131 focus_cid
= V_I4(&v
);
1135 V_VT(&v
) = VT_DISPATCH
;
1136 V_DISPATCH(&v
) = disp
;
1142 if (V_VT(&v
) == VT_DISPATCH
)
1144 hr
= IDispatch_QueryInterface(V_DISPATCH(&v
), &IID_IAccessible
, (void **)&focus_acc
);
1149 hr
= WindowFromAccessibleObject(focus_acc
, &hwnd
);
1150 if (FAILED(hr
) || !hwnd
)
1152 IAccessible_Release(focus_acc
);
1157 hr
= create_msaa_provider(focus_acc
, focus_cid
, hwnd
, FALSE
, FALSE
, &elprov
);
1158 IAccessible_Release(focus_acc
);
1160 *out_prov
= impl_from_msaa_provider(elprov
);
1165 static HRESULT WINAPI
msaa_fragment_root_GetFocus(IRawElementProviderFragmentRoot
*iface
,
1166 IRawElementProviderFragment
**ret_val
)
1168 struct msaa_provider
*msaa_prov
= impl_from_msaa_fragment_root(iface
);
1169 struct msaa_provider
*prov
, *prov2
;
1170 IRawElementProviderSimple
*elprov
;
1173 TRACE("%p, %p\n", iface
, ret_val
);
1176 if (V_I4(&msaa_prov
->cid
) != CHILDID_SELF
)
1179 hr
= create_msaa_provider(msaa_prov
->acc
, CHILDID_SELF
, msaa_prov
->hwnd
, FALSE
, FALSE
, &elprov
);
1183 prov
= impl_from_msaa_provider(elprov
);
1184 while (SUCCEEDED(msaa_acc_get_focus(prov
, &prov2
)))
1186 if (!prov2
|| (msaa_check_acc_state_hres(prov2
->acc
, prov2
->cid
, STATE_SYSTEM_INVISIBLE
) != S_FALSE
) ||
1187 ((V_I4(&prov2
->cid
) == CHILDID_SELF
) && msaa_acc_iface_cmp(prov
->acc
, prov2
->acc
)))
1190 IRawElementProviderSimple_Release(&prov2
->IRawElementProviderSimple_iface
);
1192 if (msaa_acc_iface_cmp(prov
->acc
, msaa_prov
->acc
) && V_I4(&prov
->cid
) == CHILDID_SELF
)
1194 IRawElementProviderSimple_Release(&prov
->IRawElementProviderSimple_iface
);
1200 IRawElementProviderSimple_Release(&prov
->IRawElementProviderSimple_iface
);
1204 hr
= IRawElementProviderSimple_QueryInterface(&prov
->IRawElementProviderSimple_iface
, &IID_IRawElementProviderFragment
, (void **)ret_val
);
1205 IRawElementProviderSimple_Release(&prov
->IRawElementProviderSimple_iface
);
1209 static const IRawElementProviderFragmentRootVtbl msaa_fragment_root_vtbl
= {
1210 msaa_fragment_root_QueryInterface
,
1211 msaa_fragment_root_AddRef
,
1212 msaa_fragment_root_Release
,
1213 msaa_fragment_root_ElementProviderFromPoint
,
1214 msaa_fragment_root_GetFocus
,
1218 * ILegacyIAccessibleProvider interface for UiaProviderFromIAccessible
1221 static inline struct msaa_provider
*impl_from_msaa_acc_provider(ILegacyIAccessibleProvider
*iface
)
1223 return CONTAINING_RECORD(iface
, struct msaa_provider
, ILegacyIAccessibleProvider_iface
);
1226 static HRESULT WINAPI
msaa_acc_provider_QueryInterface(ILegacyIAccessibleProvider
*iface
, REFIID riid
, void **ppv
)
1228 struct msaa_provider
*msaa_prov
= impl_from_msaa_acc_provider(iface
);
1229 return IRawElementProviderSimple_QueryInterface(&msaa_prov
->IRawElementProviderSimple_iface
, riid
, ppv
);
1232 static ULONG WINAPI
msaa_acc_provider_AddRef(ILegacyIAccessibleProvider
*iface
)
1234 struct msaa_provider
*msaa_prov
= impl_from_msaa_acc_provider(iface
);
1235 return IRawElementProviderSimple_AddRef(&msaa_prov
->IRawElementProviderSimple_iface
);
1238 static ULONG WINAPI
msaa_acc_provider_Release(ILegacyIAccessibleProvider
*iface
)
1240 struct msaa_provider
*msaa_prov
= impl_from_msaa_acc_provider(iface
);
1241 return IRawElementProviderSimple_Release(&msaa_prov
->IRawElementProviderSimple_iface
);
1244 static HRESULT WINAPI
msaa_acc_provider_Select(ILegacyIAccessibleProvider
*iface
, LONG select_flags
)
1246 FIXME("%p, %#lx: stub!\n", iface
, select_flags
);
1250 static HRESULT WINAPI
msaa_acc_provider_DoDefaultAction(ILegacyIAccessibleProvider
*iface
)
1252 FIXME("%p: stub!\n", iface
);
1256 static HRESULT WINAPI
msaa_acc_provider_SetValue(ILegacyIAccessibleProvider
*iface
, LPCWSTR val
)
1258 FIXME("%p, %p<%s>: stub!\n", iface
, val
, debugstr_w(val
));
1262 static HRESULT WINAPI
msaa_acc_provider_GetIAccessible(ILegacyIAccessibleProvider
*iface
,
1263 IAccessible
**out_acc
)
1265 struct msaa_provider
*msaa_prov
= impl_from_msaa_acc_provider(iface
);
1267 TRACE("%p, %p\n", iface
, out_acc
);
1270 if (msaa_acc_is_oleacc_proxy(msaa_prov
->acc
))
1273 return IAccessible_QueryInterface(msaa_prov
->acc
, &IID_IAccessible
, (void **)out_acc
);
1276 static HRESULT WINAPI
msaa_acc_provider_get_ChildId(ILegacyIAccessibleProvider
*iface
, int *out_cid
)
1278 struct msaa_provider
*msaa_prov
= impl_from_msaa_acc_provider(iface
);
1280 TRACE("%p, %p\n", iface
, out_cid
);
1281 *out_cid
= V_I4(&msaa_prov
->cid
);
1286 static HRESULT WINAPI
msaa_acc_provider_get_Name(ILegacyIAccessibleProvider
*iface
, BSTR
*out_name
)
1288 FIXME("%p, %p: stub!\n", iface
, out_name
);
1292 static HRESULT WINAPI
msaa_acc_provider_get_Value(ILegacyIAccessibleProvider
*iface
, BSTR
*out_value
)
1294 FIXME("%p, %p: stub!\n", iface
, out_value
);
1298 static HRESULT WINAPI
msaa_acc_provider_get_Description(ILegacyIAccessibleProvider
*iface
,
1299 BSTR
*out_description
)
1301 FIXME("%p, %p: stub!\n", iface
, out_description
);
1305 static HRESULT WINAPI
msaa_acc_provider_get_Role(ILegacyIAccessibleProvider
*iface
, DWORD
*out_role
)
1307 struct msaa_provider
*msaa_prov
= impl_from_msaa_acc_provider(iface
);
1311 TRACE("%p, %p\n", iface
, out_role
);
1315 hr
= IAccessible_get_accRole(msaa_prov
->acc
, msaa_prov
->cid
, &v
);
1316 if (SUCCEEDED(hr
) && V_VT(&v
) == VT_I4
)
1317 *out_role
= V_I4(&v
);
1322 static HRESULT WINAPI
msaa_acc_provider_get_State(ILegacyIAccessibleProvider
*iface
, DWORD
*out_state
)
1324 FIXME("%p, %p: stub!\n", iface
, out_state
);
1328 static HRESULT WINAPI
msaa_acc_provider_get_Help(ILegacyIAccessibleProvider
*iface
, BSTR
*out_help
)
1330 FIXME("%p, %p: stub!\n", iface
, out_help
);
1334 static HRESULT WINAPI
msaa_acc_provider_get_KeyboardShortcut(ILegacyIAccessibleProvider
*iface
,
1335 BSTR
*out_kbd_shortcut
)
1337 FIXME("%p, %p: stub!\n", iface
, out_kbd_shortcut
);
1341 static HRESULT WINAPI
msaa_acc_provider_GetSelection(ILegacyIAccessibleProvider
*iface
,
1342 SAFEARRAY
**out_selected
)
1344 FIXME("%p, %p: stub!\n", iface
, out_selected
);
1348 static HRESULT WINAPI
msaa_acc_provider_get_DefaultAction(ILegacyIAccessibleProvider
*iface
,
1349 BSTR
*out_default_action
)
1351 FIXME("%p, %p: stub!\n", iface
, out_default_action
);
1355 static const ILegacyIAccessibleProviderVtbl msaa_acc_provider_vtbl
= {
1356 msaa_acc_provider_QueryInterface
,
1357 msaa_acc_provider_AddRef
,
1358 msaa_acc_provider_Release
,
1359 msaa_acc_provider_Select
,
1360 msaa_acc_provider_DoDefaultAction
,
1361 msaa_acc_provider_SetValue
,
1362 msaa_acc_provider_GetIAccessible
,
1363 msaa_acc_provider_get_ChildId
,
1364 msaa_acc_provider_get_Name
,
1365 msaa_acc_provider_get_Value
,
1366 msaa_acc_provider_get_Description
,
1367 msaa_acc_provider_get_Role
,
1368 msaa_acc_provider_get_State
,
1369 msaa_acc_provider_get_Help
,
1370 msaa_acc_provider_get_KeyboardShortcut
,
1371 msaa_acc_provider_GetSelection
,
1372 msaa_acc_provider_get_DefaultAction
,
1376 * IProxyProviderWinEventHandler interface for UiaProviderFromIAccessible
1379 static inline struct msaa_provider
*impl_from_msaa_winevent_handler(IProxyProviderWinEventHandler
*iface
)
1381 return CONTAINING_RECORD(iface
, struct msaa_provider
, IProxyProviderWinEventHandler_iface
);
1384 static HRESULT WINAPI
msaa_winevent_handler_QueryInterface(IProxyProviderWinEventHandler
*iface
, REFIID riid
,
1387 struct msaa_provider
*msaa_prov
= impl_from_msaa_winevent_handler(iface
);
1388 return IRawElementProviderSimple_QueryInterface(&msaa_prov
->IRawElementProviderSimple_iface
, riid
, ppv
);
1391 static ULONG WINAPI
msaa_winevent_handler_AddRef(IProxyProviderWinEventHandler
*iface
)
1393 struct msaa_provider
*msaa_prov
= impl_from_msaa_winevent_handler(iface
);
1394 return IRawElementProviderSimple_AddRef(&msaa_prov
->IRawElementProviderSimple_iface
);
1397 static ULONG WINAPI
msaa_winevent_handler_Release(IProxyProviderWinEventHandler
*iface
)
1399 struct msaa_provider
*msaa_prov
= impl_from_msaa_winevent_handler(iface
);
1400 return IRawElementProviderSimple_Release(&msaa_prov
->IRawElementProviderSimple_iface
);
1403 static HRESULT WINAPI
msaa_winevent_handler_RespondToWinEvent(IProxyProviderWinEventHandler
*iface
, DWORD event_id
,
1404 HWND hwnd
, LONG objid
, LONG cid
, IProxyProviderWinEventSink
*event_sink
)
1406 struct msaa_provider
*msaa_prov
= impl_from_msaa_winevent_handler(iface
);
1409 TRACE("%p, %ld, %p, %ld, %ld, %p\n", iface
, event_id
, hwnd
, objid
, cid
, event_sink
);
1413 case EVENT_SYSTEM_ALERT
:
1414 hr
= IProxyProviderWinEventSink_AddAutomationEvent(event_sink
, &msaa_prov
->IRawElementProviderSimple_iface
,
1415 UIA_SystemAlertEventId
);
1417 WARN("AddAutomationEvent failed with hr %#lx\n", hr
);
1420 case EVENT_OBJECT_REORDER
:
1421 case EVENT_OBJECT_SELECTION
:
1422 case EVENT_OBJECT_NAMECHANGE
:
1423 case EVENT_OBJECT_VALUECHANGE
:
1424 case EVENT_OBJECT_HELPCHANGE
:
1425 case EVENT_OBJECT_INVOKED
:
1426 FIXME("WinEvent %ld currently unimplemented\n", event_id
);
1436 static const IProxyProviderWinEventHandlerVtbl msaa_winevent_handler_vtbl
= {
1437 msaa_winevent_handler_QueryInterface
,
1438 msaa_winevent_handler_AddRef
,
1439 msaa_winevent_handler_Release
,
1440 msaa_winevent_handler_RespondToWinEvent
,
1443 HRESULT
create_msaa_provider(IAccessible
*acc
, LONG child_id
, HWND hwnd
, BOOL root_acc_known
,
1444 BOOL is_root_acc
, IRawElementProviderSimple
**elprov
)
1446 struct msaa_provider
*msaa_prov
= calloc(1, sizeof(*msaa_prov
));
1449 return E_OUTOFMEMORY
;
1451 msaa_prov
->IRawElementProviderSimple_iface
.lpVtbl
= &msaa_provider_vtbl
;
1452 msaa_prov
->IRawElementProviderFragment_iface
.lpVtbl
= &msaa_fragment_vtbl
;
1453 msaa_prov
->IRawElementProviderFragmentRoot_iface
.lpVtbl
= &msaa_fragment_root_vtbl
;
1454 msaa_prov
->ILegacyIAccessibleProvider_iface
.lpVtbl
= &msaa_acc_provider_vtbl
;
1455 msaa_prov
->IProxyProviderWinEventHandler_iface
.lpVtbl
= &msaa_winevent_handler_vtbl
;
1456 msaa_prov
->refcount
= 1;
1457 variant_init_i4(&msaa_prov
->cid
, child_id
);
1458 msaa_prov
->acc
= acc
;
1459 IAccessible_AddRef(acc
);
1460 msaa_prov
->ia2
= msaa_acc_get_ia2(acc
);
1466 hr
= WindowFromAccessibleObject(acc
, &msaa_prov
->hwnd
);
1468 WARN("WindowFromAccessibleObject failed with hr %#lx\n", hr
);
1471 msaa_prov
->hwnd
= hwnd
;
1475 msaa_prov
->root_acc_check_ran
= TRUE
;
1476 msaa_prov
->is_root_acc
= is_root_acc
;
1479 *elprov
= &msaa_prov
->IRawElementProviderSimple_iface
;
1484 /***********************************************************************
1485 * UiaProviderFromIAccessible (uiautomationcore.@)
1487 HRESULT WINAPI
UiaProviderFromIAccessible(IAccessible
*acc
, LONG child_id
, DWORD flags
,
1488 IRawElementProviderSimple
**elprov
)
1493 TRACE("(%p, %ld, %#lx, %p)\n", acc
, child_id
, flags
, elprov
);
1501 return E_INVALIDARG
;
1503 if (flags
!= UIA_PFIA_DEFAULT
)
1505 FIXME("unsupported flags %#lx\n", flags
);
1509 if (msaa_acc_is_oleacc_proxy(acc
))
1511 WARN("Cannot wrap an oleacc proxy IAccessible!\n");
1512 return E_INVALIDARG
;
1515 hr
= WindowFromAccessibleObject(acc
, &hwnd
);
1521 return create_msaa_provider(acc
, child_id
, hwnd
, FALSE
, FALSE
, elprov
);
1524 static HRESULT
uia_get_hr_for_last_error(void)
1526 DWORD last_err
= GetLastError();
1530 case ERROR_INVALID_WINDOW_HANDLE
:
1531 return UIA_E_ELEMENTNOTAVAILABLE
;
1534 return UIA_E_TIMEOUT
;
1541 #define UIA_DEFAULT_MSG_TIMEOUT 10000
1542 static HRESULT
uia_send_message_timeout(HWND hwnd
, UINT msg
, WPARAM wparam
, LPARAM lparam
, UINT timeout
, LRESULT
*lres
)
1545 if (!SendMessageTimeoutW(hwnd
, msg
, wparam
, lparam
, SMTO_NORMAL
, timeout
, (PDWORD_PTR
)lres
))
1546 return uia_get_hr_for_last_error();
1551 static HRESULT
get_uia_control_type_for_hwnd(HWND hwnd
, int *control_type
)
1553 LONG_PTR style
, ex_style
;
1556 if ((ex_style
= GetWindowLongPtrW(hwnd
, GWL_EXSTYLE
)) & WS_EX_APPWINDOW
)
1558 *control_type
= UIA_WindowControlTypeId
;
1562 SetLastError(NO_ERROR
);
1563 if (!(style
= GetWindowLongPtrW(hwnd
, GWL_STYLE
)) && (GetLastError() != NO_ERROR
))
1564 return uia_get_hr_for_last_error();
1567 * Non-caption HWNDs that are popups or tool windows aren't considered full
1568 * windows, only panes.
1570 if (((style
& WS_CAPTION
) != WS_CAPTION
) && ((ex_style
& WS_EX_TOOLWINDOW
) || (style
& WS_POPUP
)))
1572 *control_type
= UIA_PaneControlTypeId
;
1576 /* Non top-level HWNDs are considered panes as well. */
1577 if (!uia_is_top_level_hwnd(hwnd
))
1578 *control_type
= UIA_PaneControlTypeId
;
1580 *control_type
= UIA_WindowControlTypeId
;
1586 * Default ProviderType_BaseHwnd IRawElementProviderSimple interface.
1588 struct base_hwnd_provider
{
1589 IRawElementProviderSimple IRawElementProviderSimple_iface
;
1590 IRawElementProviderFragment IRawElementProviderFragment_iface
;
1596 static inline struct base_hwnd_provider
*impl_from_base_hwnd_provider(IRawElementProviderSimple
*iface
)
1598 return CONTAINING_RECORD(iface
, struct base_hwnd_provider
, IRawElementProviderSimple_iface
);
1601 static HRESULT WINAPI
base_hwnd_provider_QueryInterface(IRawElementProviderSimple
*iface
, REFIID riid
, void **ppv
)
1603 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_provider(iface
);
1606 if (IsEqualIID(riid
, &IID_IRawElementProviderSimple
) || IsEqualIID(riid
, &IID_IUnknown
))
1608 else if (IsEqualIID(riid
, &IID_IRawElementProviderFragment
))
1609 *ppv
= &base_hwnd_prov
->IRawElementProviderFragment_iface
;
1611 return E_NOINTERFACE
;
1613 IRawElementProviderSimple_AddRef(iface
);
1617 static ULONG WINAPI
base_hwnd_provider_AddRef(IRawElementProviderSimple
*iface
)
1619 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_provider(iface
);
1620 ULONG refcount
= InterlockedIncrement(&base_hwnd_prov
->refcount
);
1622 TRACE("%p, refcount %ld\n", iface
, refcount
);
1627 static ULONG WINAPI
base_hwnd_provider_Release(IRawElementProviderSimple
*iface
)
1629 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_provider(iface
);
1630 ULONG refcount
= InterlockedDecrement(&base_hwnd_prov
->refcount
);
1632 TRACE("%p, refcount %ld\n", iface
, refcount
);
1635 free(base_hwnd_prov
);
1640 static HRESULT WINAPI
base_hwnd_provider_get_ProviderOptions(IRawElementProviderSimple
*iface
,
1641 enum ProviderOptions
*ret_val
)
1643 TRACE("%p, %p\n", iface
, ret_val
);
1644 *ret_val
= ProviderOptions_ClientSideProvider
;
1648 static HRESULT WINAPI
base_hwnd_provider_GetPatternProvider(IRawElementProviderSimple
*iface
,
1649 PATTERNID pattern_id
, IUnknown
**ret_val
)
1651 FIXME("%p, %d, %p: stub\n", iface
, pattern_id
, ret_val
);
1656 static HRESULT WINAPI
base_hwnd_provider_GetPropertyValue(IRawElementProviderSimple
*iface
,
1657 PROPERTYID prop_id
, VARIANT
*ret_val
)
1659 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_provider(iface
);
1662 TRACE("%p, %d, %p\n", iface
, prop_id
, ret_val
);
1664 VariantInit(ret_val
);
1665 if (!IsWindow(base_hwnd_prov
->hwnd
))
1666 return UIA_E_ELEMENTNOTAVAILABLE
;
1670 case UIA_ProviderDescriptionPropertyId
:
1671 V_VT(ret_val
) = VT_BSTR
;
1672 V_BSTR(ret_val
) = SysAllocString(L
"Wine: HWND Proxy");
1675 case UIA_NativeWindowHandlePropertyId
:
1676 V_VT(ret_val
) = VT_I4
;
1677 V_I4(ret_val
) = HandleToUlong(base_hwnd_prov
->hwnd
);
1680 case UIA_ProcessIdPropertyId
:
1684 if (!GetWindowThreadProcessId(base_hwnd_prov
->hwnd
, &pid
))
1685 return UIA_E_ELEMENTNOTAVAILABLE
;
1687 V_VT(ret_val
) = VT_I4
;
1688 V_I4(ret_val
) = pid
;
1692 case UIA_ClassNamePropertyId
:
1694 WCHAR buf
[256] = { 0 };
1696 if (!GetClassNameW(base_hwnd_prov
->hwnd
, buf
, ARRAY_SIZE(buf
)))
1697 hr
= uia_get_hr_for_last_error();
1700 V_VT(ret_val
) = VT_BSTR
;
1701 V_BSTR(ret_val
) = SysAllocString(buf
);
1706 case UIA_NamePropertyId
:
1710 V_VT(ret_val
) = VT_BSTR
;
1711 V_BSTR(ret_val
) = SysAllocString(L
"");
1712 hr
= uia_send_message_timeout(base_hwnd_prov
->hwnd
, WM_GETTEXTLENGTH
, 0, 0, UIA_DEFAULT_MSG_TIMEOUT
, &lres
);
1713 if (FAILED(hr
) || !lres
)
1716 if (!SysReAllocStringLen(&V_BSTR(ret_val
), NULL
, lres
))
1722 hr
= uia_send_message_timeout(base_hwnd_prov
->hwnd
, WM_GETTEXT
, SysStringLen(V_BSTR(ret_val
)) + 1,
1723 (LPARAM
)V_BSTR(ret_val
), UIA_DEFAULT_MSG_TIMEOUT
, &lres
);
1727 case UIA_ControlTypePropertyId
:
1731 hr
= get_uia_control_type_for_hwnd(base_hwnd_prov
->hwnd
, &control_type
);
1734 V_VT(ret_val
) = VT_I4
;
1735 V_I4(ret_val
) = control_type
;
1745 VariantClear(ret_val
);
1750 static HRESULT WINAPI
base_hwnd_provider_get_HostRawElementProvider(IRawElementProviderSimple
*iface
,
1751 IRawElementProviderSimple
**ret_val
)
1753 TRACE("%p, %p\n", iface
, ret_val
);
1758 static const IRawElementProviderSimpleVtbl base_hwnd_provider_vtbl
= {
1759 base_hwnd_provider_QueryInterface
,
1760 base_hwnd_provider_AddRef
,
1761 base_hwnd_provider_Release
,
1762 base_hwnd_provider_get_ProviderOptions
,
1763 base_hwnd_provider_GetPatternProvider
,
1764 base_hwnd_provider_GetPropertyValue
,
1765 base_hwnd_provider_get_HostRawElementProvider
,
1769 * IRawElementProviderFragment interface for default ProviderType_BaseHwnd
1772 static inline struct base_hwnd_provider
*impl_from_base_hwnd_fragment(IRawElementProviderFragment
*iface
)
1774 return CONTAINING_RECORD(iface
, struct base_hwnd_provider
, IRawElementProviderFragment_iface
);
1777 static HRESULT WINAPI
base_hwnd_fragment_QueryInterface(IRawElementProviderFragment
*iface
, REFIID riid
,
1780 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_fragment(iface
);
1781 return IRawElementProviderSimple_QueryInterface(&base_hwnd_prov
->IRawElementProviderSimple_iface
, riid
, ppv
);
1784 static ULONG WINAPI
base_hwnd_fragment_AddRef(IRawElementProviderFragment
*iface
)
1786 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_fragment(iface
);
1787 return IRawElementProviderSimple_AddRef(&base_hwnd_prov
->IRawElementProviderSimple_iface
);
1790 static ULONG WINAPI
base_hwnd_fragment_Release(IRawElementProviderFragment
*iface
)
1792 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_fragment(iface
);
1793 return IRawElementProviderSimple_Release(&base_hwnd_prov
->IRawElementProviderSimple_iface
);
1796 static HRESULT WINAPI
base_hwnd_fragment_Navigate(IRawElementProviderFragment
*iface
,
1797 enum NavigateDirection direction
, IRawElementProviderFragment
**ret_val
)
1799 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_fragment(iface
);
1800 IRawElementProviderSimple
*elprov
= NULL
;
1803 TRACE("%p, %d, %p\n", iface
, direction
, ret_val
);
1809 case NavigateDirection_Parent
:
1814 * Top level owned windows have their owner window as a parent instead
1815 * of the desktop window.
1817 if (uia_is_top_level_hwnd(base_hwnd_prov
->hwnd
) && (owner
= GetWindow(base_hwnd_prov
->hwnd
, GW_OWNER
)))
1820 parent
= GetAncestor(base_hwnd_prov
->hwnd
, GA_PARENT
);
1823 hr
= create_base_hwnd_provider(parent
, &elprov
);
1827 case NavigateDirection_FirstChild
:
1828 case NavigateDirection_LastChild
:
1829 case NavigateDirection_PreviousSibling
:
1830 case NavigateDirection_NextSibling
:
1831 FIXME("Unimplemented NavigateDirection %d\n", direction
);
1835 FIXME("Invalid NavigateDirection %d\n", direction
);
1836 return E_INVALIDARG
;
1841 hr
= IRawElementProviderSimple_QueryInterface(elprov
, &IID_IRawElementProviderFragment
, (void **)ret_val
);
1842 IRawElementProviderSimple_Release(elprov
);
1848 static HRESULT WINAPI
base_hwnd_fragment_GetRuntimeId(IRawElementProviderFragment
*iface
,
1849 SAFEARRAY
**ret_val
)
1851 FIXME("%p, %p: stub!\n", iface
, ret_val
);
1856 static HRESULT WINAPI
base_hwnd_fragment_get_BoundingRectangle(IRawElementProviderFragment
*iface
,
1857 struct UiaRect
*ret_val
)
1859 struct base_hwnd_provider
*base_hwnd_prov
= impl_from_base_hwnd_fragment(iface
);
1862 TRACE("%p, %p\n", iface
, ret_val
);
1864 memset(ret_val
, 0, sizeof(*ret_val
));
1866 /* Top level minimized window - Return empty rect. */
1867 if (uia_is_top_level_hwnd(base_hwnd_prov
->hwnd
) && IsIconic(base_hwnd_prov
->hwnd
))
1870 if (!GetWindowRect(base_hwnd_prov
->hwnd
, &rect
))
1871 return uia_get_hr_for_last_error();
1873 ret_val
->left
= rect
.left
;
1874 ret_val
->top
= rect
.top
;
1875 ret_val
->width
= (rect
.right
- rect
.left
);
1876 ret_val
->height
= (rect
.bottom
- rect
.top
);
1881 static HRESULT WINAPI
base_hwnd_fragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment
*iface
,
1882 SAFEARRAY
**ret_val
)
1884 FIXME("%p, %p: stub!\n", iface
, ret_val
);
1889 static HRESULT WINAPI
base_hwnd_fragment_SetFocus(IRawElementProviderFragment
*iface
)
1891 FIXME("%p: stub!\n", iface
);
1895 static HRESULT WINAPI
base_hwnd_fragment_get_FragmentRoot(IRawElementProviderFragment
*iface
,
1896 IRawElementProviderFragmentRoot
**ret_val
)
1898 FIXME("%p, %p: stub!\n", iface
, ret_val
);
1903 static const IRawElementProviderFragmentVtbl base_hwnd_fragment_vtbl
= {
1904 base_hwnd_fragment_QueryInterface
,
1905 base_hwnd_fragment_AddRef
,
1906 base_hwnd_fragment_Release
,
1907 base_hwnd_fragment_Navigate
,
1908 base_hwnd_fragment_GetRuntimeId
,
1909 base_hwnd_fragment_get_BoundingRectangle
,
1910 base_hwnd_fragment_GetEmbeddedFragmentRoots
,
1911 base_hwnd_fragment_SetFocus
,
1912 base_hwnd_fragment_get_FragmentRoot
,
1915 HRESULT
create_base_hwnd_provider(HWND hwnd
, IRawElementProviderSimple
**elprov
)
1917 struct base_hwnd_provider
*base_hwnd_prov
;
1922 return E_INVALIDARG
;
1924 if (!IsWindow(hwnd
))
1925 return UIA_E_ELEMENTNOTAVAILABLE
;
1927 if (!(base_hwnd_prov
= calloc(1, sizeof(*base_hwnd_prov
))))
1928 return E_OUTOFMEMORY
;
1930 base_hwnd_prov
->IRawElementProviderSimple_iface
.lpVtbl
= &base_hwnd_provider_vtbl
;
1931 base_hwnd_prov
->IRawElementProviderFragment_iface
.lpVtbl
= &base_hwnd_fragment_vtbl
;
1932 base_hwnd_prov
->refcount
= 1;
1933 base_hwnd_prov
->hwnd
= hwnd
;
1934 *elprov
= &base_hwnd_prov
->IRawElementProviderSimple_iface
;
1940 * UI Automation provider thread functions.
1942 struct uia_provider_thread
1944 struct rb_tree node_map
;
1945 struct list nodes_list
;
1951 static struct uia_provider_thread provider_thread
;
1952 static CRITICAL_SECTION provider_thread_cs
;
1953 static CRITICAL_SECTION_DEBUG provider_thread_cs_debug
=
1955 0, 0, &provider_thread_cs
,
1956 { &provider_thread_cs_debug
.ProcessLocksList
, &provider_thread_cs_debug
.ProcessLocksList
},
1957 0, 0, { (DWORD_PTR
)(__FILE__
": provider_thread_cs") }
1959 static CRITICAL_SECTION provider_thread_cs
= { &provider_thread_cs_debug
, -1, 0, 0, 0, 0 };
1961 struct uia_provider_thread_map_entry
1963 struct rb_entry entry
;
1965 SAFEARRAY
*runtime_id
;
1966 struct list nodes_list
;
1969 static int uia_runtime_id_compare(const void *key
, const struct rb_entry
*entry
)
1971 struct uia_provider_thread_map_entry
*prov_entry
= RB_ENTRY_VALUE(entry
, struct uia_provider_thread_map_entry
, entry
);
1972 return uia_compare_safearrays(prov_entry
->runtime_id
, (SAFEARRAY
*)key
, UIAutomationType_IntArray
);
1975 void uia_provider_thread_remove_node(HUIANODE node
)
1977 struct uia_node
*node_data
= impl_from_IWineUiaNode((IWineUiaNode
*)node
);
1979 TRACE("Removing node %p\n", node
);
1981 EnterCriticalSection(&provider_thread_cs
);
1983 list_remove(&node_data
->prov_thread_list_entry
);
1984 list_init(&node_data
->prov_thread_list_entry
);
1985 if (!list_empty(&node_data
->node_map_list_entry
))
1987 list_remove(&node_data
->node_map_list_entry
);
1988 list_init(&node_data
->node_map_list_entry
);
1989 if (list_empty(&node_data
->map
->nodes_list
))
1991 rb_remove(&provider_thread
.node_map
, &node_data
->map
->entry
);
1992 SafeArrayDestroy(node_data
->map
->runtime_id
);
1993 free(node_data
->map
);
1995 node_data
->map
= NULL
;
1998 LeaveCriticalSection(&provider_thread_cs
);
2001 static void uia_provider_thread_disconnect_node(SAFEARRAY
*sa
)
2003 struct rb_entry
*rb_entry
;
2005 EnterCriticalSection(&provider_thread_cs
);
2007 /* Provider thread hasn't been started, no nodes to disconnect. */
2008 if (!provider_thread
.ref
)
2011 rb_entry
= rb_get(&provider_thread
.node_map
, sa
);
2014 struct uia_provider_thread_map_entry
*prov_map
;
2015 struct list
*cursor
, *cursor2
;
2016 struct uia_node
*node_data
;
2018 prov_map
= RB_ENTRY_VALUE(rb_entry
, struct uia_provider_thread_map_entry
, entry
);
2019 LIST_FOR_EACH_SAFE(cursor
, cursor2
, &prov_map
->nodes_list
)
2021 node_data
= LIST_ENTRY(cursor
, struct uia_node
, node_map_list_entry
);
2023 list_remove(cursor
);
2024 list_remove(&node_data
->prov_thread_list_entry
);
2025 list_init(&node_data
->prov_thread_list_entry
);
2026 list_init(&node_data
->node_map_list_entry
);
2027 node_data
->map
= NULL
;
2029 IWineUiaNode_disconnect(&node_data
->IWineUiaNode_iface
);
2032 rb_remove(&provider_thread
.node_map
, &prov_map
->entry
);
2033 SafeArrayDestroy(prov_map
->runtime_id
);
2038 LeaveCriticalSection(&provider_thread_cs
);
2041 static HRESULT
uia_provider_thread_add_node(HUIANODE node
, SAFEARRAY
*rt_id
)
2043 struct uia_node
*node_data
= impl_from_IWineUiaNode((IWineUiaNode
*)node
);
2044 int prov_type
= get_node_provider_type_at_idx(node_data
, 0);
2045 struct uia_provider
*prov_data
;
2048 prov_data
= impl_from_IWineUiaProvider(node_data
->prov
[prov_type
]);
2049 node_data
->nested_node
= prov_data
->return_nested_node
= prov_data
->refuse_hwnd_node_providers
= TRUE
;
2051 TRACE("Adding node %p\n", node
);
2053 EnterCriticalSection(&provider_thread_cs
);
2054 list_add_tail(&provider_thread
.nodes_list
, &node_data
->prov_thread_list_entry
);
2056 /* If we have a runtime ID, create an entry in the rb tree. */
2059 struct uia_provider_thread_map_entry
*prov_map
;
2060 struct rb_entry
*rb_entry
;
2062 if ((rb_entry
= rb_get(&provider_thread
.node_map
, rt_id
)))
2063 prov_map
= RB_ENTRY_VALUE(rb_entry
, struct uia_provider_thread_map_entry
, entry
);
2066 prov_map
= calloc(1, sizeof(*prov_map
));
2073 hr
= SafeArrayCopy(rt_id
, &prov_map
->runtime_id
);
2079 list_init(&prov_map
->nodes_list
);
2080 rb_put(&provider_thread
.node_map
, prov_map
->runtime_id
, &prov_map
->entry
);
2083 list_add_tail(&prov_map
->nodes_list
, &node_data
->node_map_list_entry
);
2084 node_data
->map
= prov_map
;
2088 LeaveCriticalSection(&provider_thread_cs
);
2093 #define WM_GET_OBJECT_UIA_NODE (WM_USER + 1)
2094 #define WM_UIA_PROVIDER_THREAD_STOP (WM_USER + 2)
2095 static LRESULT CALLBACK
uia_provider_thread_msg_proc(HWND hwnd
, UINT msg
, WPARAM wparam
,
2100 case WM_GET_OBJECT_UIA_NODE
:
2102 SAFEARRAY
*rt_id
= (SAFEARRAY
*)wparam
;
2103 HUIANODE node
= (HUIANODE
)lparam
;
2106 if (FAILED(uia_provider_thread_add_node(node
, rt_id
)))
2108 WARN("Failed to add node %p to provider thread list.\n", node
);
2113 * LresultFromObject returns an index into the global atom string table,
2114 * which has a valid range of 0xc000-0xffff.
2116 lr
= LresultFromObject(&IID_IWineUiaNode
, 0, (IUnknown
*)node
);
2117 if ((lr
> 0xffff) || (lr
< 0xc000))
2119 WARN("Got invalid lresult %Ix\n", lr
);
2130 return DefWindowProcW(hwnd
, msg
, wparam
, lparam
);
2133 static DWORD WINAPI
uia_provider_thread_proc(void *arg
)
2135 HANDLE initialized_event
= arg
;
2139 CoInitializeEx(NULL
, COINIT_MULTITHREADED
);
2140 hwnd
= CreateWindowW(L
"Message", NULL
, 0, 0, 0, 0, 0, HWND_MESSAGE
, NULL
, NULL
, NULL
);
2143 WARN("CreateWindow failed: %ld\n", GetLastError());
2145 FreeLibraryAndExitThread(huia_module
, 1);
2148 SetWindowLongPtrW(hwnd
, GWLP_WNDPROC
, (LONG_PTR
)uia_provider_thread_msg_proc
);
2149 provider_thread
.hwnd
= hwnd
;
2151 /* Initialization complete, thread can now process window messages. */
2152 SetEvent(initialized_event
);
2153 TRACE("Provider thread started.\n");
2154 while (GetMessageW(&msg
, NULL
, 0, 0))
2156 if (msg
.message
== WM_UIA_PROVIDER_THREAD_STOP
)
2158 TranslateMessage(&msg
);
2159 DispatchMessageW(&msg
);
2162 TRACE("Shutting down UI Automation provider thread.\n");
2164 DestroyWindow(hwnd
);
2166 FreeLibraryAndExitThread(huia_module
, 0);
2169 static BOOL
uia_start_provider_thread(void)
2171 BOOL started
= TRUE
;
2173 EnterCriticalSection(&provider_thread_cs
);
2174 if (++provider_thread
.ref
== 1)
2181 /* Increment DLL reference count. */
2182 GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS
,
2183 (const WCHAR
*)uia_start_provider_thread
, &hmodule
);
2185 list_init(&provider_thread
.nodes_list
);
2186 rb_init(&provider_thread
.node_map
, uia_runtime_id_compare
);
2187 events
[0] = ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
2188 if (!(provider_thread
.hthread
= CreateThread(NULL
, 0, uia_provider_thread_proc
,
2189 ready_event
, 0, NULL
)))
2191 FreeLibrary(hmodule
);
2196 events
[1] = provider_thread
.hthread
;
2197 wait_obj
= WaitForMultipleObjects(2, events
, FALSE
, INFINITE
);
2198 if (wait_obj
!= WAIT_OBJECT_0
)
2200 CloseHandle(provider_thread
.hthread
);
2205 CloseHandle(ready_event
);
2208 WARN("Failed to start provider thread\n");
2209 memset(&provider_thread
, 0, sizeof(provider_thread
));
2213 LeaveCriticalSection(&provider_thread_cs
);
2217 void uia_stop_provider_thread(void)
2219 EnterCriticalSection(&provider_thread_cs
);
2220 if (!--provider_thread
.ref
)
2222 PostMessageW(provider_thread
.hwnd
, WM_UIA_PROVIDER_THREAD_STOP
, 0, 0);
2223 CloseHandle(provider_thread
.hthread
);
2224 if (!list_empty(&provider_thread
.nodes_list
))
2225 ERR("Provider thread shutdown with nodes still in the list\n");
2226 memset(&provider_thread
, 0, sizeof(provider_thread
));
2228 LeaveCriticalSection(&provider_thread_cs
);
2232 * Pass our IWineUiaNode interface to the provider thread for marshaling. UI
2233 * Automation has to work regardless of whether or not COM is initialized on
2234 * the thread calling UiaReturnRawElementProvider.
2236 LRESULT
uia_lresult_from_node(HUIANODE huianode
)
2242 hr
= UiaGetRuntimeId(huianode
, &rt_id
);
2243 if (SUCCEEDED(hr
) && uia_start_provider_thread())
2244 lr
= SendMessageW(provider_thread
.hwnd
, WM_GET_OBJECT_UIA_NODE
, (WPARAM
)rt_id
, (LPARAM
)huianode
);
2247 WARN("UiaGetRuntimeId failed with hr %#lx\n", hr
);
2250 * LresultFromObject increases refcnt by 1. If LresultFromObject
2251 * failed or wasn't called, this is expected to release the node.
2253 UiaNodeRelease(huianode
);
2254 SafeArrayDestroy(rt_id
);
2258 /***********************************************************************
2259 * UiaReturnRawElementProvider (uiautomationcore.@)
2261 LRESULT WINAPI
UiaReturnRawElementProvider(HWND hwnd
, WPARAM wparam
,
2262 LPARAM lparam
, IRawElementProviderSimple
*elprov
)
2267 TRACE("(%p, %Ix, %#Ix, %p)\n", hwnd
, wparam
, lparam
, elprov
);
2269 if (!wparam
&& !lparam
&& !elprov
)
2271 FIXME("UIA-to-MSAA bridge not implemented, no provider map to free.\n");
2275 if (lparam
!= UiaRootObjectId
)
2277 FIXME("Unsupported object id %Id, ignoring.\n", lparam
);
2281 hr
= create_uia_node_from_elprov(elprov
, &node
, FALSE
, 0);
2284 WARN("Failed to create HUIANODE with hr %#lx\n", hr
);
2288 return uia_lresult_from_node(node
);
2291 /***********************************************************************
2292 * UiaDisconnectProvider (uiautomationcore.@)
2294 HRESULT WINAPI
UiaDisconnectProvider(IRawElementProviderSimple
*elprov
)
2300 TRACE("(%p)\n", elprov
);
2302 hr
= create_uia_node_from_elprov(elprov
, &node
, FALSE
, 0);
2306 hr
= UiaGetRuntimeId(node
, &sa
);
2307 UiaNodeRelease(node
);
2312 return E_INVALIDARG
;
2314 uia_provider_thread_disconnect_node(sa
);
2316 SafeArrayDestroy(sa
);