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