阅读:2399回复:3
自己组包用NdisSend发送时为何有时会蓝屏
最近在做的这个项目要求把符合一定条件的包放在应用层处理,处理后包的长度变长。一些问题已经解决,如通过在函数MpSendPackets中把符合条件包数据放入缓冲区,用事件通知应用层,把数据取出。取出后的数据经过处理,重新组成原始封包。用WriteFile函数把数据包写回到中间层。
但在派遣例程中现了问题: 用NdisSend(&status,pAdaptList->BindingHandle,MyPacket);发送的时,有时会不成功,出现蓝屏,有时候是成功的。这让我很郁闷,到底是什么原因导致发送不成功呢?在发送前要注意些什么呢?非常感谢有此方面经验的兄弟们能回答一两句。不管你的意见如何,对我来说都很珍贵。下面是关于发送的一段代码,麻烦看一下。 在驱动中这个派遣函数如下:(代码有点长,但应该好懂,呵呵) NTSTATUS DevWrite(PDEVICE_OBJECT pDeviceObject,PIRP pIrp) { NDIS_STATUS status=NDIS_STATUS_SUCCESS; PIO_STACK_LOCATION pIrpStack; PNDIS_PACKET MyPacket; PNDIS_PACKET_EXTENSION New=NULL; PNDIS_BUFFER PktBuffer=NULL; pIrpStack=IoGetCurrentIrpStackLocation(pIrp); do{ NdisDprAllocatePacket(&status,&MyPacket,pAdaptList->SendPacketPoolHandle); if(status!=NDIS_STATUS_SUCCESS)//封包申请完了 { status=STATUS_INSUFFICIENT_RESOURCES; DBGPRINT(("packet allocate fialed!\n")); break; } ((SEND_RSVD *)MyPacket->ProtocolReserved)->pIrp=pIrp;//保存这个IRP,是为了在完成函数中需要用到 ((SEND_RSVD *)MyPacket->ProtocolReserved)->OriginalPkt=NULL;//由于是自己组织的包,因此为NULL PktBuffer=pIrp->MdlAddress; NdisChainBufferAtBack(MyPacket,PktBuffer); NdisAcquireSpinLock(&pAdaptList->Lock); if(pAdaptList->MPDeviceState>NdisDeviceStateD0)//如果微端口处于低能状态,不能发送此包 { NdisReleaseSpinLock(&pAdaptList->Lock); status=NDIS_STATUS_FAILURE; DBGPRINT(("below miniport is going to low power.\n")); break; } pAdaptList->OutstandingSends++; NdisReleaseSpinLock(&pAdaptList->Lock); /*下面的代码是设置包的带外数据OOB,包扩展信息以及标志。在这里全部设置为0,因为我仅把原始包内的数据取出,但没有取原始包的OOB数据,扩展信息以及标志等。也就是说原始包的这里数据我没有传到应用层,因此在这里也没有办法取得,因此只好设置为0了。我用了调试器看了原始包的这些数据,大部分也是为0。*/ MyPacket->Private.Flags=0; NdisSetPacketFlags(MyPacket,NDIS_FLAGS_DONT_LOOPBACK); New=NDIS_PACKET_EXTENSION_FROM_PACKET(MyPacket); NdisZeroMemory(New->NdisPacketInfo,sizeof(New->NdisPacketInfo));//把包扩展信息全部置为0 NDIS_SET_PACKET_HEADER_SIZE(MyPacket,0); NDIS_SET_PACKET_TIME_RECEIVED(MyPacket,0); NDIS_SET_PACKET_TIME_SENT(MyPacket,0); NDIS_SET_PACKET_TIME_TO_SEND(MyPacket,0); NDIS_SET_PACKET_STATUS(MyPacket,0); NDIS_SET_PACKET_MEDIA_SPECIFIC_INFO(MyPacket,NULL,0); #ifdef WIN9X NDIS_PACKET_VALID_COUNTS(MyPacket) = FALSE; #endif // WIN9X NdisSend(&status,pAdaptList->BindingHandle,MyPacket); if(status!=NDIS_STATUS_PENDING)//恰巧同步完成发送 { NdisUnchainBufferAtBack(MyPacket,&PktBuffer); NdisFreeBuffer(PktBuffer); NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdaptList); DBGPRINT(("Send immediately completement\n")); } return status; }while(FALSE); if(status!=NDIS_STATUS_SUCCESS) { pIrp->IoStatus.Information=0; pIrp->IoStatus.Status=status; IoCompleteRequest(pIrp,IO_NO_INCREMENT); } return status; }//end function 在发送完成函数中代码是这样的: VOID PtSendComplete( IN NDIS_HANDLE ProtocolBindingContext, IN PNDIS_PACKET Packet, IN NDIS_STATUS Status ) { PADAPT pAdapt = (PADAPT)ProtocolBindingContext; PNDIS_PACKET Pkt; NDIS_HANDLE PoolHandle; PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved); if(SendRsvd->OriginalPkt==NULL&&SendRsvd->pIrp!=NULL)//说明这个包是在派遣例程中发送的。 { PIRP pIrp=SendRsvd->pIrp; PIO_STACK_LOCATION pIrpStack=IoGetCurrentIrpStackLocation(pIrp); NdisDprFreePacket(Packet); ADAPT_DECR_PENDING_SENDS(pAdapt); if(Status==NDIS_STATUS_SUCCESS) { DBGPRINT(("complete function succeed\n")); pIrp->IoStatus.Information=pIrpStack->Parameters.Write.Length; pIrp->IoStatus.Status=STATUS_SUCCESS; } else { DBGPRINT(("complete function failed\n")); pIrp->IoStatus.Information=0; pIrp->IoStatus.Status=STATUS_UNSUCCESSFUL; } IoCompleteRequest(pIrp,IO_NO_INCREMENT); } else //下面是PassThru中的原代码 { Pkt = SendRsvd->OriginalPkt; #ifndef WIN9X NdisIMCopySendCompletePerPacketInfo (Pkt, Packet); #endif NdisDprFreePacket(Packet); NdisMSendComplete(pAdapt->MiniportHandle, Pkt, Status); // // Decrease the outstanding send count // ADAPT_DECR_PENDING_SENDS(pAdapt); }//end else }//end function |
|
沙发#
发布于:2008-09-01 09:21
PktBuffer=pIrp->MdlAddress;
if(status!=NDIS_STATUS_PENDING)//恰巧同步完成发送 { NdisUnchainBufferAtBack(MyPacket,&PktBuffer); NdisFreeBuffer(PktBuffer); ==》这个buf从应用层传过来的吧?能释放吗? NdisFreePacket(MyPacket); ADAPT_DECR_PENDING_SENDS(pAdaptList); DBGPRINT(("Send immediately completement\n")); } |
|
板凳#
发布于:2008-09-01 15:54
你好,谢谢你的回复.这个错误我改了,依然是蓝屏.我的QQ是42371921.能交流一下吗?
|
|
地板#
发布于:2008-09-01 17:45
我是新手,刚刚在弄这方面,好多问题也找不到人问。翻看了前几年的帖子,论坛走了很多热心人,现在冷清多了。
是在执行 NdisSend()这个函数的时候蓝屏吗?你能调试的话把相关的信息发上来最好了。 建议: 1. 虽然说MDI就是PNDIS_BUFFER,但是我感觉buf还是自己分配一下。因为我看到下面的代码好像buf和 pAdapt->RecvPacketPoolHandle还是有点联系的,你用MDL怎么能有这种联系呢? // 分配一个新的包描述符。 NdisAllocatePacket(&Status, &MyPacket, pAdapt->RecvPacketPoolHandle); //分配buf NdisAllocateBuffer(&Status, &MyBuffer, pAdapt->RecvPacketPoolHandle, 2. oob设置我觉的问题也挺多,最好还是用原来的。即使获取不到,像NDIS_SET_PACKET_HEADER_SIZE(MyPacket,0);也可以设置成正确的值吧。 还有 pSendPacket->Private.Head->Next pSendPacket->Private.Tail你还没有设置呢 |
|