VOID natpSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status ) { PFILTER_ADAPTER pAdapt = (PFILTER_ADAPTER)ProtocolBindingContext; PNDIS_PACKET pOrgPacket; NDIS_HANDLE PoolHandle; PoolHandle = NdisGetPoolFromPacket( Packet ); if ( PoolHandle == pAdapt->SndPP1 ) { pOrgPacket = *(PVOID*)(Packet->ProtocolReserved); NdisIMCopySendCompletePerPacketInfo (pOrgPacket, Packet); NdisDprFreePacket(Packet); NdisMSendComplete( pAdapt->MiniportHandle, pOrgPacket, Status ); }else if ( PoolHandle == pAdapt->SndPP2 ) { FLT_PKT *pFltPkt = *(PVOID*)(Packet->ProtocolReserved); ASSERT(pFltPkt); pOrgPacket = pFltPkt->pOrgPkt; natmFreeBuffers (Packet); NdisDprFreePacket(Packet); if(pOrgPacket) NdisMSendComplete( pAdapt->MiniportHandle, pOrgPacket, Status ); FreeFltPkt(pFltPkt); }else{ NdisMSendComplete( pAdapt->MiniportHandle, Packet, Status ); } InterlockedDecrement(&pAdapt->SendPending); }
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); } }
int divert_send_complete(PNDIS_PACKET Pkt) { int rc = 0; lock(); if (NdisGetPoolFromPacket(Pkt) == _packet_pool) { NdisFreePacket(Pkt); rc = 1; } unlock(); return rc; }
VOID FakeNDISTransferDataCompleteHandler( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET pNdisPacket, IN NDIS_STATUS TransferStatus, IN UINT BytesTransferred ) /*++ Routine Description: Called to signal completion of a pended NdisTransferData. Arguments: ProtocolBindingContext - pointer to open context pNdisPacket - our receive packet into which data is transferred TransferStatus - status of the transfer BytesTransferred - bytes copied into the packet. Return Value: None Author: xiaonie 2012/07/12 --*/ { PLIST_ENTRY pEntry; PNDIS_HOOK_LIST_NODE pNode; KIRQL irql; ULONG ulFunAddr = 0; KeAcquireSpinLock(&g_lock, &irql); for (pEntry = g_linkListHead.Flink; pEntry != &g_linkListHead; pEntry = pEntry->Flink) { pNode = CONTAINING_RECORD(pEntry, NDIS_HOOK_LIST_NODE, ListEntry); if (pNode->ProtocolBindingContext == ProtocolBindingContext) { ulFunAddr = pNode->ulRealProtocolReceiveHandler; break; } } KeReleaseSpinLock(&g_lock, irql); if (ulFunAddr == 0) { DbgPrint("\r\n Attention: FunAddr == 0(4: FakeNDISTransferDataCompleteHandler)\r\n"); return; } if (NdisGetPoolFromPacket(pNdisPacket) == g_PacketPool) { PKEVENT pEvt = *(PKEVENT *)(pNdisPacket->ProtocolReserved); // trigger the right time. KeSetEvent(pEvt, IO_NO_INCREMENT, FALSE); return; } // None of our business. call the real NDIS routines __asm { pushad; push BytesTransferred; push TransferStatus; push pNdisPacket; push ProtocolBindingContext; mov eax, ulFunAddr; call eax; popad; } }
VOID PtSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status ) /*++ Routine Description: Called by NDIS when the miniport below had completed a send. We should complete the corresponding upper-edge send this represents. Arguments: ProtocolBindingContext - Points to ADAPT structure Packet - Low level packet being completed Status - status of send Return Value: None --*/ { //------------------------------------------------------------------------- PNDIS_BUFFER packet_buffer; PUCHAR send_buffer = NULL; ULONG send_buffer_length; //------------------------------------------------------------------------- PADAPT pAdapt =(PADAPT)ProtocolBindingContext; PNDIS_PACKET Pkt; NDIS_HANDLE PoolHandle; #ifdef NDIS51 // // Packet stacking: // // Determine if the packet we are completing is the one we allocated. If so, then // get the original packet from the reserved area and completed it and free the // allocated packet. If this is the packet that was sent down to us, then just // complete it // PoolHandle = NdisGetPoolFromPacket(Packet); if (PoolHandle != pAdapt->SendPacketPoolHandle) { // // We had passed down a packet belonging to the protocol above us. // // DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet)); NdisMSendComplete(pAdapt->MiniportHandle, Packet, Status); } else #endif // NDIS51 { PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); Pkt = SendRsvd->OriginalPkt; //-------------------WestChamber----------------------------------- if (!Pkt) { //our packet //get buffer NdisUnchainBufferAtFront(Packet, &packet_buffer); if (packet_buffer) { NdisQueryBufferSafe(packet_buffer, (PVOID *)&send_buffer, &send_buffer_length, HighPagePriority); if (send_buffer && send_buffer_length) { //got buffer, free it. NdisFreeMemory(send_buffer, send_buffer_length, 0); } NdisFreeBuffer(packet_buffer); } //free packet NdisDprFreePacket(Packet); return; } //-------------------WestChamber---------------------------------- #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); #endif NdisDprFreePacket(Packet); NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); } }
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; }