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
7aaf77a5
Commit
7aaf77a5
authored
Sep 14, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
Oct 02, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Pass WinEvent data to IProxyProviderWinEventHandler::RespondToWinEvent.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
0254db34
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
192 additions
and
7 deletions
+192
-7
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+12
-4
uia_classes.idl
dlls/uiautomationcore/uia_classes.idl
+3
-0
uia_client.c
dlls/uiautomationcore/uia_client.c
+44
-0
uia_event.c
dlls/uiautomationcore/uia_event.c
+130
-3
uia_private.h
dlls/uiautomationcore/uia_private.h
+3
-0
No files found.
dlls/uiautomationcore/tests/uiautomation.c
View file @
7aaf77a5
...
@@ -449,6 +449,11 @@ static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_
...
@@ -449,6 +449,11 @@ static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_
IUnknown_Release
(
unk2
);
IUnknown_Release
(
unk2
);
}
}
#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
static
void
check_interface_marshal_proxy_creation_
(
IUnknown
*
iface
,
REFIID
iid
,
BOOL
expect_proxy
,
const
char
*
file
,
int
line
);
#define DEFINE_ACC_METHOD_EXPECT(method) \
#define DEFINE_ACC_METHOD_EXPECT(method) \
int expect_ ## method , called_ ## method
int expect_ ## method , called_ ## method
...
@@ -2824,6 +2829,11 @@ static HRESULT WINAPI ProviderWinEventHandler_RespondToWinEvent(IProxyProviderWi
...
@@ -2824,6 +2829,11 @@ static HRESULT WINAPI ProviderWinEventHandler_RespondToWinEvent(IProxyProviderWi
if
(
data
->
responder_prov
)
if
(
data
->
responder_prov
)
{
{
/*
* The IProxyProviderWinEventSink interface uses the free threaded
* marshaler, so no proxy will be created in-process.
*/
check_interface_marshal_proxy_creation
((
IUnknown
*
)
event_sink
,
&
IID_IProxyProviderWinEventSink
,
FALSE
);
hr
=
IProxyProviderWinEventSink_AddAutomationEvent
(
event_sink
,
data
->
responder_prov
,
data
->
responder_event
);
hr
=
IProxyProviderWinEventSink_AddAutomationEvent
(
event_sink
,
data
->
responder_prov
,
data
->
responder_event
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
}
}
...
@@ -11976,8 +11986,6 @@ static DWORD WINAPI interface_marshal_proxy_thread(LPVOID param)
...
@@ -11976,8 +11986,6 @@ static DWORD WINAPI interface_marshal_proxy_thread(LPVOID param)
return
0
;
return
0
;
}
}
#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
static
void
check_interface_marshal_proxy_creation_
(
IUnknown
*
iface
,
REFIID
iid
,
BOOL
expect_proxy
,
const
char
*
file
,
static
void
check_interface_marshal_proxy_creation_
(
IUnknown
*
iface
,
REFIID
iid
,
BOOL
expect_proxy
,
const
char
*
file
,
int
line
)
int
line
)
{
{
...
@@ -16717,8 +16725,8 @@ static const struct prov_method_sequence win_event_handler_seq[] = {
...
@@ -16717,8 +16725,8 @@ static const struct prov_method_sequence win_event_handler_seq[] = {
{
&
Provider_hwnd2
,
PROV_GET_HOST_RAW_ELEMENT_PROVIDER
,
METHOD_OPTIONAL
},
/* Only done on Win10v1809+. */
{
&
Provider_hwnd2
,
PROV_GET_HOST_RAW_ELEMENT_PROVIDER
,
METHOD_OPTIONAL
},
/* Only done on Win10v1809+. */
{
&
Provider_nc2
,
FRAG_NAVIGATE
},
/* NavigateDirection_Parent */
{
&
Provider_nc2
,
FRAG_NAVIGATE
},
/* NavigateDirection_Parent */
{
&
Provider_hwnd2
,
FRAG_NAVIGATE
},
/* NavigateDirection_Parent */
{
&
Provider_hwnd2
,
FRAG_NAVIGATE
},
/* NavigateDirection_Parent */
{
&
Provider_nc2
,
WINEVENT_HANDLER_RESPOND_TO_WINEVENT
,
METHOD_TODO
},
{
&
Provider_nc2
,
WINEVENT_HANDLER_RESPOND_TO_WINEVENT
},
{
&
Provider_hwnd2
,
WINEVENT_HANDLER_RESPOND_TO_WINEVENT
,
METHOD_TODO
},
{
&
Provider_hwnd2
,
WINEVENT_HANDLER_RESPOND_TO_WINEVENT
},
NODE_CREATE_SEQ_TODO
(
&
Provider_child
),
NODE_CREATE_SEQ_TODO
(
&
Provider_child
),
{
&
Provider_child
,
FRAG_GET_RUNTIME_ID
,
METHOD_TODO
},
{
&
Provider_child
,
FRAG_GET_RUNTIME_ID
,
METHOD_TODO
},
{
&
Provider_child
,
PROV_GET_PROPERTY_VALUE
,
METHOD_TODO
},
/* UIA_ProviderDescriptionPropertyId */
{
&
Provider_child
,
PROV_GET_PROPERTY_VALUE
,
METHOD_TODO
},
/* UIA_ProviderDescriptionPropertyId */
...
...
dlls/uiautomationcore/uia_classes.idl
View file @
7aaf77a5
...
@@ -19,6 +19,7 @@
...
@@ -19,6 +19,7 @@
#
pragma
makedep
regtypelib
#
pragma
makedep
regtypelib
import
"oaidl.idl"
;
import
"oaidl.idl"
;
import
"uiautomationcore.idl"
;
struct
uia_prop_info
{
struct
uia_prop_info
{
const
GUID
*
guid
;
const
GUID
*
guid
;
...
@@ -92,6 +93,8 @@ library UIA_wine_private
...
@@ -92,6 +93,8 @@ library UIA_wine_private
HRESULT
navigate
(
[
in
]
int
nav_dir
,
[
out
,
retval
]
VARIANT
*
ret_val
)
;
HRESULT
navigate
(
[
in
]
int
nav_dir
,
[
out
,
retval
]
VARIANT
*
ret_val
)
;
HRESULT
get_focus
(
[
out
,
retval
]
VARIANT
*
ret_val
)
;
HRESULT
get_focus
(
[
out
,
retval
]
VARIANT
*
ret_val
)
;
HRESULT
attach_event
(
[
in
]
LONG_PTR
huiaevent
)
;
HRESULT
attach_event
(
[
in
]
LONG_PTR
huiaevent
)
;
HRESULT
respond_to_win_event
(
[
in
]
DWORD
win_event
,
[
in
]
ULONG
hwnd
,
[
in
]
LONG
obj_id
,
[
in
]
LONG
child_id
,
[
in
]
IProxyProviderWinEventSink
*
sink
)
;
}
}
[
[
...
...
dlls/uiautomationcore/uia_client.c
View file @
7aaf77a5
...
@@ -378,6 +378,22 @@ static HRESULT attach_event_to_node_provider(IWineUiaNode *node, int idx, HUIAEV
...
@@ -378,6 +378,22 @@ static HRESULT attach_event_to_node_provider(IWineUiaNode *node, int idx, HUIAEV
return
hr
;
return
hr
;
}
}
HRESULT
respond_to_win_event_on_node_provider
(
IWineUiaNode
*
node
,
int
idx
,
DWORD
win_event
,
HWND
hwnd
,
LONG
obj_id
,
LONG
child_id
,
IProxyProviderWinEventSink
*
sink
)
{
IWineUiaProvider
*
prov
;
HRESULT
hr
;
hr
=
IWineUiaNode_get_provider
(
node
,
idx
,
&
prov
);
if
(
FAILED
(
hr
))
return
hr
;
hr
=
IWineUiaProvider_respond_to_win_event
(
prov
,
win_event
,
HandleToUlong
(
hwnd
),
obj_id
,
child_id
,
sink
);
IWineUiaProvider_Release
(
prov
);
return
hr
;
}
/*
/*
* IWineUiaNode interface.
* IWineUiaNode interface.
*/
*/
...
@@ -1939,6 +1955,23 @@ exit:
...
@@ -1939,6 +1955,23 @@ exit:
return
hr
;
return
hr
;
}
}
static
HRESULT
WINAPI
uia_provider_respond_to_win_event
(
IWineUiaProvider
*
iface
,
DWORD
win_event
,
ULONG
hwnd
,
LONG
obj_id
,
LONG
child_id
,
IProxyProviderWinEventSink
*
sink
)
{
struct
uia_provider
*
prov
=
impl_from_IWineUiaProvider
(
iface
);
IProxyProviderWinEventHandler
*
handler
;
HRESULT
hr
;
hr
=
IRawElementProviderSimple_QueryInterface
(
prov
->
elprov
,
&
IID_IProxyProviderWinEventHandler
,
(
void
**
)
&
handler
);
if
(
FAILED
(
hr
))
return
S_OK
;
hr
=
IProxyProviderWinEventHandler_RespondToWinEvent
(
handler
,
win_event
,
UlongToHandle
(
hwnd
),
obj_id
,
child_id
,
sink
);
IProxyProviderWinEventHandler_Release
(
handler
);
return
hr
;
}
static
const
IWineUiaProviderVtbl
uia_provider_vtbl
=
{
static
const
IWineUiaProviderVtbl
uia_provider_vtbl
=
{
uia_provider_QueryInterface
,
uia_provider_QueryInterface
,
uia_provider_AddRef
,
uia_provider_AddRef
,
...
@@ -1949,6 +1982,7 @@ static const IWineUiaProviderVtbl uia_provider_vtbl = {
...
@@ -1949,6 +1982,7 @@ static const IWineUiaProviderVtbl uia_provider_vtbl = {
uia_provider_navigate
,
uia_provider_navigate
,
uia_provider_get_focus
,
uia_provider_get_focus
,
uia_provider_attach_event
,
uia_provider_attach_event
,
uia_provider_respond_to_win_event
,
};
};
static
HRESULT
create_wine_uia_provider
(
struct
uia_node
*
node
,
IRawElementProviderSimple
*
elprov
,
static
HRESULT
create_wine_uia_provider
(
struct
uia_node
*
node
,
IRawElementProviderSimple
*
elprov
,
...
@@ -2388,6 +2422,15 @@ static HRESULT WINAPI uia_nested_node_provider_attach_event(IWineUiaProvider *if
...
@@ -2388,6 +2422,15 @@ static HRESULT WINAPI uia_nested_node_provider_attach_event(IWineUiaProvider *if
return
hr
;
return
hr
;
}
}
static
HRESULT
WINAPI
uia_nested_node_provider_respond_to_win_event
(
IWineUiaProvider
*
iface
,
DWORD
win_event
,
ULONG
hwnd
,
LONG
obj_id
,
LONG
child_id
,
IProxyProviderWinEventSink
*
sink
)
{
FIXME
(
"%p, %#lx, #%lx, %#lx, %#lx, %p: stub
\n
"
,
iface
,
win_event
,
hwnd
,
obj_id
,
child_id
,
sink
);
/* This should not be called. */
assert
(
0
);
return
E_FAIL
;
}
static
const
IWineUiaProviderVtbl
uia_nested_node_provider_vtbl
=
{
static
const
IWineUiaProviderVtbl
uia_nested_node_provider_vtbl
=
{
uia_nested_node_provider_QueryInterface
,
uia_nested_node_provider_QueryInterface
,
uia_nested_node_provider_AddRef
,
uia_nested_node_provider_AddRef
,
...
@@ -2398,6 +2441,7 @@ static const IWineUiaProviderVtbl uia_nested_node_provider_vtbl = {
...
@@ -2398,6 +2441,7 @@ static const IWineUiaProviderVtbl uia_nested_node_provider_vtbl = {
uia_nested_node_provider_navigate
,
uia_nested_node_provider_navigate
,
uia_nested_node_provider_get_focus
,
uia_nested_node_provider_get_focus
,
uia_nested_node_provider_attach_event
,
uia_nested_node_provider_attach_event
,
uia_nested_node_provider_respond_to_win_event
,
};
};
static
BOOL
is_nested_node_provider
(
IWineUiaProvider
*
iface
)
static
BOOL
is_nested_node_provider
(
IWineUiaProvider
*
iface
)
...
...
dlls/uiautomationcore/uia_event.c
View file @
7aaf77a5
...
@@ -20,7 +20,6 @@
...
@@ -20,7 +20,6 @@
#include "wine/debug.h"
#include "wine/debug.h"
#include "wine/rbtree.h"
#include "wine/rbtree.h"
#include "assert.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
uiautomation
);
WINE_DEFAULT_DEBUG_CHANNEL
(
uiautomation
);
...
@@ -324,6 +323,118 @@ static void uia_event_args_release(struct uia_event_args *args)
...
@@ -324,6 +323,118 @@ static void uia_event_args_release(struct uia_event_args *args)
}
}
/*
/*
* IProxyProviderWinEventSink interface implementation.
*/
struct
uia_proxy_win_event_sink
{
IProxyProviderWinEventSink
IProxyProviderWinEventSink_iface
;
LONG
ref
;
int
event_id
;
IUnknown
*
marshal
;
};
static
inline
struct
uia_proxy_win_event_sink
*
impl_from_IProxyProviderWinEventSink
(
IProxyProviderWinEventSink
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
uia_proxy_win_event_sink
,
IProxyProviderWinEventSink_iface
);
}
static
HRESULT
WINAPI
uia_proxy_win_event_sink_QueryInterface
(
IProxyProviderWinEventSink
*
iface
,
REFIID
riid
,
void
**
obj
)
{
struct
uia_proxy_win_event_sink
*
sink
=
impl_from_IProxyProviderWinEventSink
(
iface
);
*
obj
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IProxyProviderWinEventSink
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
obj
=
iface
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IMarshal
))
return
IUnknown_QueryInterface
(
sink
->
marshal
,
riid
,
obj
);
else
return
E_NOINTERFACE
;
IProxyProviderWinEventSink_AddRef
(
iface
);
return
S_OK
;
}
static
ULONG
WINAPI
uia_proxy_win_event_sink_AddRef
(
IProxyProviderWinEventSink
*
iface
)
{
struct
uia_proxy_win_event_sink
*
sink
=
impl_from_IProxyProviderWinEventSink
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
sink
->
ref
);
TRACE
(
"%p, refcount %ld
\n
"
,
sink
,
ref
);
return
ref
;
}
static
ULONG
WINAPI
uia_proxy_win_event_sink_Release
(
IProxyProviderWinEventSink
*
iface
)
{
struct
uia_proxy_win_event_sink
*
sink
=
impl_from_IProxyProviderWinEventSink
(
iface
);
ULONG
ref
=
InterlockedDecrement
(
&
sink
->
ref
);
TRACE
(
"%p, refcount %ld
\n
"
,
sink
,
ref
);
if
(
!
ref
)
{
IUnknown_Release
(
sink
->
marshal
);
free
(
sink
);
}
return
ref
;
}
static
HRESULT
WINAPI
uia_proxy_win_event_sink_AddAutomationPropertyChangedEvent
(
IProxyProviderWinEventSink
*
iface
,
IRawElementProviderSimple
*
elprov
,
PROPERTYID
prop_id
,
VARIANT
new_value
)
{
FIXME
(
"%p, %p, %d, %s: stub
\n
"
,
iface
,
elprov
,
prop_id
,
debugstr_variant
(
&
new_value
));
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
uia_proxy_win_event_sink_AddAutomationEvent
(
IProxyProviderWinEventSink
*
iface
,
IRawElementProviderSimple
*
elprov
,
EVENTID
event_id
)
{
FIXME
(
"%p, %p, %d: stub
\n
"
,
iface
,
elprov
,
event_id
);
return
S_OK
;
}
static
HRESULT
WINAPI
uia_proxy_win_event_sink_AddStructureChangedEvent
(
IProxyProviderWinEventSink
*
iface
,
IRawElementProviderSimple
*
elprov
,
enum
StructureChangeType
structure_change_type
,
SAFEARRAY
*
runtime_id
)
{
FIXME
(
"%p, %p, %d, %p: stub
\n
"
,
iface
,
elprov
,
structure_change_type
,
runtime_id
);
return
E_NOTIMPL
;
}
static
const
IProxyProviderWinEventSinkVtbl
uia_proxy_event_sink_vtbl
=
{
uia_proxy_win_event_sink_QueryInterface
,
uia_proxy_win_event_sink_AddRef
,
uia_proxy_win_event_sink_Release
,
uia_proxy_win_event_sink_AddAutomationPropertyChangedEvent
,
uia_proxy_win_event_sink_AddAutomationEvent
,
uia_proxy_win_event_sink_AddStructureChangedEvent
,
};
static
HRESULT
create_proxy_win_event_sink
(
struct
uia_proxy_win_event_sink
**
out_sink
,
int
event_id
)
{
struct
uia_proxy_win_event_sink
*
sink
=
calloc
(
1
,
sizeof
(
*
sink
));
HRESULT
hr
;
*
out_sink
=
NULL
;
if
(
!
sink
)
return
E_OUTOFMEMORY
;
sink
->
IProxyProviderWinEventSink_iface
.
lpVtbl
=
&
uia_proxy_event_sink_vtbl
;
sink
->
ref
=
1
;
sink
->
event_id
=
event_id
;
hr
=
CoCreateFreeThreadedMarshaler
((
IUnknown
*
)
&
sink
->
IProxyProviderWinEventSink_iface
,
&
sink
->
marshal
);
if
(
FAILED
(
hr
))
{
free
(
sink
);
return
hr
;
}
*
out_sink
=
sink
;
return
S_OK
;
}
/*
* UI Automation event thread.
* UI Automation event thread.
*/
*/
struct
uia_event_thread
struct
uia_event_thread
...
@@ -576,9 +687,12 @@ static HRESULT create_msaa_provider_from_hwnd(HWND hwnd, int in_child_id, IRawEl
...
@@ -576,9 +687,12 @@ static HRESULT create_msaa_provider_from_hwnd(HWND hwnd, int in_child_id, IRawEl
static
HRESULT
uia_win_event_for_each_callback
(
struct
uia_event
*
event
,
void
*
data
)
static
HRESULT
uia_win_event_for_each_callback
(
struct
uia_event
*
event
,
void
*
data
)
{
{
struct
uia_queue_win_event
*
win_event
=
(
struct
uia_queue_win_event
*
)
data
;
struct
uia_queue_win_event
*
win_event
=
(
struct
uia_queue_win_event
*
)
data
;
struct
uia_proxy_win_event_sink
*
sink
;
IRawElementProviderSimple
*
elprov
;
IRawElementProviderSimple
*
elprov
;
struct
uia_node
*
node_data
;
HUIANODE
node
;
HUIANODE
node
;
HRESULT
hr
;
HRESULT
hr
;
int
i
;
/*
/*
* Check if this HWND, or any of it's ancestors (excluding the desktop)
* Check if this HWND, or any of it's ancestors (excluding the desktop)
...
@@ -605,10 +719,23 @@ static HRESULT uia_win_event_for_each_callback(struct uia_event *event, void *da
...
@@ -605,10 +719,23 @@ static HRESULT uia_win_event_for_each_callback(struct uia_event *event, void *da
if
(
FAILED
(
hr
))
if
(
FAILED
(
hr
))
return
hr
;
return
hr
;
FIXME
(
"IProxyProviderWinEventHandler usage is currently unimplemented.
\n
"
);
hr
=
create_proxy_win_event_sink
(
&
sink
,
event
->
event_id
);
if
(
SUCCEEDED
(
hr
))
{
node_data
=
impl_from_IWineUiaNode
((
IWineUiaNode
*
)
node
);
for
(
i
=
0
;
i
<
node_data
->
prov_count
;
i
++
)
{
hr
=
respond_to_win_event_on_node_provider
((
IWineUiaNode
*
)
node
,
i
,
win_event
->
event_id
,
win_event
->
hwnd
,
win_event
->
obj_id
,
win_event
->
child_id
,
&
sink
->
IProxyProviderWinEventSink_iface
);
if
(
FAILED
(
hr
))
break
;
}
IProxyProviderWinEventSink_Release
(
&
sink
->
IProxyProviderWinEventSink_iface
);
}
UiaNodeRelease
(
node
);
UiaNodeRelease
(
node
);
return
S_OK
;
return
hr
;
}
}
static
void
uia_event_thread_process_queue
(
struct
list
*
event_queue
)
static
void
uia_event_thread_process_queue
(
struct
list
*
event_queue
)
...
...
dlls/uiautomationcore/uia_private.h
View file @
7aaf77a5
...
@@ -22,6 +22,7 @@
...
@@ -22,6 +22,7 @@
#include "uia_classes.h"
#include "uia_classes.h"
#include "wine/list.h"
#include "wine/list.h"
#include "wine/rbtree.h"
#include "wine/rbtree.h"
#include "assert.h"
extern
HMODULE
huia_module
DECLSPEC_HIDDEN
;
extern
HMODULE
huia_module
DECLSPEC_HIDDEN
;
...
@@ -210,6 +211,8 @@ static inline BOOL uia_array_reserve(void **elements, SIZE_T *capacity, SIZE_T c
...
@@ -210,6 +211,8 @@ static inline BOOL uia_array_reserve(void **elements, SIZE_T *capacity, SIZE_T c
/* uia_client.c */
/* uia_client.c */
int
get_node_provider_type_at_idx
(
struct
uia_node
*
node
,
int
idx
)
DECLSPEC_HIDDEN
;
int
get_node_provider_type_at_idx
(
struct
uia_node
*
node
,
int
idx
)
DECLSPEC_HIDDEN
;
HRESULT
respond_to_win_event_on_node_provider
(
IWineUiaNode
*
node
,
int
idx
,
DWORD
win_event
,
HWND
hwnd
,
LONG
obj_id
,
LONG
child_id
,
IProxyProviderWinEventSink
*
sink
)
DECLSPEC_HIDDEN
;
HRESULT
attach_event_to_uia_node
(
HUIANODE
node
,
struct
uia_event
*
event
)
DECLSPEC_HIDDEN
;
HRESULT
attach_event_to_uia_node
(
HUIANODE
node
,
struct
uia_event
*
event
)
DECLSPEC_HIDDEN
;
HRESULT
clone_uia_node
(
HUIANODE
in_node
,
HUIANODE
*
out_node
)
DECLSPEC_HIDDEN
;
HRESULT
clone_uia_node
(
HUIANODE
in_node
,
HUIANODE
*
out_node
)
DECLSPEC_HIDDEN
;
HRESULT
navigate_uia_node
(
struct
uia_node
*
node
,
int
nav_dir
,
HUIANODE
*
out_node
)
DECLSPEC_HIDDEN
;
HRESULT
navigate_uia_node
(
struct
uia_node
*
node
,
int
nav_dir
,
HUIANODE
*
out_node
)
DECLSPEC_HIDDEN
;
...
...
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