mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
604 lines
14 KiB
604 lines
14 KiB
/*++
|
|
|
|
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
|
|
|