📄 epacket.c
字号:
PLIST_ENTRY RequestListEntry;
PINTERNAL_REQUEST pRequest;
PPACKET_RESERVED pReserved;
EPACKET_OID * OidData;
NDIS_STATUS Status;
// Acquire request element from list
NdisAcquireSpinLock(&Open->RequestSpinLock);
if (IsListEmpty(&Open->RequestList)) {
*(DWORD *)(pDiocParms->lpcbBytesReturned) = 0;
NdisReleaseSpinLock(&Open->RequestSpinLock);
return NDIS_STATUS_SUCCESS;
}
RequestListEntry = RemoveHeadList(&Open->RequestList);
NdisReleaseSpinLock(&Open->RequestSpinLock);
pReserved = CONTAINING_RECORD(RequestListEntry, PACKET_RESERVED, ListElement);
pRequest = CONTAINING_RECORD(pReserved, INTERNAL_REQUEST, Reserved);
OidData = (EPACKET_OID*)(pDiocParms->lpvInBuffer);
if ((pDiocParms->cbInBuffer != pDiocParms->cbOutBuffer) ||
(pDiocParms->cbInBuffer < sizeof(*OidData) - sizeof(OidData->Data) + OidData->Length)) {
*(DWORD *)pDiocParms->lpcbBytesReturned = 1;
return NDIS_STATUS_BUFFER_TOO_SHORT;
}
// The buffer is valid
pReserved->lpBuffer = (PVOID)PacketPageLock(pDiocParms->lpvInBuffer, pDiocParms->cbInBuffer);
pReserved->lpcbBytesReturned = (PVOID)PacketPageLock(pDiocParms->lpcbBytesReturned, sizeof(DWORD));
pReserved->lpoOverlapped = (PVOID)PacketPageLock(pDiocParms->lpoOverlapped, sizeof(OVERLAPPED));
pReserved->cbBuffer = pDiocParms->cbInBuffer;
pReserved->hDevice = pDiocParms->hDevice;
pReserved->tagProcess = pDiocParms->tagProcess;
if (FunctionCode == IOCTL_EPACKET_SET_OID) {
pRequest->Request.RequestType = NdisRequestSetInformation;
pRequest->Request.DATA.SET_INFORMATION.Oid = OidData->Oid;
pRequest->Request.DATA.SET_INFORMATION.InformationBufferLength = OidData->Length;
pRequest->Request.DATA.SET_INFORMATION.InformationBuffer = OidData->Data;
}
else {
if (OidData->Oid >= 0x01000000)
pRequest->Request.RequestType = NdisRequestQueryInformation;
else
pRequest->Request.RequestType = NdisRequestGeneric1;
pRequest->Request.DATA.QUERY_INFORMATION.Oid = OidData->Oid;
pRequest->Request.DATA.QUERY_INFORMATION.InformationBufferLength = OidData->Length;
pRequest->Request.DATA.QUERY_INFORMATION.InformationBuffer = OidData->Data;
}
// submit the request
NdisRequest(&Status, Open->AdapterHandle, &pRequest->Request);
if (Status == NDIS_STATUS_PENDING)
return(-1); // This will make DeviceIOControl return ERROR_IO_PENDING
PacketRequestComplete(Open, &pRequest->Request, Status);
return Status;
}
///////////////////////////////////////////////////////////////////////////////
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)
{
// upcall on packet arrival
POPEN_INSTANCE Open;
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
NDIS_STATUS Status;
UINT BytesTransfered = 0;
PPACKET_RESERVED pReserved;
if (HeaderBufferSize != ETHERNET_HEADER_LENGTH)
return NDIS_STATUS_NOT_ACCEPTED;
Open = (POPEN_INSTANCE) ProtocolBindingContext;
// See if there are any pending reads that we can satisfy
NdisAcquireSpinLock(&Open->RcvQSpinLock); // fixed 5.11.97
if (IsListEmpty(&Open->RcvList)) {
NdisReleaseSpinLock(&Open->RcvQSpinLock);
return NDIS_STATUS_NOT_ACCEPTED;
}
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);
// 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)
return NDIS_STATUS_PENDING;
if (Status == NDIS_STATUS_SUCCESS) {
PacketTransferDataComplete(Open, pPacket, Status, BytesTransfered);
return NDIS_STATUS_SUCCESS;
}
PacketTransferDataComplete(Open, pPacket, Status, 0);
return NDIS_STATUS_SUCCESS;
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketReceiveComplete(IN NDIS_HANDLE ProtocolBindingContext)
{
// upcall when receive complete
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketStatus(IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN PVOID StatusBuffer,
IN UINT StatusBufferSize)
{
// get packet status
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketStatusComplete(IN NDIS_HANDLE ProtocolBindingContext)
{
// completion handler
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketBindAdapterComplete(IN NDIS_HANDLE ProtocolBindingContext,
IN NDIS_STATUS Status,
IN NDIS_STATUS OpenErrorStatus)
{
// upcall on Bind completion
POPEN_INSTANCE Open = (POPEN_INSTANCE)ProtocolBindingContext;
// If the binding is unsuccessful then we deallocate data structures in
// preparation for unloading
if (Status != NDIS_STATUS_SUCCESS) {
NdisFreeSpinLock(&Open->RequestSpinLock);
NdisFreeSpinLock(&Open->RcvQSpinLock);
NdisFreeBufferPool(Open->BufferPool);
NdisFreePacketPool(Open->PacketPool);
NdisFreeMemory(Open, sizeof(OPEN_INSTANCE), 0);
}
else {
// Insert New Adapter into list
InsertTailList(&GlobalDeviceExtension->OpenList, &Open->ListElement);
}
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketBindAdapter(OUT PNDIS_STATUS pStatus,
IN NDIS_HANDLE BindAdapterContext,
IN PNDIS_STRING pAdapterName,
IN PVOID SystemSpecific1,
IN PVOID SystemSpecific2)
{
// bind this driver to a NIC
POPEN_INSTANCE oiNew;
NDIS_STATUS ErrorStatus, AllocStatus;
UINT Medium;
NDIS_MEDIUM MediumArray = NdisMedium802_3;
UINT i;
// allocate some memory for the open structure
NdisAllocateMemory((PVOID *)&oiNew, sizeof(OPEN_INSTANCE), 0, -1);
if (oiNew == NULL) { // not enough memory
*pStatus = NDIS_STATUS_RESOURCES;
return;
}
NdisZeroMemory((PVOID)oiNew, sizeof(OPEN_INSTANCE));
// Save Binding Context
oiNew->BindAdapterContext = BindAdapterContext;
// Save the device handle
oiNew->hDevice = (DWORD)SystemSpecific1;
// Allocate a packet pool for our xmit and receive packets
NdisAllocatePacketPool(&AllocStatus,
&(oiNew->PacketPool),
TRANSMIT_PACKETS,
sizeof(PACKET_RESERVED));
if (AllocStatus != NDIS_STATUS_SUCCESS) { // not enough memory
NdisFreeMemory(oiNew, sizeof(OPEN_INSTANCE), 0);
*pStatus = NDIS_STATUS_RESOURCES;
return;
}
// Allocate a buffer pool for our xmit and receive buffers
NdisAllocateBufferPool(&AllocStatus, &(oiNew->BufferPool), TRANSMIT_PACKETS);
if (AllocStatus != NDIS_STATUS_SUCCESS) { // not enough memory
NdisFreeMemory(oiNew, sizeof(OPEN_INSTANCE), 0);
*pStatus = NDIS_STATUS_RESOURCES;
return;
}
// list to hold irp's that want to reset the adapter
NdisAllocateSpinLock(&oiNew->ResetSpinLock);
InitializeListHead(&oiNew->ResetIrpList);
// Initialize list for holding pending read requests
NdisAllocateSpinLock(&oiNew->RcvQSpinLock);
InitializeListHead(&oiNew->RcvList);
// Initialize the request list
NdisAllocateSpinLock(&oiNew->RequestSpinLock);
InitializeListHead(&oiNew->RequestList);
// link up the request stored in our open block
for (i = 0; i < MAX_REQUESTS; i++) {
// Braces are required as InsertTailList macro has multiple statements in it
InsertTailList(&oiNew->RequestList, &oiNew->Requests[i].Reserved.ListElement);
}
// Try to open the MAC
NdisOpenAdapter(pStatus, &ErrorStatus, &oiNew->AdapterHandle, &Medium, &MediumArray, 1,
GlobalDeviceExtension->NdisProtocolHandle, oiNew, pAdapterName, 0, NULL);
// Save the status returned by NdisOpenAdapter for completion routine
oiNew->Status = *pStatus;
switch (*pStatus) {
case NDIS_STATUS_PENDING:
break;
case NDIS_STATUS_SUCCESS:
ErrorStatus = NDIS_STATUS_SUCCESS;
// fall through to completion routine with oiNew->Status
// set to !NDIS_STATUS_PENDING
default:
PacketBindAdapterComplete(oiNew, *pStatus, ErrorStatus);
break;
}
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketUnbindAdapterComplete(IN POPEN_INSTANCE Open,
IN NDIS_STATUS Status)
{
// upcall on NdisCloseAdapter completion
// If Open->Status == NDIS_STATUS_PENDING then we must complete the pended unbinding
if (Open->Status == NDIS_STATUS_PENDING) {
NdisCompleteUnbindAdapter(Open->BindAdapterContext, Status);
Open->Status = NDIS_STATUS_SUCCESS;
}
if (Status != NDIS_STATUS_SUCCESS)
return;
// Remove Adapter from global list
RemoveEntryList(&Open->ListElement);
// Free Memory
NdisFreeSpinLock(&Open->RequestSpinLock);
NdisFreeSpinLock(&Open->RcvQSpinLock);
NdisFreeSpinLock(&Open->ResetSpinLock);
NdisFreeBufferPool(Open->BufferPool);
NdisFreePacketPool(Open->PacketPool);
NdisFreeMemory(Open, sizeof(OPEN_INSTANCE), 0);
}
///////////////////////////////////////////////////////////////////////////////
VOID NDIS_API PacketUnbindAdapter(OUT PNDIS_STATUS Status,
IN POPEN_INSTANCE Open,
IN POPEN_INSTANCE junk)
{
// detach protocol from the NIC clean up any pending I/O requests
PLIST_ENTRY PacketListEntry;
PNDIS_PACKET pPacket;
// The open instance of the device is about to close
// We need to complete all pending I/O requests
// First we complete any pending read requests
NdisAcquireSpinLock(&Open->RcvQSpinLock);
while (!IsListEmpty(&Open->RcvList)) {
PacketListEntry = RemoveHeadList(&Open->RcvList);
pPacket = CONTAINING_RECORD(PacketListEntry, NDIS_PACKET, ProtocolReserved);
// complete normally
PacketTransferDataComplete(Open, pPacket, NDIS_STATUS_SUCCESS, 0);
}
NdisReleaseSpinLock(&Open->RcvQSpinLock);
// close the adapter
NdisCloseAdapter(Status, Open->AdapterHandle);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -