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
890faf87
Commit
890faf87
authored
Oct 10, 2022
by
Connor McAdams
Committed by
Alexandre Julliard
Oct 12, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Implement UiaDisconnectProvider.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
858e9a4c
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
178 additions
and
9 deletions
+178
-9
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+0
-0
uia_classes.idl
dlls/uiautomationcore/uia_classes.idl
+1
-0
uia_client.c
dlls/uiautomationcore/uia_client.c
+98
-1
uia_main.c
dlls/uiautomationcore/uia_main.c
+0
-6
uia_private.h
dlls/uiautomationcore/uia_private.h
+6
-0
uia_provider.c
dlls/uiautomationcore/uia_provider.c
+72
-2
uiautomationcoreapi.h
include/uiautomationcoreapi.h
+1
-0
No files found.
dlls/uiautomationcore/tests/uiautomation.c
View file @
890faf87
This diff is collapsed.
Click to expand it.
dlls/uiautomationcore/uia_classes.idl
View file @
890faf87
...
...
@@ -56,5 +56,6 @@ library UIA_wine_private
{
HRESULT
get_provider
(
[
out
,
retval
]
IWineUiaProvider
**
out_prov
)
;
HRESULT
get_prop_val
(
[
in
]
const
GUID
*
prop_guid
,
[
out
,
retval
]
VARIANT
*
ret_val
)
;
HRESULT
disconnect
()
;
}
}
dlls/uiautomationcore/uia_client.c
View file @
890faf87
...
...
@@ -49,6 +49,54 @@ static HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems)
return
S_OK
;
}
int
uia_compare_runtime_ids
(
SAFEARRAY
*
sa1
,
SAFEARRAY
*
sa2
)
{
LONG
i
,
idx
,
lbound
[
2
],
elems
[
2
];
int
val
[
2
];
HRESULT
hr
;
hr
=
get_safearray_bounds
(
sa1
,
&
lbound
[
0
],
&
elems
[
0
]);
if
(
FAILED
(
hr
))
{
ERR
(
"Failed to get safearray bounds from sa1 with hr %#lx
\n
"
,
hr
);
return
-
1
;
}
hr
=
get_safearray_bounds
(
sa2
,
&
lbound
[
1
],
&
elems
[
1
]);
if
(
FAILED
(
hr
))
{
ERR
(
"Failed to get safearray bounds from sa2 with hr %#lx
\n
"
,
hr
);
return
-
1
;
}
if
(
elems
[
0
]
!=
elems
[
1
])
return
(
elems
[
0
]
>
elems
[
1
])
-
(
elems
[
0
]
<
elems
[
1
]);
for
(
i
=
0
;
i
<
elems
[
0
];
i
++
)
{
idx
=
lbound
[
0
]
+
i
;
hr
=
SafeArrayGetElement
(
sa1
,
&
idx
,
&
val
[
0
]);
if
(
FAILED
(
hr
))
{
ERR
(
"Failed to get element from sa1 with hr %#lx
\n
"
,
hr
);
return
-
1
;
}
idx
=
lbound
[
1
]
+
i
;
hr
=
SafeArrayGetElement
(
sa2
,
&
idx
,
&
val
[
1
]);
if
(
FAILED
(
hr
))
{
ERR
(
"Failed to get element from sa2 with hr %#lx
\n
"
,
hr
);
return
-
1
;
}
if
(
val
[
0
]
!=
val
[
1
])
return
(
val
[
0
]
>
val
[
1
])
-
(
val
[
0
]
<
val
[
1
]);
}
return
0
;
}
static
void
clear_uia_node_ptr_safearray
(
SAFEARRAY
*
sa
,
LONG
elems
)
{
HUIANODE
node
;
...
...
@@ -312,7 +360,8 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface)
}
}
IWineUiaProvider_Release
(
node
->
prov
);
if
(
node
->
prov
)
IWineUiaProvider_Release
(
node
->
prov
);
if
(
!
list_empty
(
&
node
->
prov_thread_list_entry
))
uia_provider_thread_remove_node
((
HUIANODE
)
iface
);
if
(
node
->
nested_node
)
...
...
@@ -328,6 +377,12 @@ static HRESULT WINAPI uia_node_get_provider(IWineUiaNode *iface, IWineUiaProvide
{
struct
uia_node
*
node
=
impl_from_IWineUiaNode
(
iface
);
if
(
node
->
disconnected
)
{
*
out_prov
=
NULL
;
return
UIA_E_ELEMENTNOTAVAILABLE
;
}
if
(
node
->
git_cookie
)
{
IGlobalInterfaceTable
*
git
;
...
...
@@ -360,11 +415,18 @@ static HRESULT WINAPI uia_node_get_prop_val(IWineUiaNode *iface, const GUID *pro
VARIANT
*
ret_val
)
{
int
prop_id
=
UiaLookupId
(
AutomationIdentifierType_Property
,
prop_guid
);
struct
uia_node
*
node
=
impl_from_IWineUiaNode
(
iface
);
HRESULT
hr
;
VARIANT
v
;
TRACE
(
"%p, %s, %p
\n
"
,
iface
,
debugstr_guid
(
prop_guid
),
ret_val
);
if
(
node
->
disconnected
)
{
VariantInit
(
ret_val
);
return
UIA_E_ELEMENTNOTAVAILABLE
;
}
hr
=
UiaGetPropertyValue
((
HUIANODE
)
iface
,
prop_id
,
&
v
);
/* VT_UNKNOWN is UiaGetReservedNotSupported value, no need to marshal it. */
...
...
@@ -376,12 +438,47 @@ static HRESULT WINAPI uia_node_get_prop_val(IWineUiaNode *iface, const GUID *pro
return
hr
;
}
static
HRESULT
WINAPI
uia_node_disconnect
(
IWineUiaNode
*
iface
)
{
struct
uia_node
*
node
=
impl_from_IWineUiaNode
(
iface
);
TRACE
(
"%p
\n
"
,
node
);
if
(
node
->
disconnected
)
{
ERR
(
"Attempted to disconnect node which was already disconnected.
\n
"
);
return
E_FAIL
;
}
if
(
node
->
git_cookie
)
{
IGlobalInterfaceTable
*
git
;
HRESULT
hr
;
hr
=
get_global_interface_table
(
&
git
);
if
(
SUCCEEDED
(
hr
))
{
hr
=
IGlobalInterfaceTable_RevokeInterfaceFromGlobal
(
git
,
node
->
git_cookie
);
if
(
FAILED
(
hr
))
WARN
(
"Failed to get revoke provider interface from Global Interface Table, hr %#lx
\n
"
,
hr
);
}
node
->
git_cookie
=
0
;
}
IWineUiaProvider_Release
(
node
->
prov
);
node
->
prov
=
NULL
;
node
->
disconnected
=
TRUE
;
return
S_OK
;
}
static
const
IWineUiaNodeVtbl
uia_node_vtbl
=
{
uia_node_QueryInterface
,
uia_node_AddRef
,
uia_node_Release
,
uia_node_get_provider
,
uia_node_get_prop_val
,
uia_node_disconnect
,
};
static
struct
uia_node
*
unsafe_impl_from_IWineUiaNode
(
IWineUiaNode
*
iface
)
...
...
dlls/uiautomationcore/uia_main.c
View file @
890faf87
...
...
@@ -346,12 +346,6 @@ HRESULT WINAPI UiaHostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **pr
return
S_OK
;
}
HRESULT
WINAPI
UiaDisconnectProvider
(
IRawElementProviderSimple
*
provider
)
{
FIXME
(
"(%p): stub
\n
"
,
provider
);
return
E_NOTIMPL
;
}
/***********************************************************************
* DllMain (uiautomationcore.@)
*/
...
...
dlls/uiautomationcore/uia_private.h
View file @
890faf87
...
...
@@ -39,6 +39,9 @@ struct uia_node {
HWND
hwnd
;
BOOL
nested_node
;
BOOL
disconnected
;
/* This RuntimeId is used as a comparison for UiaDisconnectProvider(). */
SAFEARRAY
*
runtime_id
;
struct
list
prov_thread_list_entry
;
};
...
...
@@ -47,6 +50,9 @@ static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface)
return
CONTAINING_RECORD
(
iface
,
struct
uia_node
,
IWineUiaNode_iface
);
}
/* uia_client.c */
int
uia_compare_runtime_ids
(
SAFEARRAY
*
sa1
,
SAFEARRAY
*
sa2
)
DECLSPEC_HIDDEN
;
/* uia_ids.c */
const
struct
uia_prop_info
*
uia_prop_info_from_id
(
PROPERTYID
prop_id
)
DECLSPEC_HIDDEN
;
...
...
dlls/uiautomationcore/uia_provider.c
View file @
890faf87
...
...
@@ -1155,18 +1155,58 @@ void uia_provider_thread_remove_node(HUIANODE node)
EnterCriticalSection
(
&
provider_thread_cs
);
list_remove
(
&
node_data
->
prov_thread_list_entry
);
list_init
(
&
node_data
->
prov_thread_list_entry
);
SafeArrayDestroy
(
node_data
->
runtime_id
);
node_data
->
runtime_id
=
NULL
;
LeaveCriticalSection
(
&
provider_thread_cs
);
}
static
void
uia_provider_thread_disconnect_node
(
SAFEARRAY
*
sa
)
{
struct
list
*
cursor
,
*
cursor2
;
struct
uia_node
*
node_data
;
EnterCriticalSection
(
&
provider_thread_cs
);
/* Provider thread hasn't been started, no nodes to disconnect. */
if
(
!
provider_thread
.
ref
)
goto
exit
;
LIST_FOR_EACH_SAFE
(
cursor
,
cursor2
,
&
provider_thread
.
nodes_list
)
{
node_data
=
LIST_ENTRY
(
cursor
,
struct
uia_node
,
prov_thread_list_entry
);
if
(
node_data
->
runtime_id
)
{
if
(
!
uia_compare_runtime_ids
(
sa
,
node_data
->
runtime_id
))
{
list_remove
(
cursor
);
list_init
(
&
node_data
->
prov_thread_list_entry
);
IWineUiaNode_disconnect
(
&
node_data
->
IWineUiaNode_iface
);
SafeArrayDestroy
(
node_data
->
runtime_id
);
node_data
->
runtime_id
=
NULL
;
}
}
}
exit:
LeaveCriticalSection
(
&
provider_thread_cs
);
}
static
HRESULT
uia_provider_thread_add_node
(
HUIANODE
node
)
{
struct
uia_node
*
node_data
=
impl_from_IWineUiaNode
((
IWineUiaNode
*
)
node
);
TRACE
(
"Adding node %p
\n
"
,
node
)
;
SAFEARRAY
*
sa
;
HRESULT
hr
;
node_data
->
nested_node
=
TRUE
;
hr
=
UiaGetRuntimeId
(
node
,
&
sa
);
if
(
FAILED
(
hr
))
return
hr
;
TRACE
(
"Adding node %p
\n
"
,
node
);
EnterCriticalSection
(
&
provider_thread_cs
);
node_data
->
runtime_id
=
sa
;
list_add_tail
(
&
provider_thread
.
nodes_list
,
&
node_data
->
prov_thread_list_entry
);
LeaveCriticalSection
(
&
provider_thread_cs
);
...
...
@@ -1363,3 +1403,33 @@ LRESULT WINAPI UiaReturnRawElementProvider(HWND hwnd, WPARAM wparam,
return
uia_lresult_from_node
(
node
);
}
/***********************************************************************
* UiaDisconnectProvider (uiautomationcore.@)
*/
HRESULT
WINAPI
UiaDisconnectProvider
(
IRawElementProviderSimple
*
elprov
)
{
SAFEARRAY
*
sa
;
HUIANODE
node
;
HRESULT
hr
;
TRACE
(
"(%p)
\n
"
,
elprov
);
hr
=
UiaNodeFromProvider
(
elprov
,
&
node
);
if
(
FAILED
(
hr
))
return
hr
;
hr
=
UiaGetRuntimeId
(
node
,
&
sa
);
UiaNodeRelease
(
node
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
!
sa
)
return
E_INVALIDARG
;
uia_provider_thread_disconnect_node
(
sa
);
SafeArrayDestroy
(
sa
);
return
S_OK
;
}
include/uiautomationcoreapi.h
View file @
890faf87
...
...
@@ -398,6 +398,7 @@ BOOL WINAPI UiaNodeRelease(HUIANODE huianode);
HRESULT
WINAPI
UiaGetRuntimeId
(
HUIANODE
huianode
,
SAFEARRAY
**
runtime_id
);
HRESULT
WINAPI
UiaHUiaNodeFromVariant
(
VARIANT
*
in_val
,
HUIANODE
*
huianode
);
HRESULT
WINAPI
UiaNodeFromHandle
(
HWND
hwnd
,
HUIANODE
*
huianode
);
HRESULT
WINAPI
UiaDisconnectProvider
(
IRawElementProviderSimple
*
elprov
);
#ifdef __cplusplus
}
...
...
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