NDIS IM 驱动那些事情
最近不知道为什么开始学习windows NDIS驱动开发,用的是寒江独钓的例子,其实他的改的代码也就一点点,说的有用的东西也就那么多,不过还是感谢他出了这么一本书,不然这真的就没有一本稍微好一点的书籍来说windows 的NDIS书籍了。
这方面的知识貌似大家都不太愿意说,我在网上找了好久无非就是那几篇经典的例子,不过网上代码有点错误有点问题,而且核心都不原因讲解。。
比喻大家都会遇到问题,怎么在NDIS中间层发送自定义数据包的问题? 一般我们发送都会蓝屏,网上有类似的文章。
http://blog.csdn.net/floweronwarmbed/article/details/3202065
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 = -;
dwSendBufferLength = max(dwBufferLength, ETH_MIN_PACKET_SIZE); status = NdisAllocateMemory(&pSendBuffer, dwSendBufferLength, , 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, ); return status;
} NdisAllocateBuffer( &status,
&pSendPacketBuffer,
NdisSendPacketPool,
pSendBuffer,
dwSendBufferLength );
if (status != NDIS_STATUS_SUCCESS)
{
NdisFreeMemory(pSendBuffer, dwSendBufferLength, );
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, );
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, );
} NdisFreeBuffer( pMySendPacketBuffer );
} NdisDprFreePacket(Packet);
但这里代码比较模糊也没有说明蓝屏的本质,只是PtSendComplete里面要释放原因。。。
其实这里我测试得出,其实你释放不释放最多内存泄漏,比喻你的程序内存泄漏基本不会马上崩溃,应用程序崩溃一般是我们内存越界,类似系统不过是一个最大的应用程序。然后自己也在网上看到类似不要调用NdisMSendComplete类似的东西,这个API 通知上层驱动释放资源 等等问题,显然我NidsSend是在自己中间层调用根本没有上层,那么上层怎么释放呢!!显然就报错嘛?蓝屏还用说吗??我发现驱动蓝屏比较恐怖的事情,这2周学习感觉还好,只要你内存操作注意点时候,基本上不会蓝屏,内存泄漏感觉只会影响驱动稳定性。
貌似上面的MySendPacket 里面那个
NdisAllocateBuffer( &status,
&pSendPacketBuffer,
NdisSendPacketPool,
pSendBuffer,
dwSendBufferLength );
这里应该是错误,
NdisSendPacketPool 这个句柄明显是分配Packet。
我看一下NdisAllocateBuffer 句柄应该是自己调用的VOID
NdisAllocateBufferPool(
OUT PNDIS_STATUS Status,
OUT PNDIS_HANDLE PoolHandle,
IN UINT NumberOfDescriptors
);
。。
我不知道是不是他们估计要把代码写错,如果能混用的话感觉微软就没有必要提供NdisSendPacketPool的函数了。
等我自己一个项目整体完成了,然后把代码分享出来。-----------》实现那种局域网管理软件使用ARP欺骗进行管理的核心功能。
前几天看到一个厉害人吧,感觉能力比较强,看他的文章他非常熟悉linux的内核。然后开发起windows驱动非常顺手,看来linux真是c/c++的乐园吧。。。
有时间还得仔细学习学习。
最后我贴一下我写的ptComple的函数的API 其实很简单了。。
VOID
PtSendComplete(
IN NDIS_HANDLE ProtocolBindingContext,
IN PNDIS_PACKET Packet,
IN NDIS_STATUS Status
)
/*++ Routine Description: Called by NDIS when the miniport below had completed a send. We should
complete the corresponding upper-edge send this represents. Arguments: ProtocolBindingContext - Points to ADAPT structure
Packet - Low level packet being completed
Status - status of send Return Value: None --*/
{
PADAPT pAdapt = (PADAPT)ProtocolBindingContext;
PNDIS_PACKET Pkt;
NDIS_HANDLE PoolHandle; PSEND_RSVD tempRsvd;
PNDIS_BUFFER pMySendPacketBuffer = NULL;
UINT dwMySendBufferLength = ;
PVOID pMySendBuffer = NULL; tempRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
Pkt = tempRsvd->OriginalPkt; if (Pkt == (PNDIS_PACKET) )
{
NdisUnchainBufferAtFront(Packet, &pMySendPacketBuffer);
if (pMySendPacketBuffer)
{
NdisQueryBufferSafe( pMySendPacketBuffer,
(PVOID *)&pMySendBuffer,
&dwMySendBufferLength,
HighPagePriority );
if (pMySendBuffer && dwMySendBufferLength)
{
NdisFreeMemory(pMySendBuffer, dwMySendBufferLength, );
} NdisFreeBuffer( pMySendPacketBuffer ); NdisFreePacket(Packet);
}
return;
} #ifdef NDIS51
//
// Packet stacking:
//
// Determine if the packet we are completing is the one we allocated. If so, then
// get the original packet from the reserved area and completed it and free the
// allocated packet. If this is the packet that was sent down to us, then just
// complete it
//
//DbgPrint("我在NDIS51发送完了");
PoolHandle = NdisGetPoolFromPacket(Packet);
if (PoolHandle != pAdapt->SendPacketPoolHandle)
{
//
// We had passed down a packet belonging to the protocol above us.
//
// DBGPRINT(("PtSendComp: Adapt %p, Stacked Packet %p\n", pAdapt, Packet)); NdisMSendComplete(pAdapt->MiniportHandle,
Packet,
Status);
}
else
#endif // NDIS51
{ PSEND_RSVD SendRsvd; SendRsvd = (PSEND_RSVD)(Packet->ProtocolReserved);
Pkt = SendRsvd->OriginalPkt; //DbgPrint("我没有在NDIS51调用哦,熊熊你知道了蓝屏是为什么了"); #ifndef WIN9X
NdisIMCopySendCompletePerPacketInfo (Pkt, Packet);
#endif NdisDprFreePacket(Packet); NdisMSendComplete(pAdapt->MiniportHandle,
Pkt,
Status);
}
//
// Decrease the outstanding send count
//
ADAPT_DECR_PENDING_SENDS(pAdapt);
}
NDIS IM 驱动那些事情的更多相关文章
- 基于PassThru的NDIS中间层驱动程序扩展
基于PassThru的NDIS中间层驱动程序扩展 独孤求真 概要:开发一个NDIS驱动是一项相对复杂的工作,这一方面是由于核心驱动本身 ...
- NDIS中间层驱动实现截获数据包、包过滤功能
1.包截获功能 http://wenku.baidu.com/view/43960751f01dc281e53af055.html 2.包过滤功能 http://wenku.baidu.com/lin ...
- Windows网络驱动、NDIS驱动(微端口驱动、中间层驱动、协议驱动)、TDI驱动(网络传输层过滤)、WFP(Windows Filtering Platform)
catalog . 引言 . Windows 2000网络结构和OSI模型 . NDIS驱动 . NDIS微端口驱动编程实例 . NDIS中间层驱动编程实例 . NDIS协议层驱动编程实例 . TDI ...
- Windows内核安全与驱动开发
这篇是计算机中Windows Mobile/Symbian类的优质预售推荐<Windows内核安全与驱动开发>. 编辑推荐 本书适合计算机安全软件从业人员.计算机相关专业院校学生以及有一定 ...
- Windows驱动开发(中间层)
Windows驱动开发 一.前言 依据<Windows内核安全与驱动开发>及MSDN等网络质料进行学习开发. 二.初步环境 1.下载安装WDK7.1.0(WinDDK\7600.16385 ...
- 达人眼中的WINCE网络驱动
实际上在WinCE上开发网络驱动,比如设计一个NIC驱动, 大多数情况,是从XP移植NDIS Miniport驱动(小端口驱动)到WinCE.什么是ndis?Ndis做什么用的? 什么是minipor ...
- 从串口驱动的移植看linux2.6内核中的驱动模型 platform device & platform driver【转】
转自:http://blog.csdn.net/bonnshore/article/details/7979705 写在前面的话: 博主新开了个人站点:你也可以在这里看到这篇文章,点击打开链接 本文是 ...
- 科普NDIS封包过滤
闲言: 这个月一直在学习NDIS驱动编程,杂七杂八的资料都看个遍了,做了点笔记,捋捋思路,发上来备忘. Ps:只是小菜的一点学习笔记,没什么技术含量,不过版主如果觉得对大家稍微有点帮助的话 ...
- 汉澳sinox通过ndis执行windows驱动程序
汉澳sinox不仅能通过wine执行windows应用程序.还能通过ndis执行windows驱动程序 汉澳sinox使用 Windows NDIS 驱动程序 详细实现方法是用ndisgen把wind ...
随机推荐
- 插入三层treeview代码
#region treetView加载 private void treeViewLoad() { DataView dv = navds.tbSiteKind.AsDataView(); treeV ...
- Spring3.0 AOP 详解
一.什么是 AOP. AOP(Aspect Orient Programming),也就是面向切面编程.可以这样理解,面向对象编程(OOP)是从静态角度考虑程序结构,面向切面编程(AOP)是从动态角度 ...
- Unity3D - 关于Dynamic和Static
含有Collider和RigidBody的GameObject, Unity视之为Dynamic 含有Collider的GameObject, Unity视之为Static 如果Static的物体发生 ...
- Codeforces Round #Pi (Div. 2) D. One-Dimensional Battle Ships set区间分解
D. One-Dimensional Battle ShipsTime Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/co ...
- 保存form配置信息INI
(* 功能:IniFormState1 保存和读取 窗体的大小2 保存和读取 窗体在屏幕上的位置//让程序第1次出现在屏幕的中心点获取屏幕的中心点POSITION:poScreenCenter //不 ...
- 线性求中位数 poj2388
在做uva11300时,遇到了n < 1000 000的中位数,就看了一下线性求中位数. 该算法的最差时间复杂度为O(N^2),期望时间复杂度为O(N),证明推理详见算法导论P110. 和快排的 ...
- 面试题——设计一个程序:运行报错Stack Overflow Error
所谓Stack Overflow就是栈里面放的东西太多了,溢出了. 大家知道栈里面存放的是基本数据类型还有引用类型. 下面看这个程序 class Test { public static void m ...
- MapReduce数据连接
对于不同文件里的数据,有时候有相应关系,须要进行连接(join),获得一个新的文件以便进行分析.比方有两个输入文件a.txt,b.txt,当中的数据格式分别例如以下 1 a 2 b 3 c 4 d 1 ...
- 简化版可用于多线程的logger
logger 嘛要高效,要简单.废话不多话. GitHub 地址 https://github.com/goldli/logger 本文所说的logger使用System.Logger做为NameSp ...
- Jordan Lecture Note-12: Kernel典型相关分析(Kernel Canonical Correlation Analysis, KCCA).
Kernel典型相关分析 (一)KCCA 同样,我们可以引入Kernel函数,通过非线性的坐标变换达到之前CCA所寻求的目标.首先,假设映射$\Phi_X: x\rightarrow \Phi_X(x ...