Huw Davies : nsiproxy: Implement the ability to cancel the listener.
Alexandre Julliard
julliard at winehq.org
Tue Oct 5 15:51:40 CDT 2021
Module: wine
Branch: master
Commit: 19a6d409c04c5a9361cc753183224b3286a58181
URL: https://source.winehq.org/git/wine.git/?a=commit;h=19a6d409c04c5a9361cc753183224b3286a58181
Author: Huw Davies <huw at codeweavers.com>
Date: Tue Oct 5 07:37:53 2021 +0100
nsiproxy: Implement the ability to cancel the listener.
Signed-off-by: Huw Davies <huw at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
dlls/nsiproxy.sys/device.c | 16 ++++++++++++++--
dlls/nsiproxy.sys/icmp_echo.c | 31 +++++++++++++++++++++++++++++--
dlls/nsiproxy.sys/nsi.c | 1 +
dlls/nsiproxy.sys/unix_private.h | 1 +
4 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/dlls/nsiproxy.sys/device.c b/dlls/nsiproxy.sys/device.c
index 6461071c395..90a7a3ded7c 100644
--- a/dlls/nsiproxy.sys/device.c
+++ b/dlls/nsiproxy.sys/device.c
@@ -58,6 +58,7 @@ static NTSTATUS nsiproxy_call( unsigned int code, void *args )
enum unix_calls
{
+ icmp_cancel_listen,
icmp_close,
icmp_listen,
icmp_send_echo,
@@ -191,12 +192,23 @@ static inline HANDLE irp_set_icmp_handle( IRP *irp, HANDLE handle )
static void WINAPI icmp_echo_cancel( DEVICE_OBJECT *device, IRP *irp )
{
+ HANDLE handle;
+
TRACE( "device %p, irp %p.\n", device, irp );
IoReleaseCancelSpinLock( irp->CancelIrql );
- /* FIXME: at the moment just let the request thread bail */
- return;
+ EnterCriticalSection( &nsiproxy_cs );
+
+ /* If the handle is not set, either the irp is still
+ in the request queue, in which case the request thread will
+ cancel it, or the irp has already finished. If the handle
+ does exist then notify the listen thread. In all cases the irp
+ will be completed elsewhere. */
+ handle = irp_get_icmp_handle( irp );
+ if (handle) nsiproxy_call( icmp_cancel_listen, handle );
+
+ LeaveCriticalSection( &nsiproxy_cs );
}
static NTSTATUS nsiproxy_icmp_echo( IRP *irp )
diff --git a/dlls/nsiproxy.sys/icmp_echo.c b/dlls/nsiproxy.sys/icmp_echo.c
index cef5c04a6c7..999b53186c2 100644
--- a/dlls/nsiproxy.sys/icmp_echo.c
+++ b/dlls/nsiproxy.sys/icmp_echo.c
@@ -100,6 +100,7 @@ struct icmp_data
{
LARGE_INTEGER send_time;
int socket;
+ int cancel_pipe[2];
unsigned short id;
unsigned short seq;
const struct family_ops *ops;
@@ -522,8 +523,14 @@ static NTSTATUS icmp_data_create( ADDRESS_FAMILY win_family, struct icmp_data **
if (ops->family == AF_INET) ops = &ipv4_linux_ping;
#endif
}
- data->ops = ops;
+ if (pipe( data->cancel_pipe ))
+ {
+ close( data->socket );
+ free( data );
+ return STATUS_ACCESS_DENIED;
+ }
+ data->ops = ops;
*icmp_data = data;
return STATUS_SUCCESS;
}
@@ -531,6 +538,8 @@ static NTSTATUS icmp_data_create( ADDRESS_FAMILY win_family, struct icmp_data **
static void icmp_data_free( struct icmp_data *data )
{
close( data->socket );
+ close( data->cancel_pipe[0] );
+ close( data->cancel_pipe[1] );
free( data );
}
@@ -668,7 +677,7 @@ NTSTATUS icmp_listen( void *args )
{
struct icmp_listen_params *params = args;
struct icmp_data *data;
- struct pollfd fds[1];
+ struct pollfd fds[2];
NTSTATUS status;
int ret;
@@ -677,9 +686,17 @@ NTSTATUS icmp_listen( void *args )
fds[0].fd = data->socket;
fds[0].events = POLLIN;
+ fds[1].fd = data->cancel_pipe[0];
+ fds[1].events = POLLIN;
while ((ret = poll( fds, ARRAY_SIZE(fds), get_timeout( data->send_time, params->timeout ) )) > 0)
{
+ if (fds[1].revents & POLLIN)
+ {
+ TRACE( "cancelled\n" );
+ return STATUS_CANCELLED;
+ }
+
status = recv_msg( data, params );
if (status == STATUS_RETRY) continue;
return status;
@@ -694,6 +711,16 @@ NTSTATUS icmp_listen( void *args )
return set_reply_ip_status( params, errno_to_ip_status( errno ) );
}
+NTSTATUS icmp_cancel_listen( void *args )
+{
+ HANDLE handle = args;
+ struct icmp_data *data = handle_data( handle );
+
+ if (!data) return STATUS_INVALID_PARAMETER;
+ write( data->cancel_pipe[1], "x", 1 );
+ return STATUS_SUCCESS;
+}
+
NTSTATUS icmp_close( void *args )
{
HANDLE handle = args;
diff --git a/dlls/nsiproxy.sys/nsi.c b/dlls/nsiproxy.sys/nsi.c
index b92de7a9a11..fa997d2fe36 100644
--- a/dlls/nsiproxy.sys/nsi.c
+++ b/dlls/nsiproxy.sys/nsi.c
@@ -147,6 +147,7 @@ static NTSTATUS unix_nsi_get_parameter_ex( void *args )
const unixlib_entry_t __wine_unix_call_funcs[] =
{
+ icmp_cancel_listen,
icmp_close,
icmp_listen,
icmp_send_echo,
diff --git a/dlls/nsiproxy.sys/unix_private.h b/dlls/nsiproxy.sys/unix_private.h
index 855c06011f9..ffb48cc7380 100644
--- a/dlls/nsiproxy.sys/unix_private.h
+++ b/dlls/nsiproxy.sys/unix_private.h
@@ -157,6 +157,7 @@ static inline int ascii_strcasecmp( const char *s1, const char *s2 )
return ascii_strncasecmp( s1, s2, -1 );
}
+NTSTATUS icmp_cancel_listen( void *args ) DECLSPEC_HIDDEN;
NTSTATUS icmp_close( void *args ) DECLSPEC_HIDDEN;
NTSTATUS icmp_listen( void *args ) DECLSPEC_HIDDEN;
NTSTATUS icmp_send_echo( void *args ) DECLSPEC_HIDDEN;
More information about the wine-cvs
mailing list