📄 read.c
字号:
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 + -