【转帖】Ndis中间层驱动自己发包的实现(经典问题)
来源:互联网 发布:神作 英剧 知乎 编辑:程序博客网 时间:2024/05/27 09:46
这个问题,大部分学习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);
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);
- 【转帖】Ndis中间层驱动自己发包的实现(经典问题)
- 【转帖】Ndis中间层驱动自己发包的实现(经典问题)
- 关于 NDIS 中间层驱动的实现方案。。。
- ndis中间层 发包
- 【转帖】NAT在NDIS中间层驱动中的实现
- NAT在NDIS中间层驱动中的实现
- NAT在NDIS中间层驱动中的实现
- NAT在NDIS中间层驱动中的实现
- NAT在NDIS中间层驱动中的实现
- NDIS 中间层驱动开发
- NDIS中间层驱动学习小记
- WinDDK自带的 Passthru NDIS网络中间层驱动 学习
- NDIS中间层的驱动包截获技术教程
- NDIS中间层的驱动包截获技术教程
- NDIS中间层驱动网络连接属性隐藏
- 个人防火墙--中间层NDIS中间层驱动发送和接收流程
- 【转帖】基于PassThru的NDIS中间层驱动程序扩展
- 【转帖】基于PassThru的NDIS中间层驱动程序扩展(完整版)
- SEO一般有哪些步骤或环节?
- SEO菜鸟:SEO知识自测
- COM学习(一)
- SEO服务方式有哪些?
- 符合垃圾自动垃圾回收的标准
- 【转帖】Ndis中间层驱动自己发包的实现(经典问题)
- URL标准化是什么意思?
- Dictionary of Information Security
- .NET Framework版本解析
- Sams Teach Yourself PHP, MySQL and Apache All in One (3rd Edition)
- 尝试initramfs+klibc
- Upgrading Visual Basic 6.0 Applications to Visual Basic .NET and Visual Basic 2005
- 新的开始,一切从头开始
- 提高关键词排名的28个SEO技巧