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>
This commit is contained in:
parent
7ed25b6c16
commit
f59a64144b
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue