📄 read.c
字号:
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
packet.c
Abstract:
Author:
Environment:
Kernel mode only.
Notes:
Future:
Revision History:
--*/
#include "stdarg.h"
#include "ntddk.h"
#include "ntiologc.h"
#include "ndis.h"
#include "debug.h"
#include "packet.h"
NTSTATUS
PacketRead(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This is the dispatch routine for create/open and close requests.
These requests complete successfully.
Arguments:
DeviceObject - Pointer to the device object.
Irp - Pointer to the request packet.
Return Value:
Status is returned.
--*/
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PNDIS_PACKET pPacket;
PMDL pMdl;
NDIS_STATUS Status;
IF_LOUD(DbgPrint("Packet: Read\n");)
IrpSp = IoGetCurrentIrpStackLocation(Irp);
Open=IrpSp->FileObject->FsContext;
//
// See if the buffer is atleast big enough to hold the
// ethernet header
//
if (IrpSp->Parameters.Read.Length < ETHERNET_HEADER_LENGTH) {
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// 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) {
IF_LOUD(DbgPrint("Packet: Read-Failed to allocate Mdl\n");)
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// Build the mdl to point to the the portion of the buffer followin
// 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;
//
// Try to get a packet from our list of free ones
//
NdisAllocatePacket(
&Status,
&pPacket,
Open->PacketPool
);
if (Status != NDIS_STATUS_SUCCESS) {
IF_LOUD(DbgPrint("Packet: Read- No free packets\n");)
IoFreeMdl(pMdl);
Irp->IoStatus.Status = STATUS_UNSUCCESSFUL;
return STATUS_UNSUCCESSFUL;
}
//
// Get a pointer to the packet itself
//
RESERVED(pPacket)->Irp=Irp;
RESERVED(pPacket)->pMdl=pMdl;
IoMarkIrpPending(Irp);
Irp->IoStatus.Status = STATUS_PENDING;
//
// Attach our new MDL to the packet
//
NdisChainBufferAtFront(pPacket,pMdl);
//
// Put this packet in a list of pending reads.
// The receive indication handler will attemp to remove packets
// from this list for use in transfer data calls
//
ExInterlockedInsertTailList(
&Open->RcvList,
&RESERVED(pPacket)->ListElement,
&Open->RcvQSpinLock);
return(STATUS_PENDING);
}
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
)
{
POPEN_INSTANCE Open;
PIO_STACK_LOCATION IrpSp;
PIRP Irp;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
ULONG SizeToTransfer;
NDIS_STATUS Status;
UINT BytesTransfered;
ULONG BufferLength;
PPACKET_RESERVED Reserved;
IF_LOUD(DbgPrint("Packet: 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) {
return NDIS_STATUS_SUCCESS;
}
Reserved=CONTAINING_RECORD(PacketListEntry,PACKET_RESERVED,ListElement);
pPacket=CONTAINING_RECORD(Reserved,NDIS_PACKET,ProtocolReserved);
Irp=RESERVED(pPacket)->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
//
// 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(
MmGetSystemAddressForMdl(Irp->MdlAddress),
HeaderBuffer,
HeaderBufferSize
);
//
// Call the Mac to transfer the packet
//
NdisTransferData(
&Status,
Open->AdapterHandle,
MacReceiveContext,
0,
SizeToTransfer,
pPacket,
&BytesTransfered);
if (Status != NDIS_STATUS_PENDING) {
//
// 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
)
{
PIO_STACK_LOCATION IrpSp;
POPEN_INSTANCE Open;
PIRP Irp;
PMDL pMdl;
IF_LOUD(DbgPrint("Packet: TransferDataComplete\n");)
Open= (POPEN_INSTANCE)ProtocolBindingContext;
Irp=RESERVED(pPacket)->Irp;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
pMdl=RESERVED(pPacket)->pMdl;
//
// Free the MDL that we allocated
//
IoFreeMdl(pMdl);
//
// recylcle the packet
//
NdisReinitializePacket(pPacket);
//
// Put the packet on the free queue
//
NdisFreePacket(pPacket);
Irp->IoStatus.Status = Status;
Irp->IoStatus.Information = BytesTransfered+ETHERNET_HEADER_LENGTH;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return;
}
VOID
PacketReceiveComplete(
IN NDIS_HANDLE ProtocolBindingContext
)
{
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -