VOID MPSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) /*++ Routine Description: Send Packet Array handler. Either this or our SendPacket handler is called based on which one is enabled in our Miniport Characteristics. Arguments: MiniportAdapterContext Pointer to our adapter PacketArray Set of packets to send NumberOfPackets Self-explanatory Return Value: None --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; UINT i; PVOID MediaSpecificInfo = NULL; UINT MediaSpecificInfoSize = 0; for (i = 0; i < NumberOfPackets; i++) { PNDIS_PACKET Packet, MyPacket; ULONG SndFltAction; Packet = PacketArray[i]; // // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue; } // // Call Send Packet Filter // SndFltAction = FltFilterSendPacket( pAdapt, Packet, FALSE // Caller is running at IRQL <= DISPATCH_LEVEL ); // // Possibly Block (Drop) Packet // ---------------------------- // Lying send. Report SUCCESS, even though it really hasn't // been sent. // if( SndFltAction & ACTION_BLOCK_PACKET ) { NdisMSendComplete( ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_SUCCESS); continue; } #ifdef NDIS51 // // Use NDIS 5.1 packet stacking: // { PNDIS_PACKET_STACK pStack; BOOLEAN Remaining; // // Packet stacks: Check if we can use the same packet for sending down. // pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". // // NOTE: if we needed to keep per-packet information in packets // sent down, we can use pStack->IMReserved[]. // ASSERT(pStack); // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); } else { pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisSend(&Status, pAdapt->BindingHandle, Packet); if (Status != NDIS_STATUS_PENDING) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, Status); ADAPT_DECR_PENDING_SENDS(pAdapt); } } continue; } } #endif do { NdisAcquireSpinLock(&pAdapt->Lock); // // If the below miniport is going to low power state, stop sending down any packet. // if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; MyPacket->Private.Flags = NdisGetPacketFlags(Packet); MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; #ifdef WIN9X // // Work around the fact that NDIS does not initialize this // to FALSE on Win9x. // MyPacket->Private.ValidCounts = FALSE; #endif // WIN9X // // Copy the OOB data from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); // // Copy relevant parts of the per packet info into the new packet // #ifndef WIN9X NdisIMCopySendPerPacketInfo(MyPacket, Packet); #endif // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); #endif NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { // // The driver cannot allocate a packet. // ADAPT_DECR_PENDING_SENDS(pAdapt); } } while (FALSE); if (Status != NDIS_STATUS_PENDING) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, Status); } } }
NDIS_STATUS MPSend( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet, IN UINT Flags ) /*++ Routine Description: Send Packet handler. Either this or our SendPackets (array) handler is called based on which one is enabled in our Miniport Characteristics. Arguments: MiniportAdapterContext Pointer to the adapter Packet Packet to send Flags Unused, passed down below Return Value: Return code from NdisSend --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; PNDIS_PACKET MyPacket; PVOID MediaSpecificInfo = NULL; ULONG MediaSpecificInfoSize = 0; ULONG SndFltAction; // // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { return NDIS_STATUS_FAILURE; } // // Call Send Packet Filter // SndFltAction = FltFilterSendPacket( pAdapt, Packet, TRUE // Caller is running at IRQL DISPATCH_LEVEL ); // // Possibly Block (Drop) Packet // ---------------------------- // Lying send. Report SUCCESS, even though it really hasn't // been sent. // if( SndFltAction & ACTION_BLOCK_PACKET) { return NDIS_STATUS_SUCCESS; } #ifdef NDIS51 // // Use NDIS 5.1 packet stacking: // { PNDIS_PACKET_STACK pStack; BOOLEAN Remaining; // // Packet stacks: Check if we can use the same packet for sending down. // pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". // // NOTE: if we needed to keep per-packet information in packets // sent down, we can use pStack->IMReserved[]. // ASSERT(pStack); // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); return NDIS_STATUS_FAILURE; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisSend(&Status, pAdapt->BindingHandle, Packet); if (Status != NDIS_STATUS_PENDING) { ADAPT_DECR_PENDING_SENDS(pAdapt); } return(Status); } } #endif // NDIS51 // // We are either not using packet stacks, or there isn't stack space // in the original packet passed down to us. Allocate a new packet // to wrap the data with. // // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); return NDIS_STATUS_FAILURE; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; // // Save a pointer to the original packet in our reserved // area in the new packet. This is needed so that we can // get back to the original packet when the new packet's send // is completed. // SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; MyPacket->Private.Flags = Flags; // // Set up the new packet so that it describes the same // data as the original packet. // MyPacket->Private.Head = Packet->Private.Head; MyPacket->Private.Tail = Packet->Private.Tail; #ifdef WIN9X // // Work around the fact that NDIS does not initialize this // to FALSE on Win9x. // MyPacket->Private.ValidCounts = FALSE; #endif // // Copy the OOB Offset from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); #ifndef WIN9X // // Copy the right parts of per packet info into the new packet. // This API is not available on Win9x since task offload is // not supported on that platform. // NdisIMCopySendPerPacketInfo(MyPacket, Packet); #endif // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); #endif NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { ADAPT_DECR_PENDING_SENDS(pAdapt); // // We are out of packets. Silently drop it. Alternatively we can deal with it: // - By keeping separate send and receive pools // - Dynamically allocate more pools as needed and free them when not needed // } return(Status); }
VOID MPSendPackets( IN NDIS_HANDLE MiniportAdapterContext, IN PPNDIS_PACKET PacketArray, IN UINT NumberOfPackets ) /*++ Routine Description: Send Packet Array handler. Either this or our SendPacket handler is called based on which one is enabled in our Miniport Characteristics. Arguments: MiniportAdapterContext Pointer to our adapter PacketArray Set of packets to send NumberOfPackets Self-explanatory Return Value: None --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; UINT i; PVOID MediaSpecificInfo = NULL; UINT MediaSpecificInfoSize = 0; FILTER_STATUS fStatus; PUCHAR pBuffer; int nBufLen; for (i = 0; i < NumberOfPackets; i++) { PNDIS_PACKET Packet, MyPacket; Packet = PacketArray[i]; //KdPrint(("微端口MPSendPackets方法,开始报文分析\n")); getMemoryCopyFromPacket(Packet, &pBuffer, &nBufLen); KdPrint(("\n==> 微端口MPSendPackets方法,开始分析报文\n")); fStatus = analyzeBuffer(pAdapt, pBuffer, &nBufLen, MODE_SEND); //fStatus = AnalysisPacket(Packet, FALSE); //fStatus = FILTER_STATUS_PASS; if (fStatus == FILTER_STATUS_DROP) { //丢弃 KdPrint(("<== 微端口MPSendPackets方法,进入FILTER_STATUS_DROP模式\n")); freeMemory(pBuffer); // 在这个函数中,任何一个被放弃的包,都必须调用NdisMSendComplete。 NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue; } /* else if (fStatus == FILTER_STATUS_MODIFY_REDIRECT) { //没有发送时接收转发这种情况 } */ else if (fStatus == FILTER_STATUS_MODIFY_SEND) { //修改+发送 KdPrint(("<== 微端口MPSendPackets方法,进入FILTER_STATUS_MODIFY_SEND模式\n")); MyPacket = createPacketFromMemory_SendPool(pAdapt, pBuffer, nBufLen); //freePacketBufferOnly(Packet); // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue; } //这里原来有NDIS51的一个简化处理,放在此文件最下面了 do { PSEND_RSVD SendRsvd; NdisAcquireSpinLock(&pAdapt->Lock); // // If the below miniport is going to low power state, stop sending down any packet. // if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); //NdisAllocatePacket(&Status, // &MyPacket, // pAdapt->SendPacketPoolHandle); SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); NdisSetPacketFlags(MyPacket, NDIS_FLAGS_RESERVED4); //我们做个标记 //现在我们自己构造buffer,所以不需要用原packet的buffer了 //NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet); //NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet); // // Copy the OOB data from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); // // Copy relevant parts of the per packet info into the new packet // NdisIMCopySendPerPacketInfo(MyPacket, Packet); // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); //NdisFreePacket(MyPacket); freePacketBufferAndMemory(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } while (FALSE); if (Status != NDIS_STATUS_PENDING) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, Status); } } else //FILTER_STATUS_PASS { //按PASS处理 KdPrint(("<== 微端口MPSendPackets方法,进入FILTER_STATUS_PASS模式\n")); freeMemory(pBuffer); // // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, NDIS_STATUS_FAILURE); continue; } //这里原来有NDIS51的一个简化处理,放在此文件最下面了 do { NdisAcquireSpinLock(&pAdapt->Lock); // // If the below miniport is going to low power state, stop sending down any packet. // if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); Status = NDIS_STATUS_FAILURE; break; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; NdisGetPacketFlags(MyPacket) = NdisGetPacketFlags(Packet); NdisClearPacketFlags(MyPacket, NDIS_FLAGS_RESERVED4); //防止和上面的包混淆 NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet); NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet); // // Copy the OOB data from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); // // Copy relevant parts of the per packet info into the new packet // NdisIMCopySendPerPacketInfo(MyPacket, Packet); // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { // // The driver cannot allocate a packet. // ADAPT_DECR_PENDING_SENDS(pAdapt); } } while (FALSE); if (Status != NDIS_STATUS_PENDING) { NdisMSendComplete(ADAPT_MINIPORT_HANDLE(pAdapt), Packet, Status); } } } }
/*------------------------------------------------------------------------- ssh_driver_send_packets() Sends multiple NDIS packet into the network via virtual NIC. The packets are copied and then saved into a queue. The interceptor thread then processes the packets later. Arguments: miniport_context - virtual NIC object packet_array - array of NDIS packets packet_cnt - number of packets in the array Returns: Notes: To ensure that the sequential ordering of packets is not changed in error conditions we interrupt processing packets in the array whenever we notice that we cannot handle the packet. All the remaining packets in the array are then completed with FAILURE status. If we are running low of NDIS_PACKET resources then return with failure so that upper layer notices our lack of resources and the traffic then decreases. Default IRQL: <= DISPATCH_LEVEL -------------------------------------------------------------------------*/ static Boolean ssh_driver_copy_and_send(SshNdisIMAdapter adapter, PNDIS_PACKET src) { SshNdisIMInterceptor interceptor; SshCpuContext cpu_ctx; SshNdisPacket packet; ULONG new_value; UINT flags; SSH_IRQL old_irql; Boolean status = FALSE; SSH_ASSERT(adapter != NULL); SSH_ASSERT(src != NULL); SSH_RAISE_IRQL(DISPATCH_LEVEL, &old_irql); new_value = InterlockedIncrement(&adapter->ref_count); SSH_ASSERT(new_value > 0); if (!ssh_adapter_can_accept_send(adapter)) { SSH_DEBUG(SSH_D_FAIL, ("Adapter %@: not in running state!", ssh_adapter_id_st_render, adapter)); InterlockedDecrement(&adapter->ref_count); goto end; } interceptor = (SshNdisIMInterceptor)adapter->interceptor; #ifdef _WIN32_WCE ssh_kernel_critical_section_start(&interceptor->packet_pool_cs); #endif /* _WIN32_WCE */ cpu_ctx = &interceptor->cpu_ctx[ssh_kernel_get_cpu()]; /* Try to clone the original packet's descriptors */ packet = ssh_packet_clone((SshInterceptor)interceptor, &cpu_ctx->packet_pool, SSH_PROTOCOL_ETHERNET, src, FALSE); #ifdef _WIN32_WCE ssh_kernel_critical_section_end(&interceptor->packet_pool_cs); #endif /* _WIN32_WCE */ if (packet == NULL) { SSH_DEBUG(SSH_D_FAIL, ("Adapter %@: Failed to clone packet", ssh_adapter_id_st_render, adapter)); InterlockedDecrement(&adapter->ref_count); goto end; } NDIS_SET_PACKET_STATUS(src, NDIS_STATUS_PENDING); packet->complete_cb = ssh_driver_send_complete_cb; packet->complete_cb_handle = adapter; packet->complete_cb_param = NULL; packet->parent_complete_cb = ssh_driver_parent_send_complete_cb; packet->parent_complete_handle = adapter; packet->parent_complete_np = src; packet->parent_complete_param = (void *)NDIS_STATUS_SUCCESS; /* Set don't loopback flag and per packet info */ flags = NdisGetPacketFlags(packet->np); flags |= NDIS_FLAGS_DONT_LOOPBACK; NdisSetPacketFlags(packet->np, flags); NdisIMCopySendPerPacketInfo(packet->np, src); /* Set the information that engine uses */ SSH_DUMP_PACKET(SSH_D_MY5, "Cloned packet:", packet); packet->f.flags.from_local_stack = 1; packet->ip.ifnum_in = adapter->ifnum; packet->ip.flags |= SSH_PACKET_FROMPROTOCOL; packet->adapter_in = (SshAdapter)adapter; SSH_DEBUG(SSH_D_NICETOKNOW, ("Adapter %@: %u operations pending", ssh_adapter_id_st_render, adapter, new_value)); ssh_interceptor_send_to_engine(interceptor, adapter, packet); ssh_interceptor_process_enqueued_packets(interceptor, cpu_ctx); status = TRUE; end: if (old_irql < SSH_DISPATCH_LEVEL) SSH_LOWER_IRQL(old_irql); return status; }
NDIS_STATUS MPSend( IN NDIS_HANDLE MiniportAdapterContext, IN PNDIS_PACKET Packet, IN UINT Flags ) /*++ Routine Description: Send Packet handler. Either this or our SendPackets (array) handler is called based on which one is enabled in our Miniport Characteristics. Arguments: MiniportAdapterContext Pointer to the adapter Packet Packet to send Flags Unused, passed down below Return Value: Return code from NdisSend --*/ { PADAPT pAdapt = (PADAPT)MiniportAdapterContext; NDIS_STATUS Status; FILTER_STATUS fStatus; PNDIS_PACKET MyPacket; PVOID MediaSpecificInfo = NULL; ULONG MediaSpecificInfoSize = 0; // // The driver should fail the send if the virtual miniport is in low // power state // if (pAdapt->MPDeviceState > NdisDeviceStateD0) { return NDIS_STATUS_FAILURE; } //***************************此函数作废!!!!!!!!!!!!!!!************************************ //KdPrint(("微端口MPSend方法,开始报文分析\n")); fStatus = AnalysisPacket(Packet, MODE_SEND); //getPacketBuffer(Packet, ) //fStatus = FILTER_STATUS_PASS; if (fStatus == FILTER_STATUS_DROP) { return NDIS_STATUS_FAILURE; } else if(fStatus == FILTER_STATUS_MODIFY_REDIRECT) { // 转发...... // 修改包中的目标地址,和正常发送一样将包向下发送 // TODO. } #ifdef NDIS51 // // Use NDIS 5.1 packet stacking: // { PNDIS_PACKET_STACK pStack; BOOLEAN Remaining; // // Packet stacks: Check if we can use the same packet for sending down. // pStack = NdisIMGetCurrentPacketStack(Packet, &Remaining); if (Remaining) { // // We can reuse "Packet". // // NOTE: if we needed to keep per-packet information in packets // sent down, we can use pStack->IMReserved[]. // ASSERT(pStack); // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); return NDIS_STATUS_FAILURE; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisSend(&Status, pAdapt->BindingHandle, Packet); if (Status != NDIS_STATUS_PENDING) { ADAPT_DECR_PENDING_SENDS(pAdapt); } return(Status); } } #endif // NDIS51 // // We are either not using packet stacks, or there isn't stack space // in the original packet passed down to us. Allocate a new packet // to wrap the data with. // // // If the below miniport is going to low power state, stop sending down any packet. // NdisAcquireSpinLock(&pAdapt->Lock); if (pAdapt->PTDeviceState > NdisDeviceStateD0) { NdisReleaseSpinLock(&pAdapt->Lock); return NDIS_STATUS_FAILURE; } pAdapt->OutstandingSends++; NdisReleaseSpinLock(&pAdapt->Lock); NdisAllocatePacket(&Status, &MyPacket, pAdapt->SendPacketPoolHandle); if (Status == NDIS_STATUS_SUCCESS) { PSEND_RSVD SendRsvd; // // Save a pointer to the original packet in our reserved // area in the new packet. This is needed so that we can // get back to the original packet when the new packet's send // is completed. // SendRsvd = (PSEND_RSVD)(MyPacket->ProtocolReserved); SendRsvd->OriginalPkt = Packet; NdisGetPacketFlags(MyPacket) = Flags; // // Set up the new packet so that it describes the same // data as the original packet. // NDIS_PACKET_FIRST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_FIRST_NDIS_BUFFER(Packet); NDIS_PACKET_LAST_NDIS_BUFFER(MyPacket) = NDIS_PACKET_LAST_NDIS_BUFFER(Packet); #ifdef WIN9X // // Work around the fact that NDIS does not initialize this // to FALSE on Win9x. // NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE; #endif // // Copy the OOB Offset from the original packet to the new // packet. // NdisMoveMemory(NDIS_OOB_DATA_FROM_PACKET(MyPacket), NDIS_OOB_DATA_FROM_PACKET(Packet), sizeof(NDIS_PACKET_OOB_DATA)); #ifndef WIN9X // // Copy the right parts of per packet info into the new packet. // This API is not available on Win9x since task offload is // not supported on that platform. // NdisIMCopySendPerPacketInfo(MyPacket, Packet); #endif // // Copy the Media specific information // NDIS_GET_PACKET_MEDIA_SPECIFIC_INFO(Packet, &MediaSpecificInfo, &MediaSpecificInfoSize); if (MediaSpecificInfo || MediaSpecificInfoSize) { NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket, MediaSpecificInfo, MediaSpecificInfoSize); } NdisSend(&Status, pAdapt->BindingHandle, MyPacket); if (Status != NDIS_STATUS_PENDING) { #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Packet, MyPacket); #endif NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdapt); } } else { ADAPT_DECR_PENDING_SENDS(pAdapt); // // We are out of packets. Silently drop it. Alternatively we can deal with it: // - By keeping separate send and receive pools // - Dynamically allocate more pools as needed and free them when not needed // } return(Status); }