dispatch.c

来自「winNT技术操作系统,国外开放的原代码和LIUX一样」· 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 + -
显示快捷键?