Module: wine Branch: master Commit: f59a64144ba29fb1a382d8fbbb2fd4a71dd30cf6 URL: https://source.winehq.org/git/wine.git/?a=commit;h=f59a64144ba29fb1a382d8fbb...
Author: Huw Davies huw@codeweavers.com Date: Mon Oct 4 12:23:20 2021 +0100
nsiproxy: Introduce IOCTL_NSIPROXY_WINE_ICMP_ECHO.
With this patch the irp is simply marked as pending and transferred to the request thread which completes the irp with STATUS_NOT_SUPPORTED.
Signed-off-by: Huw Davies huw@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/nsiproxy.sys/device.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ include/wine/nsi.h | 34 +++++++++++++++ 2 files changed, 137 insertions(+)
diff --git a/dlls/nsiproxy.sys/device.c b/dlls/nsiproxy.sys/device.c index fb330ddfc93..f4cefd4b794 100644 --- a/dlls/nsiproxy.sys/device.c +++ b/dlls/nsiproxy.sys/device.c @@ -36,6 +36,18 @@ WINE_DEFAULT_DEBUG_CHANNEL(nsi);
static unixlib_handle_t nsiproxy_handle; +static HANDLE request_event; + +#define DECLARE_CRITICAL_SECTION(cs) \ + static CRITICAL_SECTION cs; \ + static CRITICAL_SECTION_DEBUG cs##_debug = \ + { 0, 0, &cs, { &cs##_debug.ProcessLocksList, &cs##_debug.ProcessLocksList }, \ + 0, 0, { (DWORD_PTR)(__FILE__ ": " # cs) }}; \ + static CRITICAL_SECTION cs = { &cs##_debug, -1, 0, 0, 0, 0 }; +DECLARE_CRITICAL_SECTION( nsiproxy_cs ); + +#define LIST_ENTRY_INIT( list ) { .Flink = &(list), .Blink = &(list) } +static LIST_ENTRY request_queue = LIST_ENTRY_INIT( request_queue );
static NTSTATUS nsiproxy_call( unsigned int code, void *args ) { @@ -162,6 +174,59 @@ static NTSTATUS nsiproxy_get_parameter( IRP *irp ) return status; }
+static void WINAPI icmp_echo_cancel( DEVICE_OBJECT *device, IRP *irp ) +{ + TRACE( "device %p, irp %p.\n", device, irp ); + + IoReleaseCancelSpinLock( irp->CancelIrql ); + + /* FIXME: at the moment just let the request thread bail */ + return; +} + +static NTSTATUS nsiproxy_icmp_echo( IRP *irp ) +{ + IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); + struct nsiproxy_icmp_echo *in = (struct nsiproxy_icmp_echo *)irp->AssociatedIrp.SystemBuffer; + DWORD in_len = irpsp->Parameters.DeviceIoControl.InputBufferLength; + DWORD out_len = irpsp->Parameters.DeviceIoControl.OutputBufferLength; + + TRACE( "\n" ); + + if (in_len < offsetof(struct nsiproxy_icmp_echo, data[0]) || + in_len < offsetof(struct nsiproxy_icmp_echo, data[((in->opt_size + 3) & ~3) + in->req_size]) || + out_len < sizeof(struct nsiproxy_icmp_echo_reply)) + return STATUS_INVALID_PARAMETER; + + switch (in->dst.si_family) + { + case AF_INET: + if (in->dst.Ipv4.sin_addr.s_addr == INADDR_ANY) return STATUS_INVALID_ADDRESS_WILDCARD; + break; + default: + return STATUS_INVALID_PARAMETER; + } + + EnterCriticalSection( &nsiproxy_cs ); + + IoSetCancelRoutine( irp, icmp_echo_cancel ); + if (irp->Cancel && !IoSetCancelRoutine( irp, NULL )) + { + /* IRP was canceled before we set cancel routine */ + InitializeListHead( &irp->Tail.Overlay.ListEntry ); + LeaveCriticalSection( &nsiproxy_cs ); + return STATUS_CANCELLED; + } + + InsertTailList( &request_queue, &irp->Tail.Overlay.ListEntry ); + IoMarkIrpPending( irp ); + + LeaveCriticalSection( &nsiproxy_cs ); + SetEvent( request_event ); + + return STATUS_PENDING; +} + static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp ) { IO_STACK_LOCATION *irpsp = IoGetCurrentIrpStackLocation( irp ); @@ -186,6 +251,10 @@ static NTSTATUS WINAPI nsi_ioctl( DEVICE_OBJECT *device, IRP *irp ) status = nsiproxy_get_parameter( irp ); break;
+ case IOCTL_NSIPROXY_WINE_ICMP_ECHO: + status = nsiproxy_icmp_echo( irp ); + break; + default: FIXME( "ioctl %x not supported\n", irpsp->Parameters.DeviceIoControl.IoControlCode ); status = STATUS_NOT_SUPPORTED; @@ -220,10 +289,40 @@ static int add_device( DRIVER_OBJECT *driver ) return 1; }
+static DWORD WINAPI request_thread_proc( void *arg ) +{ + LIST_ENTRY *entry; + + while (WaitForSingleObject( request_event, INFINITE ) == WAIT_OBJECT_0) + { + TRACE( "request_event triggered\n" ); + EnterCriticalSection( &nsiproxy_cs ); + while ((entry = RemoveHeadList( &request_queue )) != &request_queue ) + { + IRP *irp = CONTAINING_RECORD( entry, IRP, Tail.Overlay.ListEntry ); + + if (irp->Cancel) + { + irp->IoStatus.Status = STATUS_CANCELLED; + TRACE( "already cancelled\n" ); + IoCompleteRequest( irp, IO_NO_INCREMENT ); + continue; + } + + /* FIXME */ + irp->IoStatus.Status = STATUS_NOT_SUPPORTED; + IoCompleteRequest( irp, IO_NO_INCREMENT ); + } + LeaveCriticalSection( &nsiproxy_cs ); + } + return 0; +} + NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path ) { HMODULE instance; NTSTATUS status; + HANDLE thread;
TRACE( "(%p, %s)\n", driver, debugstr_w( path->Buffer ) );
@@ -236,5 +335,9 @@ NTSTATUS WINAPI DriverEntry( DRIVER_OBJECT *driver, UNICODE_STRING *path )
add_device( driver );
+ request_event = CreateEventW( NULL, FALSE, FALSE, NULL ); + thread = CreateThread( NULL, 0, request_thread_proc, NULL, 0, NULL ); + CloseHandle( thread ); + return STATUS_SUCCESS; } diff --git a/include/wine/nsi.h b/include/wine/nsi.h index 7b8cb29e9d5..9664b534b09 100644 --- a/include/wine/nsi.h +++ b/include/wine/nsi.h @@ -380,6 +380,7 @@ struct nsi_udp_endpoint_static #define IOCTL_NSIPROXY_WINE_ENUMERATE_ALL CTL_CODE(FILE_DEVICE_NETWORK, 0x400, METHOD_BUFFERED, 0) #define IOCTL_NSIPROXY_WINE_GET_ALL_PARAMETERS CTL_CODE(FILE_DEVICE_NETWORK, 0x401, METHOD_BUFFERED, 0) #define IOCTL_NSIPROXY_WINE_GET_PARAMETER CTL_CODE(FILE_DEVICE_NETWORK, 0x402, METHOD_BUFFERED, 0) +#define IOCTL_NSIPROXY_WINE_ICMP_ECHO CTL_CODE(FILE_DEVICE_NETWORK, 0x403, METHOD_BUFFERED, 0)
/* input for IOCTL_NSIPROXY_WINE_ENUMERATE_ALL */ struct nsiproxy_enumerate_all @@ -420,6 +421,39 @@ struct nsiproxy_get_parameter BYTE key[1]; /* key_size */ };
+/* input for IOCTL_NSIPROXY_WINE_ICMP_ECHO */ +struct nsiproxy_icmp_echo +{ + SOCKADDR_INET src; + SOCKADDR_INET dst; + BYTE ttl; + BYTE tos; + BYTE flags; + DWORD opt_size; + DWORD req_size; + DWORD timeout; + BYTE data[1]; /* ((opt_size + 3) & ~3) + req_size */ +}; + +/* output for IOCTL_NSIPROXY_WINE_ICMP_ECHO - cf. ICMP_ECHO_REPLY */ +struct nsiproxy_icmp_echo_reply +{ + SOCKADDR_INET addr; + ULONG status; + ULONG round_trip_time; + USHORT data_size; + USHORT num_of_pkts; + DWORD data_offset; + struct + { + BYTE ttl; + BYTE tos; + BYTE flags; + BYTE options_size; + DWORD options_offset; + } opts; +}; + /* Undocumented Nsi api */
#define NSI_PARAM_TYPE_RW 0