📄 read.c
字号:
// read.c - PacketAllocatePacketBuffer, PacketRead, PacketReceiveIndicate,
// PacketTransferDataComplete, PacketReceiveComplete
// Original code by William Ingle (address unknown)
// debugged and extended by Chris Chlap (chrisc@fir.canberra.edu.au)
#include <basedef.h>
#include <vmm.h>
#include <debug.h>
#include <ndis.h>
#include <vwin32.h>
#include "packet.h"
#include "ntddpack.h"
#pragma VxD_LOCKED_CODE_SEG
#pragma VxD_LOCKED_DATA_SEG
//--------------------------------------------------------------------
//
// PacketAllocatePacketBuffer - allocate a buffer for reading/writing
//
//--------------------------------------------------------------------
VOID PacketAllocatePacketBuffer(PNDIS_STATUS pStatus,
POPEN_INSTANCE pOpen,
PNDIS_PACKET *ppPacket,
PDIOCPARAMETERS pDiocParms,
DWORD FunctionCode )
{
PNDIS_BUFFER pNdisBuffer;
PNDIS_PACKET pPacket;
//
// Try to get a packet from our list of free ones
//
NdisAllocatePacket(pStatus, ppPacket, pOpen->PacketPool);
if (*pStatus != NDIS_STATUS_SUCCESS) {
Debug_Out("PacketAllocatePacketBuffer: ERROR: no packet buffer\n");
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
return;
}
pPacket = *ppPacket;
//
// Buffers used asynchronously must be page locked
//
switch (FunctionCode) {
case IOCTL_PROTOCOL_READ:
RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock((PVOID) pDiocParms->lpvOutBuffer, pDiocParms->cbOutBuffer);
RESERVED(pPacket)->cbBuffer = pDiocParms->cbOutBuffer;
break;
case IOCTL_PROTOCOL_WRITE:
RESERVED(pPacket)->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer);
RESERVED(pPacket)->cbBuffer = pDiocParms->cbInBuffer;
break;
default:
Debug_Out("PacketAllocatePacketBuffer: ERROR: Bad FunctionCode\n");
// recycle the packet
NdisReinitializePacket(pPacket);
// Put the packet on the free queue
NdisFreePacket(pPacket);
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
*pStatus = NDIS_STATUS_NOT_ACCEPTED;
return;
}
RESERVED(pPacket)->lpcbBytesReturned = (PVOID)PacketPageLock((PVOID) pDiocParms->lpcbBytesReturned, sizeof(DWORD));
RESERVED(pPacket)->lpoOverlapped = (PVOID)PacketPageLock((PVOID) pDiocParms->lpoOverlapped, sizeof(OVERLAPPED));
RESERVED(pPacket)->hDevice = pDiocParms->hDevice;
RESERVED(pPacket)->tagProcess = pDiocParms->tagProcess;
switch (FunctionCode) {
case IOCTL_PROTOCOL_READ:
NdisAllocateBuffer(pStatus,
&pNdisBuffer,
pOpen->BufferPool,
(PVOID)(RESERVED(pPacket)->lpBuffer + ETHERNET_HEADER_LENGTH),
pDiocParms->cbOutBuffer);
break;
case IOCTL_PROTOCOL_WRITE:
NdisAllocateBuffer(pStatus,
&pNdisBuffer,
pOpen->BufferPool,
(PVOID)RESERVED(pPacket)->lpBuffer,
pDiocParms->cbInBuffer);
break;
}
if (*pStatus != NDIS_STATUS_SUCCESS) {
Debug_Out("PacketAllocatePacketBuffer: ERROR: no buffer descriptor\n");
// recycle the packet
NdisReinitializePacket(pPacket);
// Put the packet on the free queue
NdisFreePacket(pPacket);
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
return;
}
// Attach buffer to Packet
NdisChainBufferAtFront(pPacket, pNdisBuffer);
return;
}
//--------------------------------------------------------------------
//
// PacketRead - read a packet
//
//--------------------------------------------------------------------
DWORD PacketRead(POPEN_INSTANCE Open,
DWORD dwDDB,
DWORD hDevice,
PDIOCPARAMETERS pDiocParms)
{
NDIS_STATUS Status;
PNDIS_PACKET pPacket;
//
// Check that the buffer can hold a max length Ethernet packet
//
if (pDiocParms->cbOutBuffer < ETHERNET_PACKET_LENGTH) {
// Need bigger buffer
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
Debug_Out("Debug_Out: PacketRead: ERROR: buffer length not 1514 bytes\n");
return NDIS_STATUS_SUCCESS;
}
PacketAllocatePacketBuffer(&Status, Open, &pPacket, pDiocParms, IOCTL_PROTOCOL_READ);
if (Status == NDIS_STATUS_SUCCESS) {
//
// Put this packet in a list of pending reads.
// The receive indication handler will attempt to remove packets
// from this list for use in transfer data calls
//
NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 6.11.97
InsertTailList(&Open->RcvList, &RESERVED(pPacket)->ListElement);
NdisReleaseSpinLock(&Open->RcvQSpinLock);
}
else Debug_Out("PacketRead: ERROR: allocate packet buffer failed\n");
return -1; // This will make DeviceIOControl return ERROR_IO_PENDING
}
//--------------------------------------------------------------------
//
// PacketReceiveIndicate - upcall on packet arrival
//
//--------------------------------------------------------------------
NDIS_STATUS NDIS_API 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;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
UINT BytesTransfered = 0;
ULONG BufferLength;
PPACKET_RESERVED pReserved;
// UINT flags;
if (HeaderBufferSize != ETHERNET_HEADER_LENGTH) {
Debug_Out("PacketReceiveIndicate: ERROR: bad HeaderBufferSize\n");
return NDIS_STATUS_NOT_ACCEPTED;
}
Open = (POPEN_INSTANCE) ProtocolBindingContext;
//
// See if there are any pending reads that we can satisfy
//
NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 6.11.97
if (IsListEmpty(&Open->RcvList)) {
NdisReleaseSpinLock(&Open->RcvQSpinLock);
Debug_Out("PacketReceiveIndicate: ERROR: RcvList empty\n");
return NDIS_STATUS_NOT_ACCEPTED;
}
else {
PacketListEntry = RemoveHeadList(&Open->RcvList);
NdisReleaseSpinLock(&Open->RcvQSpinLock);
}
pReserved = CONTAINING_RECORD(PacketListEntry, PACKET_RESERVED, ListElement);
pPacket = CONTAINING_RECORD(pReserved, NDIS_PACKET, ProtocolReserved);
//
// Copy the MAC header
//
NdisMoveMemory(RESERVED(pPacket)->lpBuffer, HeaderBuffer, HeaderBufferSize);
//NdisQuerySendFlags(pPacket, &flags);
//NdisMoveMemory(RESERVED(pPacket)->lpBuffer, &flags, 4);
//
// Call the Mac to transfer the data portion of the packet
//
NdisTransferData(&Status, Open->AdapterHandle, MacReceiveContext,
0, PacketSize, pPacket, &BytesTransfered);
if (Status == NDIS_STATUS_PENDING) {
Debug_Out("PacketReceiveIndicate: NdisTransfer pending\n");
return NDIS_STATUS_SUCCESS;
}
if (Status == NDIS_STATUS_SUCCESS) {
Debug_Out("PacketReceiveIndicate: NdisTransfer complete\n");
PacketTransferDataComplete(Open, pPacket, Status, BytesTransfered);
return NDIS_STATUS_SUCCESS;
}
Debug_Out("PacketReceiveIndicate: ERROR: NdisTransfer\n");
PacketTransferDataComplete(Open, pPacket, Status, 0);
return NDIS_STATUS_SUCCESS;
}
//--------------------------------------------------------------------
//
// PacketTransferDataComplete - upcall when no more data available
//
//--------------------------------------------------------------------
VOID NDIS_API PacketTransferDataComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET pPacket,
IN NDIS_STATUS Status,
IN UINT BytesTransfered)
{
POPEN_INSTANCE Open;
PPACKET_RESERVED pReserved;
OVERLAPPED* pOverlap;
PNDIS_BUFFER pNdisBuffer;
Open = (POPEN_INSTANCE) ProtocolBindingContext;
pReserved = ((PPACKET_RESERVED) (pPacket->ProtocolReserved));
pOverlap = ((OVERLAPPED *) (pReserved->lpoOverlapped));
//
// free buffer descriptor
//
NdisUnchainBufferAtFront(pPacket, &pNdisBuffer);
if (pNdisBuffer)
NdisFreeBuffer(pNdisBuffer);
//
// set total bytes returned
//
BytesTransfered += ETHERNET_HEADER_LENGTH;
*(pReserved->lpcbBytesReturned) += BytesTransfered;
pOverlap->O_InternalHigh = *(pReserved->lpcbBytesReturned);
//
// The internal member of overlapped structure contains
// a pointer to the event structure that will be signalled,
// resuming the execution of the waitng GetOverlappedResult
// call.
//
VWIN32_DIOCCompletionRoutine(pOverlap->O_Internal);
// Unlock buffers
PacketPageUnlock(pReserved->lpBuffer, pReserved->cbBuffer);
PacketPageUnlock(pReserved->lpcbBytesReturned, sizeof(DWORD));
PacketPageUnlock(pReserved->lpoOverlapped, sizeof(OVERLAPPED));
// recycle the packet
NdisReinitializePacket(pPacket);
// Put the packet on the free queue
NdisFreePacket(pPacket);
return;
}
//--------------------------------------------------------------------
//
// PacketReceiveComplete - upcall when receive complete
//
//--------------------------------------------------------------------
VOID NDIS_API PacketReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
{
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -