diff options
Diffstat (limited to 'private/ntos/afd/dispatch.c')
-rw-r--r-- | private/ntos/afd/dispatch.c | 604 |
1 files changed, 604 insertions, 0 deletions
diff --git a/private/ntos/afd/dispatch.c b/private/ntos/afd/dispatch.c new file mode 100644 index 000000000..80cce6922 --- /dev/null +++ b/private/ntos/afd/dispatch.c @@ -0,0 +1,604 @@ +/*++ + +Copyright (c) 1989 Microsoft Corporation + +Module Name: + + dispatch.c + +Abstract: + + This module contains the dispatch routines for AFD. + +Author: + + David Treadwell (davidtr) 21-Feb-1992 + +Revision History: + +--*/ + +#include "afdp.h" + +NTSTATUS +AfdDispatchDeviceControl ( + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text( PAGEAFD, AfdDispatch ) +#pragma alloc_text( PAGEAFD, AfdDispatchDeviceControl ) +#endif + +// +// Lookup table to verify incoming IOCTL codes. +// + +ULONG AfdIoctlTable[] = + { + IOCTL_AFD_BIND, + IOCTL_AFD_CONNECT, + IOCTL_AFD_START_LISTEN, + IOCTL_AFD_WAIT_FOR_LISTEN, + IOCTL_AFD_ACCEPT, + IOCTL_AFD_RECEIVE, + IOCTL_AFD_RECEIVE_DATAGRAM, + IOCTL_AFD_SEND, + IOCTL_AFD_SEND_DATAGRAM, + IOCTL_AFD_POLL, + IOCTL_AFD_PARTIAL_DISCONNECT, + IOCTL_AFD_GET_ADDRESS, + IOCTL_AFD_QUERY_RECEIVE_INFO, + IOCTL_AFD_QUERY_HANDLES, + IOCTL_AFD_SET_INFORMATION, + IOCTL_AFD_GET_CONTEXT_LENGTH, + IOCTL_AFD_GET_CONTEXT, + IOCTL_AFD_SET_CONTEXT, + IOCTL_AFD_SET_CONNECT_DATA, + IOCTL_AFD_SET_CONNECT_OPTIONS, + IOCTL_AFD_SET_DISCONNECT_DATA, + IOCTL_AFD_SET_DISCONNECT_OPTIONS, + IOCTL_AFD_GET_CONNECT_DATA, + IOCTL_AFD_GET_CONNECT_OPTIONS, + IOCTL_AFD_GET_DISCONNECT_DATA, + IOCTL_AFD_GET_DISCONNECT_OPTIONS, + IOCTL_AFD_SIZE_CONNECT_DATA, + IOCTL_AFD_SIZE_CONNECT_OPTIONS, + IOCTL_AFD_SIZE_DISCONNECT_DATA, + IOCTL_AFD_SIZE_DISCONNECT_OPTIONS, + IOCTL_AFD_GET_INFORMATION, + IOCTL_AFD_TRANSMIT_FILE, + IOCTL_AFD_SUPER_ACCEPT, + IOCTL_AFD_EVENT_SELECT, + IOCTL_AFD_ENUM_NETWORK_EVENTS, + IOCTL_AFD_DEFER_ACCEPT, + IOCTL_AFD_WAIT_FOR_LISTEN_LIFO, + IOCTL_AFD_SET_QOS, + IOCTL_AFD_GET_QOS, + IOCTL_AFD_NO_OPERATION, + IOCTL_AFD_VALIDATE_GROUP, + IOCTL_AFD_GET_UNACCEPTED_CONNECT_DATA + +#ifdef NT351 + ,IOCTL_AFD_QUEUE_APC +#endif + }; + +#define NUM_AFD_IOCTLS ( sizeof(AfdIoctlTable) / sizeof(AfdIoctlTable[0]) ) + + +NTSTATUS +AfdDispatch ( + IN PDEVICE_OBJECT DeviceObject, + IN PIRP Irp + ) + +/*++ + +Routine Description: + + This is the dispatch routine for AFD. + +Arguments: + + DeviceObject - Pointer to device object for target device + + Irp - Pointer to I/O request packet + +Return Value: + + NTSTATUS -- Indicates whether the request was successfully queued. + +--*/ + +{ + PIO_STACK_LOCATION irpSp; + NTSTATUS status; +#if DBG + KIRQL oldIrql; + + oldIrql = KeGetCurrentIrql( ); +#endif + + DeviceObject; // prevent compiler warnings + + irpSp = IoGetCurrentIrpStackLocation( Irp ); + + switch ( irpSp->MajorFunction ) { + + case IRP_MJ_DEVICE_CONTROL: + + return AfdDispatchDeviceControl( Irp, irpSp ); + + case IRP_MJ_WRITE: + + // + // Make the IRP look like a send IRP. + // + + ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Write.Length ) == + FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.OutputBufferLength ) ); + ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Write.Key ) == + FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.InputBufferLength ) ); + irpSp->Parameters.Write.Key = 0; + + status = AfdSend( Irp, irpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case IRP_MJ_READ: + + // + // Make the IRP look like a receive IRP. + // + + ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Read.Length ) == + FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.OutputBufferLength ) ); + ASSERT( FIELD_OFFSET( IO_STACK_LOCATION, Parameters.Read.Key ) == + FIELD_OFFSET( IO_STACK_LOCATION, Parameters.DeviceIoControl.InputBufferLength ) ); + irpSp->Parameters.Read.Key = 0; + + status = AfdReceive( Irp, irpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case IRP_MJ_CREATE: + + status = AfdCreate( Irp, irpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + return status; + + case IRP_MJ_CLEANUP: + + status = AfdCleanup( Irp, irpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case IRP_MJ_CLOSE: + + status = AfdClose( Irp, irpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + default: + KdPrint(( "AfdDispatch: Invalid major function %lx\n", + irpSp->MajorFunction )); + Irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + return STATUS_NOT_IMPLEMENTED; + } + +} // AfdDispatch + + +NTSTATUS +AfdDispatchDeviceControl ( + IN PIRP Irp, + IN PIO_STACK_LOCATION IrpSp + ) + +/*++ + +Routine Description: + + This is the dispatch routine for AFD IOCTLs. + +Arguments: + + Irp - Pointer to I/O request packet. + + IrpSp - pointer to the stack location to use for this request. + +Return Value: + + NTSTATUS -- Indicates whether the request was successfully queued. + +--*/ + +{ + ULONG code; + ULONG request; + NTSTATUS status; +#if DBG + KIRQL oldIrql; + + oldIrql = KeGetCurrentIrql( ); +#endif + + + // + // Extract the IOCTL control code and process the request. + // + + code = IrpSp->Parameters.DeviceIoControl.IoControlCode; + request = _AFD_REQUEST(code); + + if( _AFD_BASE(code) == FSCTL_AFD_BASE && + request < NUM_AFD_IOCTLS && + AfdIoctlTable[request] == code ) { + + switch( request ) { + + case AFD_SEND: + + status = AfdSend( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_SEND_DATAGRAM: + + status = AfdSendDatagram( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_RECEIVE: + + status = AfdReceive( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_RECEIVE_DATAGRAM: + + status = AfdReceiveDatagram( Irp, IrpSp, 0, 0 ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_TRANSMIT_FILE: + + status = AfdTransmitFile( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_BIND: + + status = AfdBind( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_CONNECT: + + return AfdConnect( Irp, IrpSp ); + + case AFD_START_LISTEN: + + status = AfdStartListen( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_WAIT_FOR_LISTEN: + case AFD_WAIT_FOR_LISTEN_LIFO: + + status = AfdWaitForListen( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_ACCEPT: + + status = AfdAccept( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_PARTIAL_DISCONNECT: + + status = AfdPartialDisconnect( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_ADDRESS: + + status = AfdGetAddress( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_POLL: + + status = AfdPoll( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_QUERY_RECEIVE_INFO: + + status = AfdQueryReceiveInformation( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_QUERY_HANDLES: + + status = AfdQueryHandles( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_CONTEXT_LENGTH: + + status = AfdGetContextLength( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_CONTEXT: + + status = AfdGetContext( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_SET_CONTEXT: + + status = AfdSetContext( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_SET_INFORMATION: + + status = AfdSetInformation( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_INFORMATION: + + status = AfdGetInformation( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_SET_CONNECT_DATA: + case AFD_SET_CONNECT_OPTIONS: + case AFD_SET_DISCONNECT_DATA: + case AFD_SET_DISCONNECT_OPTIONS: + case AFD_SIZE_CONNECT_DATA: + case AFD_SIZE_CONNECT_OPTIONS: + case AFD_SIZE_DISCONNECT_DATA: + case AFD_SIZE_DISCONNECT_OPTIONS: + + status = AfdSetConnectData( Irp, IrpSp, code ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_CONNECT_DATA: + case AFD_GET_CONNECT_OPTIONS: + case AFD_GET_DISCONNECT_DATA: + case AFD_GET_DISCONNECT_OPTIONS: + + status = AfdGetConnectData( Irp, IrpSp, code ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_SUPER_ACCEPT: + + status = AfdSuperAccept( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_EVENT_SELECT : + + status = AfdEventSelect( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql() == LOW_LEVEL ); + + return status; + + case AFD_ENUM_NETWORK_EVENTS : + + status = AfdEnumNetworkEvents( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql() == LOW_LEVEL ); + + return status; + + case AFD_DEFER_ACCEPT: + + status = AfdDeferAccept( Irp, IrpSp ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_SET_QOS : + + status = AfdSetQos( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_QOS : + + status = AfdGetQos( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_NO_OPERATION : + + status = AfdNoOperation( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_VALIDATE_GROUP : + + status = AfdValidateGroup( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + + case AFD_GET_UNACCEPTED_CONNECT_DATA : + + status = AfdGetUnacceptedConnectData( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql( ) == oldIrql ); + + return status; + +#ifdef NT351 + case AFD_QUEUE_APC : + + status = AfdQueueUserApc( Irp, IrpSp ); + + Irp->IoStatus.Status = status; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + ASSERT( KeGetCurrentIrql() == LOW_LEVEL ); + + return status; +#endif // NT351 + + } + + } + + // + // If we made it this far, then the ioctl is invalid. + // + + KdPrint(( + "AfdDispatchDeviceControl: invalid IOCTL %08lX\n", + code + )); + + Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; + IoCompleteRequest( Irp, AfdPriorityBoost ); + + return STATUS_INVALID_DEVICE_REQUEST; + +} // AfdDispatchDeviceControl + |