📄 read.c
字号:
NdisFreeMemory(VirtualAddress, TotalLength, 0);
NdisFreePacket(pPacket);
pPacket = NULL;
goto ERROR;
}
NdisChainBufferAtFront(
pPacket,
pBuffer
);
//
// Copy the ethernet header into the packet first.
//
NdisMoveMappedMemory(
(PUCHAR)VirtualAddress + TotalLength - ETHERNET_HEADER_LENGTH,
HeaderBuffer,
HeaderBufferSize
);
//
// Copy data received on the underlying NIC into the packet we have just built.
//
NdisTransferData(
&status,
open->AdapterHandle,
MacReceiveContext,
0,
PacketSize,
pPacket,
&bytesTransfered
);
if (status == NDIS_STATUS_PENDING) {
return NDIS_STATUS_SUCCESS;
}
ERROR:
//
// If it didn't pend, call the completion 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:
--*/
{
POPEN_INSTANCE open;
PNDIS_BUFFER pFirstBuffer;
PVOID VirtualAddress;
UINT Length;
PIRP irp;
PMDL pMdl;
PIO_STACK_LOCATION irpSp;
open = (POPEN_INSTANCE)ProtocolBindingContext;
DebugPrint(("Packet: TransferDataComplete\n"));
if(open->Buffer_Handin){
irp=RESERVED(pPacket)->Irp;
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);
}else{
//
// Put this packet in the list of received packets if NdisTransferData returns NDIS_STATUS_SUCCESS.
// The PacketRead will attempt to remove packets from this list.
//
if (Status == NDIS_STATUS_SUCCESS) {
ExInterlockedInsertTailList(
&open->RcvPackQList,
&RESERVED(pPacket)->RcvPackQListElement,
&open->RcvPackQSpinLock
);
} else {
//
// If control flow passes this branch, there are two possibilities for the pPacket:
// i. We call PacketTransferDataComplete immediately after the statement "goto ERROR".
// We have nothing to do in this manner since we have released all the resources before "goto ERROR".
// ii.PacketTransferDataComplete is called automatically as the result that the preceding call to
// NdisTransferData returns NDIS_STATUS_PENDING.
// Since NdisTransferData failed eventually, we should release all the resources now.
//
if (pPacket != NULL) {
NdisQueryPacket(pPacket, NULL, NULL, &pFirstBuffer, NULL);
NdisQueryBuffer(pFirstBuffer, &VirtualAddress, &Length);
//
// Free pPacket if failed during the transfer.
//
NdisFreeMemory(VirtualAddress, Length, 0);
NdisFreeBuffer(pFirstBuffer);
NdisFreePacket(pPacket);
}
}
}
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.
--*/
{
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 + -