【转帖】Ndis中间层驱动自己发包的实现(经典问题) 收藏

这个问题,大部分学习Ndis中间层的人都会去思考,算是一个比较经典的问题了。
到论坛上问,别人只会告诉你大概的方法和步骤,这里贴出具体的代码,希望对研究Ndis中间层的哥们有些帮助:


NDIS_STATUS
MySendPacket (
   NDIS_HANDLE     NdisBindingHandle,
   NDIS_HANDLE     NdisSendPacketPool,
   PVOID           pBuffer,
   ULONG           dwBufferLength
   )
{
   NDIS_STATUS     status;
   PNDIS_PACKET    pSendPacket = NULL;
   PNDIS_BUFFER    pSendPacketBuffer = NULL;
   PUCHAR          pSendBuffer = NULL;
   ULONG           dwSendBufferLength;
   NDIS_PHYSICAL_ADDRESS HighestAcceptableAddress;
   PSEND_RSVD      SendRsvd = NULL;

   if (!NdisBindingHandle)
       return NDIS_STATUS_FAILURE;

   if (!pBuffer)
       return NDIS_STATUS_FAILURE;

   if (dwBufferLength > ETH_MAX_PACKET_SIZE)
       return NDIS_STATUS_FAILURE;

   HighestAcceptableAddress.QuadPart = -1;
   dwSendBufferLength = max(dwBufferLength, ETH_MIN_PACKET_SIZE);

   status = NdisAllocateMemory(&pSendBuffer, dwSendBufferLength, 0, HighestAcceptableAddress);
   if (status != NDIS_STATUS_SUCCESS)
   {
       return status;
   }

   RtlZeroMemory(pSendBuffer, dwSendBufferLength);
   RtlMoveMemory(pSendBuffer, pBuffer, dwSendBufferLength);

   NdisAllocatePacket(&status, &pSendPacket, NdisSendPacketPool);
   if (status != NDIS_STATUS_SUCCESS)
   {
       NdisFreeMemory(pSendBuffer, dwSendBufferLength, 0);
      
       return status;
   }

   NdisAllocateBuffer( &status,
                       &pSendPacketBuffer,
                       NdisSendPacketPool,
                       pSendBuffer,
                       dwSendBufferLength );
   if (status != NDIS_STATUS_SUCCESS)
   {
       NdisFreeMemory(pSendBuffer, dwSendBufferLength, 0);
       NdisDprFreePacket(pSendPacket);

       return status;
   }

   NdisChainBufferAtFront(pSendPacket, pSendPacketBuffer);

   SendRsvd = (PSEND_RSVD)(pSendPacket->ProtocolReserved);
   SendRsvd->OriginalPkt = NULL; //注意这里

   pSendPacket->Private.Head->Next=NULL;
   pSendPacket->Private.Tail=NULL;

   //NDIS_SET_PACKET_HEADER_SIZE(pSendPacket, 14);
   NdisSetPacketFlags(pSendPacket, NDIS_FLAGS_DONT_LOOPBACK);

   NdisSend(&status, NdisBindingHandle, pSendPacket);
   if (status != STATUS_PENDING)
   {
       NdisUnchainBufferAtFront(pSendPacket ,&pSendPacketBuffer);
       NdisQueryBufferSafe( pSendPacketBuffer,
                            (PVOID *)&pSendBuffer,
                            &dwSendBufferLength,
                            HighPagePriority );
       NdisFreeBuffer(pSendPacketBuffer);
       NdisFreeMemory(pSendBuffer, dwSendBufferLength, 0);
       NdisDprFreePacket(pSendPacket);
   }

   return status;
}

注意:NdisSend如果是立刻完成,没有Pending的话,你需要在NdisSend返回后释放掉刚才分配的资源,否则是Pending的话,我们就要等发生包这个事件真正完成是的Complete例程里面去释放分配的资源。

在函数PtSendComplete中:
PSEND_RSVD        SendRsvd;
SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
Pkt = SendRsvd->OriginalPkt;
// ProtocolReserved是个可以自己放自己数据的地方, passthru用这个存放原始包的地址, 而我们自己构造包的时候把SendRsvd->OriginalPkt设为了NULL,所以很容易判断出那个已完成发送的包是passtru的,哪 些是我们构造的


       if (!Pkt )
       {
           NdisUnchainBufferAtFront(Packet, &pMySendPacketBuffer);

           if (pMySendPacketBuffer)
           {
               NdisQueryBufferSafe( pMySendPacketBuffer,
                                    (PVOID *)&pMySendBuffer,
                                    &dwMySendBufferLength,
                                    HighPagePriority );
               if (pMySendBuffer && dwMySendBufferLength)
               {
                   NdisFreeMemory(pMySendBuffer, dwMySendBufferLength, 0);
               }

               NdisFreeBuffer( pMySendPacketBuffer );
           }

            NdisDprFreePacket(Packet);

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/floweronwarmbed/archive/2008/11/01/3202065.aspx

转载于:https://www.cnblogs.com/xuneng/archive/2009/11/30/1613452.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1 NDIS中间层驱动程序 2 1.1 NDIS中间层驱动程序(NDIS Intermediate Drivers)概述 2 1.2 NDIS中间层驱动程序的用途 4 1.3 NDIS中间层驱动程序的开发环境 4 2 NDIS中间层驱动程序的开发 4 2.1 可分页和可丢弃代码 4 2.2 共享资源的访问同步 5 2.3 中间层驱动程序的DriverEntry函数 5 2.3.1 注册NDIS中间层驱动程序 6 2.3.1.1 注册中间层驱动程序的Miniport 6 2.3.1.2 注册中间层驱动程序的协议 8 2.4 中间层驱动程序的动态绑定 11 2.4.1 打开中间层驱动程序下层的适配器 12 2.4.2 微端口(Miniport)初始化 12 2.4.3 中间层驱动程序查询和设置操作 13 2.4.3.1 发布设置和查询请求 14 2.4.3.2 响应设置和查询请求 15 2.4.4 作为面向连接客户程序注册中间层驱动程序 15 2.5 中间层驱动程序数据包管理 17 2.5.1.1 重用数据包 18 2.6 中间层驱动程序的限制 19 2.7 中间层驱动程序接收数据 19 2.7.1 下边界面向无连接的中间层驱动程序接收数据 19 2.7.1.1 在中间层驱动程序中实现ProtocolReceivePacket处理程序 20 2.7.1.2 在中间层驱动程序中实现ProtocolReceive处理程序 21 2.7.1.3 下边界面向无连接中间层驱动程序接收OOB数据信息 22 2.7.2 下边界面向连接的中间层驱动程序接收数据 22 2.7.2.1 在中间层驱动程序中实现ProtocolCoReceivePacket处理程序 23 2.7.2.2 在下边界面向连接的中间层驱动程序中接收OOB数据信息 23 2.7.3 向高层驱动程序指示接收数据包 23 2.8 通过中间层驱动程序传输数据包 23 2.8.1 传递介质相关信息 25 2.9 处理中间层驱动程序的PnP事件和PM事件 26 2.9.1 处理OID_PNP_XXX查询和设置 26 2.9.2 中间层驱动程序ProtocolPnPEvent处理程序的实现 27 2.9.3 处理规定的电源请求 28 2.9.3.1 睡眠状态的电源设置请求 28 2.9.3.2 工作状态的电源设置请求 29 2.10 中间层驱动程序复位操作 29 2.11 中间层驱动程序拆除绑定操作 30 2.12 中间层驱动程序状态指示 31 3 负载平衡和失效替换 31 3.1 关于LBFO 31 3.2 指定对LBFO的支持 32 3.3 在微端口驱动程序上实现LBFO 32 3.3.1 初始化微端口束 33 3.3.2 平衡微端口驱动程序的工作量 33 3.3.3 在主微端口失效后提升一个次微端口 34 4 安装网络组件 34 4.1 用于安装网络组件的组件和文件 34 4.2 创建网络INF文件 35 4.2.1 网络INFS文件名的约定 35 4.2.2 网络INF文件的版本节 35 4.2.3 网络INF文件的模型节 36 4.2.4 INF文件的DDInstall节 37 4.2.5 删除节 38 4.2.6 ControlFlags节 39 4.2.7 网络INF文件的add-registry-sections 39
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值