VOID MPReturnPacket( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) /*++ Routine Description: NDIS Miniport entry point called whenever protocols are done with a packet that we had indicated up and they had queued up for returning later. Arguments: MiniportAdapterContext - pointer to ADAPT structure Packet - packet being returned. Return Value: None. --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; #ifdef NDIS51 // // Packet stacking: Check if this packet belongs to us. // if (NdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle) { // // We reused the original packet in a receive indication. // Simply return it to the miniport below us. // NdisReturnPackets(&Packet, 1); } else #endif // NDIS51 { // // This is a packet allocated from this IM's receive packet pool. // Reclaim our packet, and return the original to the driver below. // PNDIS_PACKET MyPacket; PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved); MyPacket = RecvRsvd->OriginalPkt; NdisFreePacket(Packet); NdisReturnPackets(&MyPacket, 1); } }
VOID MiniportReturnPacket5( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet ) { PADAPTER pAdapt = (PADAPTER)MiniportAdapterContext; // // Packet stacking: Check if this packet belongs to us. // if (MyNdisGetPoolFromPacket(Packet) != pAdapt->RecvPacketPoolHandle) { // // We reused the original packet in a receive indication. // Simply return it to the miniport below us. // NdisReturnPackets(&Packet, 1); } else { // // This is a packet allocated from this IM's receive packet pool. // Reclaim our packet, and return the original to the driver below. // PNDIS_PACKET MyPacket; PRECV_RSVD RecvRsvd; RecvRsvd = (PRECV_RSVD)(Packet->MiniportReserved); MyPacket = RecvRsvd->OriginalPkt; NdisFreePacket(Packet); if(MyPacket) NdisReturnPackets(&MyPacket, 1); } }
VOID PacketFree2 ( IN PNDIS_PACKET Packet ) { PLPX_RESERVED reserved = RESERVED(Packet); PUCHAR packetData; PNDIS_BUFFER pNdisBuffer; UINT uiLength; LONG clone; LONG BufferSeq; BOOLEAN allocMiniport = FALSE; PLPX_RESERVED externalReserved; DebugPrint( 3, ("PacketFree reserved->type = %d\n", reserved->Type) ); ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); switch (reserved->Type) { case LPX_PACKET_TYPE_SEND: clone = InterlockedDecrement( &reserved->Cloned ); if(clone >= 0) { return; } pNdisBuffer = NULL; BufferSeq = 0; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); while (pNdisBuffer) { // // Assuming the first data buffer comes from user application // the others are created in LPX for padding, etc. // Free the memory of the others. // if (BufferSeq == 0) { #if DBG NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); ASSERT( packetData == (PCHAR)&RESERVED(Packet)->EthernetHeader ); #endif } else if (BufferSeq == 1) { // UserBuffer } else if (BufferSeq == 2) { // Padding NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); LpxFreeMemoryWithLpxTag( packetData ); } else { ASSERT( FALSE ); } NdisFreeBuffer( pNdisBuffer ); pNdisBuffer = NULL; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); BufferSeq ++; } if (reserved->IrpSp != NULL) { PIRP _Irp = IRP_SEND_IRP( reserved->IrpSp ); ASSERT( reserved->NdisStatus == NDIS_STATUS_SUCCESS || reserved->NdisStatus == NDIS_STATUS_NOT_ACCEPTED || !NT_SUCCESS(reserved->NdisStatus) ); if (!NT_SUCCESS(reserved->NdisStatus)) { _Irp->IoStatus.Status = reserved->NdisStatus; } //INC_IRP_RETRANSMITS( _Irp, reserved->Retransmits ); LpxDereferenceSendIrp( "Destroy packet", reserved->IrpSp, RREF_PACKET ); } else { DebugPrint( 3, ("[LPX] PacketFree: No IrpSp\n") ) ; } break; case LPX_PACKET_TYPE_RECEIVE: // // If the packet allocated by NIC miniport, break here. // if(RESERVED(Packet)->RecvFlags & LPX_RESERVED_RECVFLAG_ALLOC_MINIPORT) { allocMiniport = TRUE; break; } pNdisBuffer = NULL; NdisUnchainBufferAtFront( Packet, &pNdisBuffer ); #if __LPX_STATISTICS__ { LARGE_INTEGER systemTime; KeQuerySystemTime( &systemTime ); RESERVED(Packet)->DeviceContext->NumberOfRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength; if (RESERVED(Packet)->PacketRawDataLength) { RESERVED(Packet)->DeviceContext->NumberOfLargeRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfLargeRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfLargeRecvPackets.QuadPart += sizeof(LPX_HEADER) + RESERVED(Packet)->PacketRawDataLength; } else { RESERVED(Packet)->DeviceContext->NumberOfSmallRecvPackets ++; RESERVED(Packet)->DeviceContext->FreeTimeOfSmallRecvPackets.QuadPart += systemTime.QuadPart - RESERVED(Packet)->RecvTime2.QuadPart; RESERVED(Packet)->DeviceContext->BytesOfSmallRecvPackets.QuadPart += sizeof(LPX_HEADER); } } #endif if (pNdisBuffer) { NdisQueryBufferSafe( pNdisBuffer, &packetData, &uiLength, HighPagePriority ); LpxFreeMemoryWithLpxTag( packetData ); NdisFreeBuffer( pNdisBuffer ); } break; default: ASSERT(FALSE); return; } // // Free external protocol reserved context. // externalReserved = ((PLPX_RESERVED)(Packet->ProtocolReserved))->ExternalReserved; if(externalReserved) { NdisFreeMemory(externalReserved, sizeof(LPX_RESERVED), 0); } ASSERT( Packet->Private.NdisPacketFlags & fPACKET_ALLOCATED_BY_NDIS ); if(allocMiniport) { // // Return the packet allocated by NIC miniport // NdisReturnPackets(&Packet, 1); } else { NdisFreePacket( Packet ); InterlockedDecrement( &NumberOfAllockPackets ); DebugPrint( 3, ("Packet REALLY Freed NumberOfAllockPackets = %d\n", NumberOfAllockPackets) ); } }
VOID ndisprotServiceReads( IN PNDISPROT_OPEN_CONTEXT pOpenContext ) /*++ Routine Description: Utility routine to copy received data into user buffers and complete READ IRPs. Arguments: pOpenContext - pointer to open context Return Value: None --*/ { PIRP pIrp = NULL; PLIST_ENTRY pIrpEntry; PNDIS_PACKET pRcvPacket; PLIST_ENTRY pRcvPacketEntry; PUCHAR pSrc, pDst; ULONG BytesRemaining; // at pDst PNDIS_BUFFER pNdisBuffer; ULONG BytesAvailable; BOOLEAN FoundPendingIrp; DEBUGP(DL_VERY_LOUD, ("ServiceReads: open %p/%x\n", pOpenContext, pOpenContext->Flags)); NPROT_REF_OPEN(pOpenContext); // temp ref - service reads NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); while (!NPROT_IS_LIST_EMPTY(&pOpenContext->PendedReads) && !NPROT_IS_LIST_EMPTY(&pOpenContext->RecvPktQueue)) { FoundPendingIrp = FALSE; // // Get the first pended Read IRP // pIrpEntry = pOpenContext->PendedReads.Flink; while (pIrpEntry != &pOpenContext->PendedReads) { pIrp = CONTAINING_RECORD(pIrpEntry, IRP, Tail.Overlay.ListEntry); // // Check to see if it is being cancelled. // if (IoSetCancelRoutine(pIrp, NULL)) { // // It isn't being cancelled, and can't be cancelled henceforth. // NPROT_REMOVE_ENTRY_LIST(pIrpEntry); FoundPendingIrp = TRUE; break; // // NOTE: we decrement PendedReadCount way below in the // while loop, to avoid letting through a thread trying // to unbind. // } else { // // The IRP is being cancelled; let the cancel routine handle it. // DEBUGP(DL_INFO, ("ServiceReads: open %p, skipping cancelled IRP %p\n", pOpenContext, pIrp)); pIrpEntry = pIrpEntry->Flink; } } // // If no pending IRP // if (FoundPendingIrp == FALSE) { break; } // // Get the first queued receive packet // pRcvPacketEntry = pOpenContext->RecvPktQueue.Flink; NPROT_REMOVE_ENTRY_LIST(pRcvPacketEntry); pOpenContext->RecvPktCount --; NPROT_RELEASE_LOCK(&pOpenContext->Lock); NPROT_DEREF_OPEN(pOpenContext); // Service: dequeue rcv packet pRcvPacket = NPROT_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); // // Copy as much data as possible from the receive packet to // the IRP MDL. // pDst = MmGetSystemAddressForMdlSafe(pIrp->MdlAddress, NormalPagePriority); __analysis_assume(pDst); NPROT_ASSERT(pDst != NULL); // since it was already mapped BytesRemaining = MmGetMdlByteCount(pIrp->MdlAddress); pNdisBuffer = NDIS_PACKET_FIRST_NDIS_BUFFER(pRcvPacket); // // Copy the data in the received packet into the buffer provided by the client. // If the length of the receive packet is greater than length of the given buffer, // we just copy as many bytes as we can. Once the buffer is full, we just discard // the rest of the data, and complete the IRP sucessfully even we only did a partial copy. // while (BytesRemaining && (pNdisBuffer != NULL)) { #ifndef WIN9X NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DEBUGP(DL_FATAL, ("ServiceReads: Open %p, QueryBuffer failed for buffer %p\n", pOpenContext, pNdisBuffer)); break; } #else NdisQueryBuffer(pNdisBuffer, &pSrc, &BytesAvailable); #endif if (BytesAvailable) { ULONG BytesToCopy = MIN(BytesAvailable, BytesRemaining); NPROT_COPY_MEM(pDst, pSrc, BytesToCopy); BytesRemaining -= BytesToCopy; pDst += BytesToCopy; } NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer); } // // Complete the IRP. // pIrp->IoStatus.Status = STATUS_SUCCESS; pIrp->IoStatus.Information = MmGetMdlByteCount(pIrp->MdlAddress) - BytesRemaining; DEBUGP(DL_INFO, ("ServiceReads: Open %p, IRP %p completed with %d bytes\n", pOpenContext, pIrp, pIrp->IoStatus.Information)); IoCompleteRequest(pIrp, IO_NO_INCREMENT); // // Free up the receive packet - back to the miniport if it // belongs to it, else reclaim it (local copy). // if (NdisGetPoolFromPacket(pRcvPacket) != pOpenContext->RecvPacketPool) { NdisReturnPackets(&pRcvPacket, 1); } else { ndisprotFreeReceivePacket(pOpenContext, pRcvPacket); } NPROT_DEREF_OPEN(pOpenContext); // took out pended Read NPROT_ACQUIRE_LOCK(&pOpenContext->Lock); pOpenContext->PendedReadCount--; } NPROT_RELEASE_LOCK(&pOpenContext->Lock); NPROT_DEREF_OPEN(pOpenContext); // temp ref - service reads }
VOID SecLabFreeReceivePacket( PADAPT pAdapt, IN PNDIS_PACKET pNdisPacket ) /*++ Routine Description: 释放所有与接收包相关的资源。如果这是一个本地拷贝,将此包释放到接收包池 。否则释放到miniport. Arguments: pNdisPacket - 指向要释放的包的指针 Return Value: None --*/ { PNDIS_BUFFER pNdisBuffer; UINT TotalLength; UINT BufferLength; PUCHAR pCopyData; if (NdisGetPoolFromPacket(pNdisPacket) ==pAdapt->RecvPacketPoolHandle) { // // This is a local copy. // #ifdef NDIS51 NdisGetFirstBufferFromPacketSafe( pNdisPacket, &pNdisBuffer, (PVOID *)&pCopyData, &BufferLength, &TotalLength, NormalPagePriority); #else NdisGetFirstBufferFromPacket( pNdisPacket, &pNdisBuffer, (PVOID *)&pCopyData, &BufferLength, &TotalLength); #endif if(BufferLength != TotalLength || pNdisBuffer==NULL || pCopyData==NULL) { DbgPrint("Error! Failed in Free a Packet"); DbgBreakPoint(); } NdisFreePacket(pNdisPacket); NdisFreeBuffer(pNdisBuffer); NdisFreeMemory(pCopyData,0,0); } else { NdisReturnPackets(&pNdisPacket, 1); } }
BOOLEAN PickPacketFromList(PADAPT pAdapt,PIRP Irp) { PIO_STACK_LOCATION IrpStack; ULONG PacketLenTotal=0; PNDIS_PACKET pRcvPacket; PLIST_ENTRY pRcvPacketEntry; PUCHAR pSrc, pDst; PUCHAR pDstFormer; ULONG BytesRemaining; // at pDst PNDIS_BUFFER pNdisBuffer; ULONG BytesAvailable; ULONG BytesToCopy; NdisAcquireSpinLock(&PacketListLock); if(!IsListEmpty(&PacketList)) { // // Get the first queued receive packet // pRcvPacketEntry = PacketList.Flink; RemoveEntryList(pRcvPacketEntry); PacketCount--; NdisReleaseSpinLock(&PacketListLock); pRcvPacket = SECLAB_LIST_ENTRY_TO_RCV_PKT(pRcvPacketEntry); // // Copy as much data as possible from the receive packet to // the IRP MDL. // pDst = (PUCHAR)ExAllocatePool(NonPagedPool,MY_MTU); if(pDst==NULL) { DbgPrint("Can not allocate enough pool"); DbgBreakPoint(); } pDstFormer=pDst; IrpStack = IoGetCurrentIrpStackLocation(Irp); BytesRemaining = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; pNdisBuffer = pRcvPacket->Private.Head; while (BytesRemaining && (pNdisBuffer != NULL)) { NdisQueryBufferSafe(pNdisBuffer, &pSrc, &BytesAvailable, NormalPagePriority); if (pSrc == NULL) { DbgPrint("PickPacketFromList: QueryBuffer failed for buffer"); break; } if (BytesAvailable) { BytesToCopy = MIN(BytesAvailable, BytesRemaining); NdisMoveMemory(pDstFormer, pSrc, BytesToCopy); BytesRemaining -= BytesToCopy; pDstFormer += BytesToCopy; PacketLenTotal += BytesToCopy; } NdisGetNextBuffer(pNdisBuffer, &pNdisBuffer); } // // Complete the IRP. // RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, pDst, PacketLenTotal); IoSetCancelRoutine(Irp,NULL); CompleteIrp(Irp,STATUS_SUCCESS,PacketLenTotal); ExFreePool(pDst); // // Free up the receive packet - back to the miniport if it // belongs to it, else reclaim it (local copy). // if (NdisGetPoolFromPacket(pRcvPacket) != pAdapt->RecvPacketPoolHandle) { NdisReturnPackets(&pRcvPacket, 1); } else { SecLabFreeReceivePacket(pAdapt, pRcvPacket); } } else { NdisReleaseSpinLock(&PacketListLock); return FALSE; } return TRUE; }