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

📄 read.c

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

    pMdl=RESERVED(pPacket)->pMdl;

    
    //
    //  Free the partial MDL that we allocated
    //
    if(pMdl)
        IoFreeMdl(pMdl);

    //
    //  Put the packet on the free queue
    //
    NdisFreePacket(pPacket);

    if(Status == NDIS_STATUS_SUCCESS)
    {
        irp->IoStatus.Status = STATUS_SUCCESS;
        irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH;
    } else {
    
        irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
        irp->IoStatus.Information = 0;
    }

    DebugPrint(("BytesTransfered:%d\n", irp->IoStatus.Information));

    IoCompleteRequest(irp, IO_NO_INCREMENT);

    IoDecrement(open);
    return;


}

VOID
PacketReceiveComplete(
    IN NDIS_HANDLE  ProtocolBindingContext
    )
/*++

Routine Description:

    This is a required function. PacketReceiveComplete 
    is called to indicate that any received packets previously 
    indicated to PacketReceivePacket can now be postprocessed. 
    
Arguments:


Return Value:


--*/
{
    return;
}

INT
PacketReceivePacket(
    IN    NDIS_HANDLE         ProtocolBindingContext,
    IN    PNDIS_PACKET        Packet
    )
/*++

Routine Description:

    ReceivePacket handler. Called up by the miniport below 
    when it supports NDIS 4.0 style receives.
    A ProtocolReceivePacket function should be provided if 
    the protocol driver might be bound to a NIC driver that 
    indicates an array of one or more packets by calling 
    NdisMIndicateReceivePacket. 

Arguments:

    ProtocolBindingContext    Pointer to our adapter structure.
    Packet - Pointer to the packet

Return Value:

    == 0 -> We are done with the packet
    != 0 -> We will keep the packet and call NdisReturnPackets() 
            this many times when done.
--*/
{
    UINT                bytesTransfered = 0;
    POPEN_INSTANCE      open;
    PIRP                irp;
    PNDIS_PACKET        myPacket;
    PLIST_ENTRY         packetListEntry;
    ULONG               bufferLength;
    PPACKET_RESERVED    reserved;
    PIO_STACK_LOCATION  irpSp;
    PMDL                mdl;
    NTSTATUS            status = STATUS_SUCCESS;

    DebugPrint(("PacketReceivePacket\n"));

    open= (POPEN_INSTANCE)ProtocolBindingContext;

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

    if (packetListEntry == NULL) {
        //
        // No pending reads so just the dropping the packet
        // on the floor.
        //
        DebugPrint(("No pending read, dropping packets\n"));
        return 0;
    }


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

    irp = RESERVED(myPacket)->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);

    //
    // Following block of code locks the destination packet
    // MDLs in a safe manner. This is a temporary workaround
    // for NdisCopyFromPacketToPacket that currently doesn't use
    // safe functions to lock pages of MDL. This is required to
    // prevent system from bugchecking under low memory resources.
    //
    {
        PVOID           virtualAddress;
        PNDIS_BUFFER    firstBuffer, nextBuffer;
        ULONG           totalLength;

        NdisQueryPacket(Packet, NULL, NULL, &firstBuffer, &totalLength);
        while( firstBuffer != NULL)
        {
            NdisQueryBufferSafe(firstBuffer, &virtualAddress, 
                                    &totalLength, NormalPagePriority );
            if(!virtualAddress) {
                //
                // System is running low on memory resources. 
                // So fail the read.
                // 
                status = STATUS_INSUFFICIENT_RESOURCES;
                goto CleanExit;
            }
            NdisGetNextBuffer(firstBuffer,  &nextBuffer);
            firstBuffer = nextBuffer;
        }
    }
    
    //
    //
    //  Attach the actual MDL to the packet
    //

    NdisChainBufferAtFront(myPacket, irp->MdlAddress);  

    bufferLength=irpSp->Parameters.Read.Length;

    NdisCopyFromPacketToPacket(myPacket, 0, bufferLength, Packet, 0, 
                                               &bytesTransfered);    

CleanExit:
    //                                 
    //  Put the packet on the free queue
    //

    NdisFreePacket(myPacket);

    irp->IoStatus.Status = status;
    irp->IoStatus.Information = bytesTransfered;
    IoCompleteRequest(irp, IO_NO_INCREMENT);
    DebugPrint(("BytesTransfered:%d\n", bytesTransfered));
    IoDecrement(open);

    return 0;
}


VOID
PacketCancelRoutine (
    IN PDEVICE_OBJECT   DeviceObject,
    IN PIRP             Irp
    )

/*++

Routine Description:

    The cancel routine. It will remove the IRP from the queue 
    and will complete it. The cancel spin lock is already acquired 
    when this routine is called.

Arguments:

    DeviceObject - pointer to the device object.
    
    Irp - pointer to the IRP to be cancelled.
    
    
Return Value:

    VOID.

--*/
{

    POPEN_INSTANCE      open = DeviceObject->DeviceExtension; 
    KIRQL               oldIrql;
    PIRP                irpToComplete = NULL;
    PLIST_ENTRY         thisEntry, listHead;
    PIRP                pendingIrp;
    PNDIS_PACKET        myPacket = NULL;
    PPACKET_RESERVED    reserved;
    PMDL                mdl;

    //
    // Don't assume that the IRP being cancelled is in the queue.
    // Only complete the IRP if it IS in the queue.
    //
    //
    // Must acquire the local spinlock before releasing 
    // the global cancel spinlock
    //
    DebugPrint(("PacketCancelRoutine\n"));

    oldIrql = Irp->CancelIrql;

    //
    // One should not intermix KeAcquireSpinLock(AtDpcLevel) 
    // and ExInterlocked...List() functions on the same spinlock if the
    // routines that use the lock run at IRQL > DISPATCH_LEVEL.
    // After acquiring the lock using Ke function, if we got interrupted
    // and entered into an ISR and tried to manipulate the list using
    // ExInterlocked...List function with the same lock, we deadlock.
    // In this sample we can safely do that because none of our routines 
    // will be called at IRQL > DISPATCH_LEVEL.
    //
    
    KeAcquireSpinLockAtDpcLevel(&open->RcvQSpinLock);

    IoReleaseCancelSpinLock( KeGetCurrentIrql() );

    //
    // Remove the IRP from the queue
    //
  
    listHead = &open->RcvList;
    
    for(thisEntry = listHead->Flink; 
        thisEntry != listHead;
        thisEntry = thisEntry->Flink)
    {

        reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
        myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);
        pendingIrp = RESERVED(myPacket)->Irp;

        if (pendingIrp == Irp) 
        {
                RemoveEntryList(thisEntry);
                irpToComplete = pendingIrp;
                break;
        }
      
    }
    
    //
    // Release the queue spinlock
    //

    KeReleaseSpinLock(&open->RcvQSpinLock, oldIrql);

    //
    // Complete the IRP with status canclled
    //
    
    if(irpToComplete) {
    
        DebugPrint(("Cancelling IRP\n"));

        ASSERT(myPacket);       

        //
        //  Put the packet on the free queue
        //
        NdisFreePacket(myPacket);

        irpToComplete->IoStatus.Status = STATUS_CANCELLED;
        irpToComplete->IoStatus.Information = 0;
        IoCompleteRequest(irpToComplete, IO_NO_INCREMENT);
        IoDecrement(open);
    }

    return;
 
}


NTSTATUS
PacketCancelReadIrps(
    IN PDEVICE_OBJECT DeviceObject
)
{
    POPEN_INSTANCE      open = DeviceObject->DeviceExtension; 
    PLIST_ENTRY         thisEntry;
    PIRP                pendingIrp;
    PNDIS_PACKET        myPacket = NULL;
    PPACKET_RESERVED    reserved;
    PMDL                mdl;

    DebugPrint(("PacketCancelReadIrps\n"));

    //
    // Walk through the RcvList and cancel all read IRPs.
    //

    while(thisEntry=ExInterlockedRemoveHeadList(
                        &open->RcvList,
                        &open->RcvQSpinLock
                        ))
    {
        reserved=CONTAINING_RECORD(thisEntry,PACKET_RESERVED,ListElement);
        myPacket=CONTAINING_RECORD(reserved,NDIS_PACKET,ProtocolReserved);

        ASSERT(myPacket);

        pendingIrp = RESERVED(myPacket)->Irp;

        //
        //  Put the packet on the free queue
        //
        NdisFreePacket(myPacket);
        
        DebugPrint(("Cancelled : 0%0x\n", pendingIrp));
        
        IoSetCancelRoutine(pendingIrp, NULL);

        //
        // Cancel the Irp
        //
        pendingIrp->IoStatus.Information = 0;
        pendingIrp->IoStatus.Status = STATUS_CANCELLED;
        IoCompleteRequest(pendingIrp, IO_NO_INCREMENT);
        IoDecrement(open);
    }

    return STATUS_SUCCESS;
}

⌨️ 快捷键说明

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