/*++ 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