needsun
驱动牛犊
驱动牛犊
  • 注册日期2008-07-14
  • 最后登录2009-11-12
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望48点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2399回复:3

自己组包用NdisSend发送时为何有时会蓝屏

楼主#
更多 发布于:2008-08-30 17:15
最近在做的这个项目要求把符合一定条件的包放在应用层处理,处理后包的长度变长。一些问题已经解决,如通过在函数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  
king00star
驱动牛犊
驱动牛犊
  • 注册日期2006-08-17
  • 最后登录2014-04-19
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望92点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
沙发#
发布于: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"));
  }
needsun
驱动牛犊
驱动牛犊
  • 注册日期2008-07-14
  • 最后登录2009-11-12
  • 粉丝0
  • 关注0
  • 积分15分
  • 威望48点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-09-01 15:54
你好,谢谢你的回复.这个错误我改了,依然是蓝屏.我的QQ是42371921.能交流一下吗?
king00star
驱动牛犊
驱动牛犊
  • 注册日期2006-08-17
  • 最后登录2014-04-19
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望92点
  • 贡献值0点
  • 好评度15点
  • 原创分0分
  • 专家分0分
地板#
发布于: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你还没有设置呢
游客

返回顶部