⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 read.c

📁 vc++网络程序设计实例详解 人民邮电出版社3-4章源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

Copyright (c) 1990-2000 Microsoft Corporation

Module Name:

    Read.c

Abstract:


Author:


Environment:

    Kernel mode only.

Notes:


Future:



Revision History:

    Updated for Windows 2000 - Eliyas Yakub June, 1999

--*/

#include "ntddk.h"
#include "ndis.h"
#include "packet.h"


NTSTATUS
PacketRead(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the dispatch routine for read requests.

Arguments:

    DeviceObject - Pointer to the device object.

    Irp - Pointer to the request packet.

Return Value:

    NT status code.
--*/

{
    POPEN_INSTANCE      open;
    PNDIS_PACKET        pPacket;
    NDIS_STATUS         status;
    NTSTATUS            ntStatus;
    PIO_STACK_LOCATION  irpSp;

    DebugPrint(("Read\n"));

    open = DeviceObject->DeviceExtension;

    //
    // Check to see whether you are still bound to the adapter
    //

    IoIncrement(open);
    
    if(!open->Bound)
    {
        ntStatus = STATUS_DEVICE_NOT_READY;
        goto ERROR;
    }
    
    irpSp = IoGetCurrentIrpStackLocation(Irp);

    //
    //  See if the buffer is at least big enough to hold the
    //  ethernet header
    //
    if (irpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) {

        ntStatus = STATUS_BUFFER_TOO_SMALL;
        goto ERROR;
    }

    //
    // Try to get a packet from our list of free ones. 
    //

    NdisAllocatePacket(
        &status,
        &pPacket,
        open->PacketPool
        );

    if (status != NDIS_STATUS_SUCCESS) {
        DebugPrint(("Packet: Read- No free packets\n"));

        ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        goto ERROR;
    }

    //
    //  Get a pointer to the packet itself.
    //

    RESERVED(pPacket)->Irp=Irp;
    RESERVED(pPacket)->pMdl=NULL;

    IoMarkIrpPending(Irp);

    //
    // Set the cancel routine so that we can cancel the requests
    // pending in the queue if the application terminates.
    //
    
    IoSetCancelRoutine(Irp, PacketCancelRoutine);

    //
    //  Put this packet in a list of pending reads.
    //  The PacketReceiveIndicate or PacketReceivePacket handler will 
    //  attempt to remove packets from this list.
    //
    
    ExInterlockedInsertTailList(
        &open->RcvList,
        &RESERVED(pPacket)->ListElement,
        &open->RcvQSpinLock);

  
    return STATUS_PENDING;
    
ERROR:
    Irp->IoStatus.Status = ntStatus;
    IoCompleteRequest (Irp, IO_NO_INCREMENT);
    IoDecrement(open);
    return ntStatus;

}





NDIS_STATUS
PacketReceiveIndicate (
    IN NDIS_HANDLE ProtocolBindingContext,
    IN NDIS_HANDLE MacReceiveContext,
    IN PVOID       HeaderBuffer,
    IN UINT        HeaderBufferSize,
    IN PVOID       LookAheadBuffer,
    IN UINT        LookaheadBufferSize,
    IN UINT        PacketSize
    )
/*++

Routine Description:

    PacketReceiveIndicate is called with a pointer to a 
    lookahead buffer. If this buffer contains less than 
    the full, received network packet, it 
    calls NdisTransferData with a protocol-allocated packet 
    descriptor specifying protocol-allocated buffer(s) to obtain 
    the remainder of the received packet. 

Arguments:


Return Value:


--*/
{
    POPEN_INSTANCE      open;
    PIO_STACK_LOCATION  irpSp;
    PIRP                irp;
    PLIST_ENTRY         packetListEntry;
    PNDIS_PACKET        pPacket;
    ULONG               sizeToTransfer;
    NDIS_STATUS         status;
    UINT                bytesTransfered = 0;
    ULONG               bufferLength;
    PPACKET_RESERVED    reserved;
    PMDL                pMdl;

    DebugPrint(("ReceiveIndicate\n"));

    open= (POPEN_INSTANCE)ProtocolBindingContext;

    if (HeaderBufferSize > ETHERNET_HEADER_LENGTH) {

        return NDIS_STATUS_SUCCESS;
    }

    //
    //  See if there are any pending read that we can satisfy
    //
    packetListEntry=ExInterlockedRemoveHeadList(
                        &open->RcvList,
                        &open->RcvQSpinLock
                        );

    if (packetListEntry == NULL) {
        DebugPrint(("No pending read, dropping packets\n"));
        return NDIS_STATUS_NOT_ACCEPTED;
    }


    reserved=CONTAINING_RECORD(packetListEntry,PACKET_RESERVED,ListElement);
    pPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

    irp=RESERVED(pPacket)->Irp;
    irpSp = IoGetCurrentIrpStackLocation(irp);

    //
    // We don't have to worry about the situation where the IRP is cancelled
    // after we remove it from the queue and before we reset the cancel
    // routine because the cancel routine has been coded to cancel an IRP
    // only if it's in the queue.
    //
    
    IoSetCancelRoutine(irp, NULL);
    
    //
    //  This is the length of our partial MDL
    //
    bufferLength=irpSp->Parameters.Read.Length-ETHERNET_HEADER_LENGTH;

    //
    //  Find out how much to transfer
    //
    sizeToTransfer = (PacketSize < bufferLength) ?
                       PacketSize : bufferLength;

    //
    //  copy the ethernet header into the actual readbuffer
    //
    NdisMoveMappedMemory(
        MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority),
        HeaderBuffer,
        HeaderBufferSize
        );

    //
    //  Allocate an MDL to map the portion of the buffer following the
    //  header
    //
    pMdl=IoAllocateMdl(
              MmGetMdlVirtualAddress(irp->MdlAddress),
              MmGetMdlByteCount(irp->MdlAddress),
              FALSE,
              FALSE,
              NULL
              );


    if (pMdl == NULL) {
        DebugPrint(("Packet: Read-Failed to allocate Mdl\n"));
        status = NDIS_STATUS_RESOURCES;
        goto ERROR;
    }

    //
    //  Build the mdl to point to the the portion of the buffer following
    //  the header
    //
    IoBuildPartialMdl(
        irp->MdlAddress,
        pMdl,
        ((PUCHAR)MmGetMdlVirtualAddress(irp->MdlAddress))+ETHERNET_HEADER_LENGTH,
        0
        );

    //
    //  Clear the next link in the new MDL
    //

    pMdl->Next=NULL;

    RESERVED(pPacket)->pMdl=pMdl;

    //
    //  Attach our partial MDL to the packet
    //

    NdisChainBufferAtFront(pPacket,pMdl);

    //
    //  Call the Mac to transfer the packet
    //

    NdisTransferData(
        &status,
        open->AdapterHandle,
        MacReceiveContext,
        0,
        sizeToTransfer,
        pPacket,
        &bytesTransfered);
    if (status == NDIS_STATUS_PENDING) {
        return NDIS_STATUS_SUCCESS;
    }

ERROR:
    
    //
    //  If it didn't pend, call the completeion routine now
    //
    PacketTransferDataComplete(
                                open,
                                pPacket,
                                status,
                                bytesTransfered);
    return NDIS_STATUS_SUCCESS;

}



VOID
PacketTransferDataComplete (
    IN NDIS_HANDLE   ProtocolBindingContext,
    IN PNDIS_PACKET  pPacket,
    IN NDIS_STATUS   Status,
    IN UINT          BytesTransfered
    )
/*++

Routine Description:

    This is a required function unless the protocol binds itself 
    exclusively to underlying NIC driver(s) that indicate packets 
    with NdisMIndicateReceivePacket. ProtocolTransferDataComplete 
    is called when a previous call to NdisTransferData returned 
    NDIS_STATUS_PENDING and the remaining data has been copied 
    into the protocol-supplied buffers chained to a given packet 
    descriptor. 

Arguments:


Return Value:


--*/

{
    PIO_STACK_LOCATION   irpSp;
    POPEN_INSTANCE       open;
    PIRP                 irp;
    PMDL                 pMdl;

    DebugPrint(("Packet: TransferDataComplete\n"));

    open= (POPEN_INSTANCE)ProtocolBindingContext;

    irp=RESERVED(pPacket)->Irp;

⌨️ 快捷键说明

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