Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
a19c1ff1
Commit
a19c1ff1
authored
Mar 23, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
Apr 17, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Add a default ProviderType_Proxy MSAA bridge clientside provider.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
2a089f52
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
160 additions
and
28 deletions
+160
-28
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+105
-7
uia_client.c
dlls/uiautomationcore/uia_client.c
+13
-1
uia_private.h
dlls/uiautomationcore/uia_private.h
+2
-0
uia_provider.c
dlls/uiautomationcore/uia_provider.c
+40
-20
No files found.
dlls/uiautomationcore/tests/uiautomation.c
View file @
a19c1ff1
...
...
@@ -90,6 +90,7 @@ DEFINE_EXPECT(Accessible2_get_accName);
DEFINE_EXPECT
(
Accessible2_get_accRole
);
DEFINE_EXPECT
(
Accessible2_get_accState
);
DEFINE_EXPECT
(
Accessible2_accLocation
);
DEFINE_EXPECT
(
Accessible_QI_IAccIdentity
);
DEFINE_EXPECT
(
Accessible2_QI_IAccIdentity
);
DEFINE_EXPECT
(
Accessible2_get_uniqueID
);
DEFINE_EXPECT
(
Accessible_child_accNavigate
);
...
...
@@ -177,7 +178,10 @@ static HRESULT WINAPI Accessible_QueryInterface(IAccessible *iface, REFIID riid,
{
if
(
This
==
&
Accessible2
)
CHECK_EXPECT
(
Accessible2_QI_IAccIdentity
);
ok
(
This
==
&
Accessible2
,
"unexpected call
\n
"
);
else
if
(
This
==
&
Accessible
)
CHECK_EXPECT
(
Accessible_QI_IAccIdentity
);
ok
(
This
==
&
Accessible2
||
This
==
&
Accessible
,
"unexpected call
\n
"
);
return
E_NOINTERFACE
;
}
...
...
@@ -6738,10 +6742,17 @@ static void test_UiaNodeFromHandle(const char *name)
/* Only sent twice on Win7. */
SET_EXPECT_MULTI
(
winproc_GETOBJECT_CLIENT
,
2
);
hr
=
UiaNodeFromHandle
(
hwnd
,
&
node
);
/* Windows 10 and below return E_FAIL, Windows 11 returns S_OK. */
ok
(
hr
==
S_OK
||
broken
(
hr
==
E_FAIL
),
"Unexpected hr %#lx.
\n
"
,
hr
);
/*
* On all versions of Windows prior to Windows 11, this would fail due to
* COM being uninitialized, presumably because it tries to get an MSAA
* proxy. Windows 11 now has the thread end up in an implicit MTA after
* the call to UiaNodeFromHandle, which is probably why this now succeeds.
* I don't know of anything that relies on this behavior, so for now we
* won't match it.
*/
todo_wine
ok
(
hr
==
S_OK
||
broken
(
hr
==
E_FAIL
),
"Unexpected hr %#lx.
\n
"
,
hr
);
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
todo_wine
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
if
(
SUCCEEDED
(
hr
))
UiaNodeRelease
(
node
);
...
...
@@ -6757,7 +6768,7 @@ static void test_UiaNodeFromHandle(const char *name)
hr
=
UiaNodeFromHandle
(
hwnd
,
&
node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
todo_wine
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ProviderDescriptionPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
...
...
@@ -6783,7 +6794,7 @@ static void test_UiaNodeFromHandle(const char *name)
hr
=
UiaNodeFromHandle
(
hwnd
,
&
node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
todo_wine
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ProviderDescriptionPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
...
...
@@ -6818,7 +6829,7 @@ static void test_UiaNodeFromHandle(const char *name)
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
Provider
.
ref
==
1
||
broken
(
Provider
.
ref
==
2
),
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
todo_wine
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ProviderDescriptionPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
...
...
@@ -12684,6 +12695,93 @@ static void test_default_clientside_providers(void)
UiaNodeRelease
(
node
);
prov_root
=
NULL
;
/*
* Test default ProviderType_Proxy clientside provider. Provider will be
* the HWND provider for this node, and Accessible will be the main
* provider.
*/
initialize_provider
(
&
Provider
,
ProviderOptions_ClientSideProvider
,
hwnd
,
FALSE
);
set_accessible_props
(
&
Accessible
,
ROLE_SYSTEM_TEXT
,
STATE_SYSTEM_FOCUSABLE
,
0
,
L"Accessible"
,
0
,
0
,
20
,
20
);
set_accessible_ia2_props
(
&
Accessible
,
FALSE
,
0
);
acc_client
=
&
Accessible
.
IAccessible_iface
;
prov_root
=
child_win_prov_root
=
NULL
;
SET_EXPECT
(
Accessible_QI_IAccIdentity
);
SET_EXPECT
(
Accessible_get_accParent
);
SET_EXPECT
(
winproc_GETOBJECT_UiaRoot
);
/* Only sent twice on Win7. */
SET_EXPECT_MULTI
(
winproc_GETOBJECT_CLIENT
,
2
);
hr
=
UiaNodeFromProvider
(
&
Provider
.
IRawElementProviderSimple_iface
,
&
node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
Provider
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
ok
(
Accessible
.
ref
>=
2
,
"Unexpected refcnt %ld
\n
"
,
Accessible
.
ref
);
todo_wine
CHECK_CALLED
(
Accessible_QI_IAccIdentity
);
todo_wine
CHECK_CALLED
(
Accessible_get_accParent
);
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
CHECK_CALLED
(
winproc_GETOBJECT_CLIENT
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ProviderDescriptionPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
check_node_provider_desc_prefix
(
V_BSTR
(
&
v
),
GetCurrentProcessId
(),
hwnd
);
check_node_provider_desc
(
V_BSTR
(
&
v
),
L"Hwnd"
,
L"Provider"
,
FALSE
);
check_node_provider_desc_todo
(
V_BSTR
(
&
v
),
L"Nonclient"
,
NULL
,
FALSE
);
check_node_provider_desc
(
V_BSTR
(
&
v
),
L"Main"
,
NULL
,
TRUE
);
VariantClear
(
&
v
);
SET_EXPECT
(
Accessible_get_accRole
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ControlTypePropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
ok
(
V_VT
(
&
v
)
==
VT_I4
,
"Unexpected VT %d
\n
"
,
V_VT
(
&
v
));
ok
(
V_I4
(
&
v
)
==
UIA_EditControlTypeId
,
"Unexpected I4 %#lx
\n
"
,
V_I4
(
&
v
));
VariantClear
(
&
v
);
CHECK_CALLED
(
Accessible_get_accRole
);
UiaNodeRelease
(
node
);
ok
(
Provider
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
ok
(
Accessible
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Accessible
.
ref
);
/*
* Unlike UiaProviderFromIAccessible which won't create a provider for an
* MSAA proxy, the default clientside proxy provider will.
*/
hwnd2
=
CreateWindowA
(
"EDIT"
,
""
,
WS_VISIBLE
|
WS_CHILD
|
ES_PASSWORD
,
0
,
0
,
100
,
100
,
hwnd
,
NULL
,
NULL
,
NULL
);
initialize_provider
(
&
Provider
,
ProviderOptions_ClientSideProvider
,
hwnd2
,
FALSE
);
/* Tries to get override provider from parent HWND. */
SET_EXPECT
(
winproc_GETOBJECT_UiaRoot
);
hr
=
UiaNodeFromProvider
(
&
Provider
.
IRawElementProviderSimple_iface
,
&
node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
Provider
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
todo_wine
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ProviderDescriptionPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
check_node_provider_desc_prefix
(
V_BSTR
(
&
v
),
GetCurrentProcessId
(),
hwnd2
);
check_node_provider_desc
(
V_BSTR
(
&
v
),
L"Hwnd"
,
L"Provider"
,
FALSE
);
check_node_provider_desc_todo
(
V_BSTR
(
&
v
),
L"Main"
,
NULL
,
FALSE
);
check_node_provider_desc_todo
(
V_BSTR
(
&
v
),
L"Annotation"
,
NULL
,
TRUE
);
VariantClear
(
&
v
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ControlTypePropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
ok
(
V_VT
(
&
v
)
==
VT_I4
,
"Unexpected VT %d
\n
"
,
V_VT
(
&
v
));
ok
(
V_I4
(
&
v
)
==
UIA_EditControlTypeId
,
"Unexpected I4 %#lx
\n
"
,
V_I4
(
&
v
));
VariantClear
(
&
v
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_IsPasswordPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
ok
(
V_VT
(
&
v
)
==
VT_BOOL
,
"Unexpected VT %d
\n
"
,
V_VT
(
&
v
));
ok
(
check_variant_bool
(
&
v
,
TRUE
),
"V_BOOL(&v) = %#x
\n
"
,
V_BOOL
(
&
v
));
VariantClear
(
&
v
);
UiaNodeRelease
(
node
);
DestroyWindow
(
hwnd2
);
set_accessible_props
(
&
Accessible
,
0
,
0
,
0
,
NULL
,
0
,
0
,
0
,
0
);
acc_client
=
NULL
;
prov_root
=
child_win_prov_root
=
NULL
;
method_sequences_enabled
=
TRUE
;
DestroyWindow
(
hwnd
);
DestroyWindow
(
hwnd_child
);
...
...
dlls/uiautomationcore/uia_client.c
View file @
a19c1ff1
...
...
@@ -2653,9 +2653,21 @@ static SAFEARRAY WINAPI *default_uia_provider_callback(HWND hwnd, enum ProviderT
switch
(
prov_type
)
{
case
ProviderType_Proxy
:
FIXME
(
"Default ProviderType_Proxy MSAA provider unimplemented.
\n
"
);
{
IAccessible
*
acc
;
hr
=
AccessibleObjectFromWindow
(
hwnd
,
OBJID_CLIENT
,
&
IID_IAccessible
,
(
void
**
)
&
acc
);
if
(
FAILED
(
hr
)
||
!
acc
)
break
;
hr
=
create_msaa_provider
(
acc
,
CHILDID_SELF
,
hwnd
,
TRUE
,
&
elprov
);
if
(
FAILED
(
hr
))
WARN
(
"Failed to create MSAA proxy provider with hr %#lx
\n
"
,
hr
);
IAccessible_Release
(
acc
);
break
;
}
case
ProviderType_NonClientArea
:
FIXME
(
"Default ProviderType_NonClientArea provider unimplemented.
\n
"
);
break
;
...
...
dlls/uiautomationcore/uia_private.h
View file @
a19c1ff1
...
...
@@ -155,3 +155,5 @@ HRESULT create_base_hwnd_provider(HWND hwnd, IRawElementProviderSimple **elprov)
void
uia_stop_provider_thread
(
void
)
DECLSPEC_HIDDEN
;
void
uia_provider_thread_remove_node
(
HUIANODE
node
)
DECLSPEC_HIDDEN
;
LRESULT
uia_lresult_from_node
(
HUIANODE
huianode
)
DECLSPEC_HIDDEN
;
HRESULT
create_msaa_provider
(
IAccessible
*
acc
,
long
child_id
,
HWND
hwnd
,
BOOL
known_root_acc
,
IRawElementProviderSimple
**
elprov
)
DECLSPEC_HIDDEN
;
dlls/uiautomationcore/uia_provider.c
View file @
a19c1ff1
...
...
@@ -796,7 +796,7 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
else
acc
=
msaa_prov
->
acc
;
hr
=
UiaProviderFromIAccessible
(
acc
,
CHILDID_SELF
,
0
,
&
elprov
);
hr
=
create_msaa_provider
(
acc
,
CHILDID_SELF
,
NULL
,
FALSE
,
&
elprov
);
if
(
SUCCEEDED
(
hr
))
{
struct
msaa_provider
*
prov
=
impl_from_msaa_provider
(
elprov
);
...
...
@@ -827,7 +827,7 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
if
(
FAILED
(
hr
)
||
!
acc
)
break
;
hr
=
UiaProviderFromIAccessible
(
acc
,
child_id
,
0
,
&
elprov
);
hr
=
create_msaa_provider
(
acc
,
child_id
,
NULL
,
FALSE
,
&
elprov
);
if
(
SUCCEEDED
(
hr
))
{
struct
msaa_provider
*
prov
=
impl_from_msaa_provider
(
elprov
);
...
...
@@ -877,7 +877,7 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
if
(
FAILED
(
hr
)
||
!
acc
)
break
;
hr
=
UiaProviderFromIAccessible
(
acc
,
child_id
,
0
,
&
elprov
);
hr
=
create_msaa_provider
(
acc
,
child_id
,
NULL
,
FALSE
,
&
elprov
);
if
(
SUCCEEDED
(
hr
))
{
struct
msaa_provider
*
prov
=
impl_from_msaa_provider
(
elprov
);
...
...
@@ -1134,13 +1134,48 @@ static const ILegacyIAccessibleProviderVtbl msaa_acc_provider_vtbl = {
msaa_acc_provider_get_DefaultAction
,
};
HRESULT
create_msaa_provider
(
IAccessible
*
acc
,
long
child_id
,
HWND
hwnd
,
BOOL
known_root_acc
,
IRawElementProviderSimple
**
elprov
)
{
struct
msaa_provider
*
msaa_prov
=
heap_alloc_zero
(
sizeof
(
*
msaa_prov
));
if
(
!
msaa_prov
)
return
E_OUTOFMEMORY
;
msaa_prov
->
IRawElementProviderSimple_iface
.
lpVtbl
=
&
msaa_provider_vtbl
;
msaa_prov
->
IRawElementProviderFragment_iface
.
lpVtbl
=
&
msaa_fragment_vtbl
;
msaa_prov
->
ILegacyIAccessibleProvider_iface
.
lpVtbl
=
&
msaa_acc_provider_vtbl
;
msaa_prov
->
refcount
=
1
;
variant_init_i4
(
&
msaa_prov
->
cid
,
child_id
);
msaa_prov
->
acc
=
acc
;
IAccessible_AddRef
(
acc
);
msaa_prov
->
ia2
=
msaa_acc_get_ia2
(
acc
);
if
(
!
hwnd
)
{
HRESULT
hr
;
hr
=
WindowFromAccessibleObject
(
acc
,
&
msaa_prov
->
hwnd
);
if
(
FAILED
(
hr
))
WARN
(
"WindowFromAccessibleObject failed with hr %#lx
\n
"
,
hr
);
}
else
msaa_prov
->
hwnd
=
hwnd
;
if
(
known_root_acc
)
msaa_prov
->
root_acc_check_ran
=
msaa_prov
->
is_root_acc
=
TRUE
;
*
elprov
=
&
msaa_prov
->
IRawElementProviderSimple_iface
;
return
S_OK
;
}
/***********************************************************************
* UiaProviderFromIAccessible (uiautomationcore.@)
*/
HRESULT
WINAPI
UiaProviderFromIAccessible
(
IAccessible
*
acc
,
long
child_id
,
DWORD
flags
,
IRawElementProviderSimple
**
elprov
)
{
struct
msaa_provider
*
msaa_prov
;
IServiceProvider
*
serv_prov
;
HWND
hwnd
=
NULL
;
HRESULT
hr
;
...
...
@@ -1184,22 +1219,7 @@ HRESULT WINAPI UiaProviderFromIAccessible(IAccessible *acc, long child_id, DWORD
if
(
!
hwnd
)
return
E_FAIL
;
msaa_prov
=
heap_alloc_zero
(
sizeof
(
*
msaa_prov
));
if
(
!
msaa_prov
)
return
E_OUTOFMEMORY
;
msaa_prov
->
IRawElementProviderSimple_iface
.
lpVtbl
=
&
msaa_provider_vtbl
;
msaa_prov
->
IRawElementProviderFragment_iface
.
lpVtbl
=
&
msaa_fragment_vtbl
;
msaa_prov
->
ILegacyIAccessibleProvider_iface
.
lpVtbl
=
&
msaa_acc_provider_vtbl
;
msaa_prov
->
refcount
=
1
;
msaa_prov
->
hwnd
=
hwnd
;
variant_init_i4
(
&
msaa_prov
->
cid
,
child_id
);
msaa_prov
->
acc
=
acc
;
IAccessible_AddRef
(
acc
);
msaa_prov
->
ia2
=
msaa_acc_get_ia2
(
acc
);
*
elprov
=
&
msaa_prov
->
IRawElementProviderSimple_iface
;
return
S_OK
;
return
create_msaa_provider
(
acc
,
child_id
,
hwnd
,
FALSE
,
elprov
);
}
static
HRESULT
uia_get_hr_for_last_error
(
void
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment