dispatch.c
来自「这是一个开放源代码的与WINNT/WIN2K/WIN2003兼容的操作系统」· C语言 代码 · 共 1,574 行 · 第 1/4 页
C
1,574 行
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS TCP/IP protocol driver
* FILE: tcpip/dispatch.h
* PURPOSE: TDI dispatch routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 01/08-2000 Created
* TODO: Validate device object in all dispatch routines
*/
#include "precomp.h"
#include <pseh/pseh.h>
NTSTATUS DispPrepareIrpForCancel(
PTRANSPORT_CONTEXT Context,
PIRP Irp,
PDRIVER_CANCEL CancelRoutine)
/*
* FUNCTION: Prepare an IRP for cancellation
* ARGUMENTS:
* Context = Pointer to context information
* Irp = Pointer to an I/O request packet
* CancelRoutine = Routine to be called when I/O request is cancelled
* RETURNS:
* Status of operation
*/
{
KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IoAcquireCancelSpinLock(&OldIrql);
if (!Irp->Cancel) {
IoMarkIrpPending(Irp);
(void)IoSetCancelRoutine(Irp, CancelRoutine);
IoReleaseCancelSpinLock(OldIrql);
TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP at 0x%X can now be cancelled).\n", Irp));
return STATUS_SUCCESS;
}
/* IRP has already been cancelled */
IoReleaseCancelSpinLock(OldIrql);
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
TI_DbgPrint(DEBUG_IRP, ("Leaving (IRP was already cancelled).\n"));
return IRPFinish(Irp, STATUS_CANCELLED);
}
VOID DispCancelComplete(
PVOID Context)
/*
* FUNCTION: Completes a cancel request
* ARGUMENTS:
* Context = Pointer to context information (FILE_OBJECT)
*/
{
/*KIRQL OldIrql;*/
PFILE_OBJECT FileObject;
PTRANSPORT_CONTEXT TranContext;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
FileObject = (PFILE_OBJECT)Context;
TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
/* Set the cleanup event */
KeSetEvent(&TranContext->CleanupEvent, 0, FALSE);
/* We are expected to release the cancel spin lock */
/*IoReleaseCancelSpinLock(OldIrql);*/
TI_DbgPrint(DEBUG_IRP, ("Leaving.\n"));
}
VOID DispDataRequestComplete(
PVOID Context,
NTSTATUS Status,
ULONG Count)
/*
* FUNCTION: Completes a send/receive IRP
* ARGUMENTS:
* Context = Pointer to context information (IRP)
* Status = Status of the request
* Count = Number of bytes sent or received
*/
{
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT TranContext;
KIRQL OldIrql;
TI_DbgPrint(DEBUG_IRP, ("Called for irp %x (%x, %d).\n",
Context, Status, Count));
Irp = Context;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
IoAcquireCancelSpinLock(&OldIrql);
(void)IoSetCancelRoutine(Irp, NULL);
if (Irp->Cancel || TranContext->CancelIrps) {
/* The IRP has been cancelled */
TI_DbgPrint(DEBUG_IRP, ("IRP is cancelled.\n"));
Status = STATUS_CANCELLED;
Count = 0;
}
IoReleaseCancelSpinLock(OldIrql);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = Count;
TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Status = %x\n",
Irp->IoStatus.Status));
TI_DbgPrint(MID_TRACE, ("Irp->IoStatus.Information = %d\n",
Irp->IoStatus.Information));
TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));
IRPFinish(Irp, Irp->IoStatus.Status);
TI_DbgPrint(DEBUG_IRP, ("Done Completing IRP\n"));
}
typedef struct _DISCONNECT_TYPE {
UINT Type;
PVOID Context;
PIRP Irp;
PFILE_OBJECT FileObject;
} DISCONNECT_TYPE, *PDISCONNECT_TYPE;
VOID DispDoDisconnect( PVOID Data ) {
PDISCONNECT_TYPE DisType = (PDISCONNECT_TYPE)Data;
TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect\n"));
TCPDisconnect
( DisType->Context,
DisType->Type,
NULL,
NULL,
DispDataRequestComplete,
DisType->Irp );
TI_DbgPrint(DEBUG_IRP, ("PostCancel: DoDisconnect done\n"));
DispDataRequestComplete(DisType->Irp, STATUS_CANCELLED, 0);
DispCancelComplete(DisType->FileObject);
}
VOID NTAPI DispCancelRequest(
PDEVICE_OBJECT Device,
PIRP Irp)
/*
* FUNCTION: Cancels an IRP
* ARGUMENTS:
* Device = Pointer to device object
* Irp = Pointer to an I/O request packet
*/
{
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT TranContext;
PFILE_OBJECT FileObject;
UCHAR MinorFunction;
DISCONNECT_TYPE DisType;
PVOID WorkItem;
/*NTSTATUS Status = STATUS_SUCCESS;*/
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpSp->FileObject;
TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
MinorFunction = IrpSp->MinorFunction;
TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X) MinorFunction (0x%X) IrpSp (0x%X).\n", Irp, MinorFunction, IrpSp));
Irp->IoStatus.Status = STATUS_PENDING;
#ifdef DBG
if (!Irp->Cancel)
TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
#endif
/* Try canceling the request */
switch(MinorFunction) {
case TDI_SEND:
case TDI_RECEIVE:
DisType.Type = TDI_DISCONNECT_RELEASE |
((MinorFunction == TDI_RECEIVE) ? TDI_DISCONNECT_ABORT : 0);
DisType.Context = TranContext->Handle.ConnectionContext;
DisType.Irp = Irp;
DisType.FileObject = FileObject;
TCPRemoveIRP( TranContext->Handle.ConnectionContext, Irp );
if( !ChewCreate( &WorkItem, sizeof(DISCONNECT_TYPE),
DispDoDisconnect, &DisType ) )
ASSERT(0);
break;
case TDI_SEND_DATAGRAM:
Irp->IoStatus.Status = STATUS_CANCELLED;
if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
TI_DbgPrint(MIN_TRACE, ("TDI_SEND_DATAGRAM, but no address file.\n"));
break;
}
/*DGCancelSendRequest(TranContext->Handle.AddressHandle, Irp);*/
break;
case TDI_RECEIVE_DATAGRAM:
Irp->IoStatus.Status = STATUS_CANCELLED;
if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
TI_DbgPrint(MIN_TRACE, ("TDI_RECEIVE_DATAGRAM, but no address file.\n"));
break;
}
/*DGCancelReceiveRequest(TranContext->Handle.AddressHandle, Irp);*/
break;
default:
TI_DbgPrint(MIN_TRACE, ("Unknown IRP. MinorFunction (0x%X).\n", MinorFunction));
break;
}
if( Irp->IoStatus.Status == STATUS_PENDING )
IoMarkIrpPending(Irp);
IoReleaseCancelSpinLock(Irp->CancelIrql);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
VOID NTAPI DispCancelListenRequest(
PDEVICE_OBJECT Device,
PIRP Irp)
/*
* FUNCTION: Cancels a listen IRP
* ARGUMENTS:
* Device = Pointer to device object
* Irp = Pointer to an I/O request packet
*/
{
PIO_STACK_LOCATION IrpSp;
PTRANSPORT_CONTEXT TranContext;
PFILE_OBJECT FileObject;
PCONNECTION_ENDPOINT Connection;
/*NTSTATUS Status = STATUS_SUCCESS;*/
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
FileObject = IrpSp->FileObject;
TranContext = (PTRANSPORT_CONTEXT)FileObject->FsContext;
ASSERT( TDI_LISTEN == IrpSp->MinorFunction);
TI_DbgPrint(DEBUG_IRP, ("IRP at (0x%X).\n", Irp));
#ifdef DBG
if (!Irp->Cancel)
TI_DbgPrint(MIN_TRACE, ("Irp->Cancel is FALSE, should be TRUE.\n"));
#endif
/* Try canceling the request */
Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
TCPAbortListenForSocket(
Connection->AddressFile->Listener,
Connection );
IoReleaseCancelSpinLock(Irp->CancelIrql);
DispDataRequestComplete(Irp, STATUS_CANCELLED, 0);
DispCancelComplete(FileObject);
TI_DbgPrint(MAX_TRACE, ("Leaving.\n"));
}
NTSTATUS DispTdiAccept(
PIRP Irp)
/*
* FUNCTION: TDI_ACCEPT handler
* ARGUMENTS:
* Irp = Pointer to an I/O request packet
* RETURNS:
* Status of operation
*/
{
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
return STATUS_NOT_IMPLEMENTED;
}
NTSTATUS DispTdiAssociateAddress(
PIRP Irp)
/*
* FUNCTION: TDI_ASSOCIATE_ADDRESS handler
* ARGUMENTS:
* Irp = Pointer to an I/O request packet
* RETURNS:
* Status of operation
*/
{
PTDI_REQUEST_KERNEL_ASSOCIATE Parameters;
PTRANSPORT_CONTEXT TranContext;
PIO_STACK_LOCATION IrpSp;
PCONNECTION_ENDPOINT Connection;
PFILE_OBJECT FileObject;
PADDRESS_FILE AddrFile = NULL;
NTSTATUS Status;
TI_DbgPrint(DEBUG_IRP, ("Called.\n"));
IrpSp = IoGetCurrentIrpStackLocation(Irp);
/* Get associated connection endpoint file object. Quit if none exists */
TranContext = IrpSp->FileObject->FsContext;
if (!TranContext) {
TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
return STATUS_INVALID_PARAMETER;
}
Connection = (PCONNECTION_ENDPOINT)TranContext->Handle.ConnectionContext;
if (!Connection) {
TI_DbgPrint(MID_TRACE, ("No connection endpoint file object.\n"));
return STATUS_INVALID_PARAMETER;
}
if (Connection->AddressFile) {
TI_DbgPrint(MID_TRACE, ("An address file is already asscociated.\n"));
return STATUS_INVALID_PARAMETER;
}
Parameters = (PTDI_REQUEST_KERNEL_ASSOCIATE)&IrpSp->Parameters;
Status = ObReferenceObjectByHandle(
Parameters->AddressHandle,
0,
IoFileObjectType,
KernelMode,
(PVOID*)&FileObject,
NULL);
if (!NT_SUCCESS(Status)) {
TI_DbgPrint(MID_TRACE, ("Bad address file object handle (0x%X): %x.\n",
Parameters->AddressHandle, Status));
return STATUS_INVALID_PARAMETER;
}
if (FileObject->FsContext2 != (PVOID)TDI_TRANSPORT_ADDRESS_FILE) {
ObDereferenceObject(FileObject);
TI_DbgPrint(MID_TRACE, ("Bad address file object. Magic (0x%X).\n",
FileObject->FsContext2));
return STATUS_INVALID_PARAMETER;
}
/* Get associated address file object. Quit if none exists */
TranContext = FileObject->FsContext;
if (!TranContext) {
ObDereferenceObject(FileObject);
TI_DbgPrint(MID_TRACE, ("Bad transport context.\n"));
return STATUS_INVALID_PARAMETER;
}
AddrFile = (PADDRESS_FILE)TranContext->Handle.AddressHandle;
if (!AddrFile) {
ObDereferenceObject(FileObject);
TI_DbgPrint(MID_TRACE, ("No address file object.\n"));
return STATUS_INVALID_PARAMETER;
}
Connection->AddressFile = AddrFile;
/* Add connection endpoint to the address file */
AddrFile->Connection = Connection;
/* FIXME: Maybe do this in DispTdiDisassociateAddress() instead? */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?