605 lines
14 KiB
C
605 lines
14 KiB
C
/*++
|
||
|
||
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
|
||
|