dispatch.c

来自「一个类似windows」· C语言 代码 · 共 1,568 行 · 第 1/4 页

C
1,568
字号
        (PTDI_IND_CHAINED_RECEIVE_EXPEDITED)Parameters->EventHandler;
      AddrFile->ChainedReceiveExpeditedHandlerContext    = Parameters->EventContext;
      AddrFile->RegisteredChainedReceiveExpeditedHandler = TRUE;
    }
    break;

  default:
    TI_DbgPrint(MIN_TRACE, ("Unknown event type (0x%X).\n",
      Parameters->EventType));

    Status = STATUS_INVALID_PARAMETER;
  }

  TcpipReleaseSpinLock(&AddrFile->Lock, OldIrql);

  return Status;
}


NTSTATUS DispTdiSetInformation(
    PIRP Irp)
/*
 * FUNCTION: TDI_SET_INFORMATION handler
 * ARGUMENTS:
 *     Irp = Pointer to an I/O request packet
 * RETURNS:
 *     Status of operation
 */
{
    TI_DbgPrint(DEBUG_IRP, ("Called.\n"));

	return STATUS_NOT_IMPLEMENTED;
}


VOID DispTdiQueryInformationExComplete(
    PVOID Context,
    ULONG Status,
    UINT ByteCount)
/*
 * FUNCTION: Completes a TDI QueryInformationEx request
 * ARGUMENTS:
 *     Context   = Pointer to the IRP for the request
 *     Status    = TDI status of the request
 *     ByteCount = Number of bytes returned in output buffer
 */
{
    PTI_QUERY_CONTEXT QueryContext;
    UINT Count = 0;

    QueryContext = (PTI_QUERY_CONTEXT)Context;
    if (NT_SUCCESS(Status)) {
        Count = CopyBufferToBufferChain(
            QueryContext->InputMdl,
            FIELD_OFFSET(TCP_REQUEST_QUERY_INFORMATION_EX, Context),
            (PCHAR)&QueryContext->QueryInfo.Context,
            CONTEXT_SIZE);
    }

    MmUnlockPages(QueryContext->InputMdl);
    IoFreeMdl(QueryContext->InputMdl);
    if( QueryContext->OutputMdl ) {
	MmUnlockPages(QueryContext->OutputMdl);
	IoFreeMdl(QueryContext->OutputMdl);
    }

    QueryContext->Irp->IoStatus.Information = ByteCount;
    QueryContext->Irp->IoStatus.Status      = Status;

    ExFreePool(QueryContext);
}


NTSTATUS DispTdiQueryInformationEx(
    PIRP Irp,
    PIO_STACK_LOCATION IrpSp)
/*
 * FUNCTION: TDI QueryInformationEx handler
 * ARGUMENTS:
 *     Irp   = Pointer to I/O request packet
 *     IrpSp = Pointer to current stack location of Irp
 * RETURNS:
 *     Status of operation
 */
{
    PTCP_REQUEST_QUERY_INFORMATION_EX InputBuffer;
    PTRANSPORT_CONTEXT TranContext;
    PTI_QUERY_CONTEXT QueryContext;
    PVOID OutputBuffer;
    TDI_REQUEST Request;
    UINT Size;
    UINT InputBufferLength;
    UINT OutputBufferLength;
    BOOLEAN InputMdlLocked  = FALSE;
    BOOLEAN OutputMdlLocked = FALSE;
    PMDL InputMdl           = NULL;
    PMDL OutputMdl          = NULL;
    NTSTATUS Status         = STATUS_SUCCESS;

    TI_DbgPrint(DEBUG_IRP, ("Called.\n"));

    TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;

    switch ((ULONG)IrpSp->FileObject->FsContext2) {
    case TDI_TRANSPORT_ADDRESS_FILE:
        Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
        break;

    case TDI_CONNECTION_FILE:
        Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
        break;

    case TDI_CONTROL_CHANNEL_FILE:
        Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
        break;

    default:
        TI_DbgPrint(MIN_TRACE, ("Invalid transport context\n"));
        return STATUS_INVALID_PARAMETER;
    }

    InputBufferLength  = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
    OutputBufferLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;

    /* Validate parameters */
    if ((InputBufferLength == sizeof(TCP_REQUEST_QUERY_INFORMATION_EX)) &&
        (OutputBufferLength != 0)) {

        InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
            IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
        OutputBuffer = Irp->UserBuffer;

        QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
        if (QueryContext) {
	    _SEH_TRY {
                InputMdl = IoAllocateMdl(InputBuffer,
                    sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
                    FALSE, TRUE, NULL);

                OutputMdl = IoAllocateMdl(OutputBuffer,
                    OutputBufferLength, FALSE, TRUE, NULL);

                if (InputMdl && OutputMdl) {

                    MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
                        IoModifyAccess);

                    InputMdlLocked = TRUE;

                    MmProbeAndLockPages(OutputMdl, Irp->RequestorMode,
                        IoWriteAccess);

                    OutputMdlLocked = TRUE;

                    RtlCopyMemory(&QueryContext->QueryInfo,
                        InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));
                } else
                    Status = STATUS_INSUFFICIENT_RESOURCES;
            } _SEH_HANDLE {
                Status = _SEH_GetExceptionCode();
            } _SEH_END;

            if (NT_SUCCESS(Status)) {
                Size = MmGetMdlByteCount(OutputMdl);

                QueryContext->Irp       = Irp;
                QueryContext->InputMdl  = InputMdl;
                QueryContext->OutputMdl = OutputMdl;

                Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
                Request.RequestContext      = QueryContext;
                Status = InfoTdiQueryInformationEx(&Request,
                    &QueryContext->QueryInfo.ID, OutputMdl,
                    &Size, &QueryContext->QueryInfo.Context);
                DispTdiQueryInformationExComplete(QueryContext, Status, Size);

                TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));

                return Status;
            }

            /* An error occurred if we get here */

            if (InputMdl) {
                if (InputMdlLocked)
                    MmUnlockPages(InputMdl);
                IoFreeMdl(InputMdl);
            }

            if (OutputMdl) {
                if (OutputMdlLocked)
                    MmUnlockPages(OutputMdl);
                IoFreeMdl(OutputMdl);
            }

            ExFreePool(QueryContext);
        } else
            Status = STATUS_INSUFFICIENT_RESOURCES;
    } else if( InputBufferLength ==
	       sizeof(TCP_REQUEST_QUERY_INFORMATION_EX) ) {
	/* Handle the case where the user is probing the buffer for length */
	TI_DbgPrint(MAX_TRACE, ("InputBufferLength %d OutputBufferLength %d\n",
				InputBufferLength, OutputBufferLength));
        InputBuffer = (PTCP_REQUEST_QUERY_INFORMATION_EX)
            IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;

	Size = 0;

        QueryContext = ExAllocatePool(NonPagedPool, sizeof(TI_QUERY_CONTEXT));
        if (!QueryContext) return STATUS_INSUFFICIENT_RESOURCES;

	_SEH_TRY {
	    InputMdl = IoAllocateMdl(InputBuffer,
				     sizeof(TCP_REQUEST_QUERY_INFORMATION_EX),
				     FALSE, TRUE, NULL);

	    MmProbeAndLockPages(InputMdl, Irp->RequestorMode,
				IoModifyAccess);

	    InputMdlLocked = TRUE;
	    Status = STATUS_SUCCESS;
	} _SEH_HANDLE {
	    TI_DbgPrint(MAX_TRACE, ("Failed to acquire client buffer\n"));
	    Status = _SEH_GetExceptionCode();
	} _SEH_END;

	if( !NT_SUCCESS(Status) || !InputMdl ) {
	    if( InputMdl ) IoFreeMdl( InputMdl );
	    ExFreePool(QueryContext);
	    return Status;
	}

	RtlCopyMemory(&QueryContext->QueryInfo,
		      InputBuffer, sizeof(TCP_REQUEST_QUERY_INFORMATION_EX));

	QueryContext->Irp       = Irp;
	QueryContext->InputMdl  = InputMdl;
	QueryContext->OutputMdl = NULL;

	Request.RequestNotifyObject = DispTdiQueryInformationExComplete;
	Request.RequestContext      = QueryContext;
	Status = InfoTdiQueryInformationEx(&Request,
					   &QueryContext->QueryInfo.ID,
					   NULL,
					   &Size,
					   &QueryContext->QueryInfo.Context);
	DispTdiQueryInformationExComplete(QueryContext, Status, Size);
	TI_DbgPrint(MAX_TRACE, ("Leaving. Status = (0x%X)\n", Status));
    } else Status = STATUS_INVALID_PARAMETER;

    TI_DbgPrint(MIN_TRACE, ("Leaving. Status = (0x%X)\n", Status));

    return Status;
}


NTSTATUS DispTdiSetInformationEx(
    PIRP Irp,
    PIO_STACK_LOCATION IrpSp)
/*
 * FUNCTION: TDI SetInformationEx handler
 * ARGUMENTS:
 *     Irp   = Pointer to I/O request packet
 *     IrpSp = Pointer to current stack location of Irp
 * RETURNS:
 *     Status of operation
 */
{
    PTRANSPORT_CONTEXT TranContext;
    PTCP_REQUEST_SET_INFORMATION_EX Info;
    TDI_REQUEST Request;
    TDI_STATUS Status;
    KIRQL OldIrql;

    TI_DbgPrint(DEBUG_IRP, ("Called.\n"));

    TranContext = (PTRANSPORT_CONTEXT)IrpSp->FileObject->FsContext;
    Info        = (PTCP_REQUEST_SET_INFORMATION_EX)Irp->AssociatedIrp.SystemBuffer;

    switch ((ULONG)IrpSp->FileObject->FsContext2) {
    case TDI_TRANSPORT_ADDRESS_FILE:
        Request.Handle.AddressHandle = TranContext->Handle.AddressHandle;
        break;

    case TDI_CONNECTION_FILE:
        Request.Handle.ConnectionContext = TranContext->Handle.ConnectionContext;
        break;

    case TDI_CONTROL_CHANNEL_FILE:
        Request.Handle.ControlChannel = TranContext->Handle.ControlChannel;
        break;

    default:
        Irp->IoStatus.Status      = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;

        TI_DbgPrint(DEBUG_IRP, ("Completing IRP at (0x%X).\n", Irp));

        return IRPFinish(Irp, STATUS_INVALID_PARAMETER);
    }

    Status = DispPrepareIrpForCancel(TranContext, Irp, NULL);
    if (NT_SUCCESS(Status)) {
        Request.RequestNotifyObject = DispDataRequestComplete;
        Request.RequestContext      = Irp;

        Status = InfoTdiSetInformationEx(&Request, &Info->ID,
            &Info->Buffer, Info->BufferSize);

        if (Status != STATUS_PENDING) {
            IoAcquireCancelSpinLock(&OldIrql);
            (void)IoSetCancelRoutine(Irp, NULL);
            IoReleaseCancelSpinLock(OldIrql);
        }
    }

    return Status;
}

/* TODO: Support multiple addresses per interface.
 * For now just set the nte context to the interface index.
 *
 * Later on, create an NTE context and NTE instance
 */

NTSTATUS DispTdiSetIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
    NTSTATUS Status = STATUS_DEVICE_DOES_NOT_EXIST;
    PIP_SET_ADDRESS IpAddrChange =
        (PIP_SET_ADDRESS)Irp->AssociatedIrp.SystemBuffer;
    IF_LIST_ITER(IF);

    TI_DbgPrint(MID_TRACE,("Setting IP Address for adapter %d\n", 
			   IpAddrChange->NteIndex));

    ForEachInterface(IF) {
	TI_DbgPrint(MID_TRACE,("Looking at adapter %d\n", IF->Index));

        if( IF->Unicast.Address.IPv4Address == IpAddrChange->Address ) {
            Status = STATUS_DUPLICATE_OBJECTID;
            break;
        }
        if( IF->Index == IpAddrChange->NteIndex ) {
            IPRemoveInterfaceRoute( IF );

            IF->Unicast.Type = IP_ADDRESS_V4;
            IF->Unicast.Address.IPv4Address = IpAddrChange->Address;
            IF->Netmask.Type = IP_ADDRESS_V4;
            IF->Netmask.Address.IPv4Address = IpAddrChange->Netmask;
	    IF->Broadcast.Address.IPv4Address =
		IF->Unicast.Address.IPv4Address |
		~IF->Netmask.Address.IPv4Address;

            TI_DbgPrint(MID_TRACE,("New Unicast Address: %x\n",
                                   IF->Unicast.Address.IPv4Address));
            TI_DbgPrint(MID_TRACE,("New Netmask        : %x\n",
                                   IF->Netmask.Address.IPv4Address));

            IPAddInterfaceRoute( IF );

            IpAddrChange->Address = IF->Index;
            Status = STATUS_SUCCESS;
            Irp->IoStatus.Information = IF->Index;
            break;
        }
    } EndFor(IF);

    Irp->IoStatus.Status = Status;
    return Status;
}

NTSTATUS DispTdiDeleteIPAddress( PIRP Irp, PIO_STACK_LOCATION IrpSp ) {
    NTSTATUS Status = STATUS_UNSUCCESSFUL;
    PUSHORT NteIndex = Irp->AssociatedIrp.SystemBuffer;
    IF_LIST_ITER(IF);

    ForEachInterface(IF) {
        if( IF->Index == *NteIndex ) {
            IPRemoveInterfaceRoute( IF );
            IF->Unicast.Type = IP_ADDRESS_V4;
            IF->Unicast.Address.IPv4Address = 0;
            IF->Netmask.Type = IP_ADDRESS_V4;
            IF->Netmask.Address.IPv4Address = 0;
            Status = STATUS_SUCCESS;
        }
    } EndFor(IF);

    Irp->IoStatus.Status = Status;
    return Status;
}

/* EOF */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?