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