﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-剑父的技术之路-随笔分类-驱动开发</title><link>http://www.cppblog.com/huangjianfu/category/10603.html</link><description>网络信息安全</description><language>zh-cn</language><lastBuildDate>Mon, 01 Jun 2009 05:43:28 GMT</lastBuildDate><pubDate>Mon, 01 Jun 2009 05:43:28 GMT</pubDate><ttl>60</ttl><item><title>驱动文档阅读（一）</title><link>http://www.cppblog.com/huangjianfu/archive/2009/05/31/85702.html</link><dc:creator>黄剑父</dc:creator><author>黄剑父</author><pubDate>Sun, 31 May 2009 06:25:00 GMT</pubDate><guid>http://www.cppblog.com/huangjianfu/archive/2009/05/31/85702.html</guid><wfw:comment>http://www.cppblog.com/huangjianfu/comments/85702.html</wfw:comment><comments>http://www.cppblog.com/huangjianfu/archive/2009/05/31/85702.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/huangjianfu/comments/commentRss/85702.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/huangjianfu/services/trackbacks/85702.html</trackback:ping><description><![CDATA[【DriverEntry】<br>Each driver must have a [DriverEntry] routine,which initializes driver-wide data structures and resources.The I/O manager calls the DriverEntry routine when it loads the driver.<br>DriverEntry is the first routine called after a driver loaded,and is responsible for initializing the driver.<br>DriverEntry routine are called in the context of a system thread at IRQL=PASSIVE_LEVEL.<br><br><br>
<img src ="http://www.cppblog.com/huangjianfu/aggbug/85702.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/huangjianfu/" target="_blank">黄剑父</a> 2009-05-31 14:25 <a href="http://www.cppblog.com/huangjianfu/archive/2009/05/31/85702.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>__try,__except,__finally</title><link>http://www.cppblog.com/huangjianfu/archive/2009/05/31/86262.html</link><dc:creator>黄剑父</dc:creator><author>黄剑父</author><pubDate>Sun, 31 May 2009 06:24:00 GMT</pubDate><guid>http://www.cppblog.com/huangjianfu/archive/2009/05/31/86262.html</guid><wfw:comment>http://www.cppblog.com/huangjianfu/comments/86262.html</wfw:comment><comments>http://www.cppblog.com/huangjianfu/archive/2009/05/31/86262.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/huangjianfu/comments/commentRss/86262.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/huangjianfu/services/trackbacks/86262.html</trackback:ping><description><![CDATA[__try Begins a guarded body of code. Used with the __except keyword to construct an exception handler, or with the __finally keyword to construct a termination handler. <br>__except Begins a block of code that is executed only when an exception occurs within its associated __try block. <br>__finally Begins a block of code that is executed whenever the flow of control leaves its associated __try block. <br>__leave Allows for immediate termination of the __try block without causing abnormal termination and its performance penalty.
<img src ="http://www.cppblog.com/huangjianfu/aggbug/86262.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/huangjianfu/" target="_blank">黄剑父</a> 2009-05-31 14:24 <a href="http://www.cppblog.com/huangjianfu/archive/2009/05/31/86262.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转：NDIS 中间层驱动（IM Driver）的安装与卸载过程</title><link>http://www.cppblog.com/huangjianfu/archive/2009/05/19/83389.html</link><dc:creator>黄剑父</dc:creator><author>黄剑父</author><pubDate>Tue, 19 May 2009 09:16:00 GMT</pubDate><guid>http://www.cppblog.com/huangjianfu/archive/2009/05/19/83389.html</guid><wfw:comment>http://www.cppblog.com/huangjianfu/comments/83389.html</wfw:comment><comments>http://www.cppblog.com/huangjianfu/archive/2009/05/19/83389.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/huangjianfu/comments/commentRss/83389.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/huangjianfu/services/trackbacks/83389.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">一．绑定过程</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt"><o:p></o:p></span></strong></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>1. DriverEntry</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">中间层驱动对上层来说，扮演一个</span><span lang=EN-US>Miniport Driver</span><span style="FONT-FAMILY: 宋体">的角色，它在上边沿向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册一组</span><span lang=EN-US>Miniportxxx</span><span style="FONT-FAMILY: 宋体">函数；对于下层</span><span lang=EN-US>Miniport Driver</span><span style="FONT-FAMILY: 宋体">来说，中间层驱动扮演一个</span><span lang=EN-US>Protocol Driver</span><span style="FONT-FAMILY: 宋体">的角色，因此它在下边沿向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册一组</span><span lang=EN-US>Protocolxxx</span><span style="FONT-FAMILY: 宋体">函数。</span><span lang=EN-US>Miniport Driver</span><span style="FONT-FAMILY: 宋体">通过调用</span><span lang=EN-US>NdisMRegisterMiniport</span><span style="FONT-FAMILY: 宋体">向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册一组</span><span lang=EN-US>MiniportXxx</span><span style="FONT-FAMILY: 宋体">函数；</span><span lang=EN-US>Protocol Driver </span><span style="FONT-FAMILY: 宋体">通过调用</span><span lang=EN-US> NdisRegisterProtocol</span><span style="FONT-FAMILY: 宋体">向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册一组</span><span lang=EN-US>ProtocolXxx</span><span style="FONT-FAMILY: 宋体">函数。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">首先通过调用</span><span lang=EN-US>NdisMInitializeWrapper(&amp;NdisWrapperHandle, DriverObject, RegistryPath, NULL);</span><span style="FONT-FAMILY: 宋体">来初始化</span><span lang=EN-US>NdisWrapperHandle</span><span style="FONT-FAMILY: 宋体">，该句柄用来代表</span><span lang=EN-US>IM Driver</span><span style="FONT-FAMILY: 宋体">的自身。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">接着调用</span><span lang=EN-US>NdisIMRegisterLayeredMiniport</span><span style="FONT-FAMILY: 宋体">来向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册一组</span><span lang=EN-US>MiniportXxx</span><span style="FONT-FAMILY: 宋体">函数，返回指向</span><span lang=EN-US>Miniport</span><span style="FONT-FAMILY: 宋体">的</span><span lang=EN-US>DriverHandle</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">随后调用</span><span lang=EN-US>NdisRegisterProtocol</span><span style="FONT-FAMILY: 宋体">来向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册一组</span><span lang=EN-US>Protocolxxx</span><span style="FONT-FAMILY: 宋体">函数，返回指向</span><span lang=EN-US>Protocol</span><span style="FONT-FAMILY: 宋体">的</span><span lang=EN-US>ProtHandle</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">然后调用</span><span lang=EN-US>NdisIMAssociateMiniport(DriverHandle, ProtHandle);</span><span style="FONT-FAMILY: 宋体">将两者绑定。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>2. PtBindAdapter</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>NDIS</span><span style="FONT-FAMILY: 宋体">在完成第一步之后，将会调用</span><span lang=EN-US>PtBindAdapter</span><span style="FONT-FAMILY: 宋体">来完成对适配器的绑定（注意：此函数的调用次数是根据用户电脑上的适配器数目而定的，一般至少有两块，会有一块叫</span><span lang=EN-US>NDISWANIP</span><span style="FONT-FAMILY: 宋体">），</span><span lang=EN-US>PtBindAdapter</span><span style="FONT-FAMILY: 宋体">中有用的参数主要是</span><span lang=EN-US>DeviceName</span><span style="FONT-FAMILY: 宋体">和</span><span lang=EN-US>SystemSpecific1,</span><span style="FONT-FAMILY: 宋体">其中</span><span lang=EN-US>DeviceName</span><span style="FONT-FAMILY: 宋体">是下层</span><span lang=EN-US>NIC</span><span style="FONT-FAMILY: 宋体">驱动的服务名，</span><span lang=EN-US>SystemSpecific1</span><span style="FONT-FAMILY: 宋体">可以用来读取注册表中相关的值。（参考注册表</span><span lang=EN-US>HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Linkage</span><span style="FONT-FAMILY: 宋体">下的</span><span lang=EN-US>Bind</span><span style="FONT-FAMILY: 宋体">子键值）</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">首先调用</span><span lang=EN-US>NdisOpenProtocolConfiguration </span><span style="FONT-FAMILY: 宋体">，</span><span lang=EN-US>NdisReadConfiguration</span><span style="FONT-FAMILY: 宋体">来读取注册表信息，然后初始化</span><span lang=EN-US>PADAPT pAdapt</span><span style="FONT-FAMILY: 宋体">结构体。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">接着调用</span><span lang=EN-US>NdisOpenAdapter</span><span style="FONT-FAMILY: 宋体">来将</span><span lang=EN-US>IM</span><span style="FONT-FAMILY: 宋体">的下层协议驱动（</span><span lang=EN-US>ProtHandle</span><span style="FONT-FAMILY: 宋体">）绑定适配器。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">调用</span><span lang=EN-US>NdisIMInitializeDeviceInstanceEx</span><span style="FONT-FAMILY: 宋体">来触发对</span><span lang=EN-US>MPInitialize</span><span style="FONT-FAMILY: 宋体">的调用</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>3. MPInitialize</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">在</span><span lang=EN-US>MpInitialize</span><span style="FONT-FAMILY: 宋体">里面主要做三件事情：</span> </p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang=EN-US>1). </span><span style="FONT-FAMILY: 宋体">判断介质类型</span> </p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang=EN-US>2). </span><span style="FONT-FAMILY: 宋体">调用</span><span lang=EN-US>NdisMSetAttributesEx</span><span style="FONT-FAMILY: 宋体">设置一些特性</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span lang=EN-US>3). </span><span style="FONT-FAMILY: 宋体">调用</span><span lang=EN-US>PtRegisterDevice</span><span style="FONT-FAMILY: 宋体">函数向</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">注册设备</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>4. PtRegisterDevice</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">在</span><span lang=EN-US>PtRegisterDevice</span><span style="FONT-FAMILY: 宋体">里，主要是设置</span><span lang=EN-US>IM Driver</span><span style="FONT-FAMILY: 宋体">自己要处理的一些派遣例程和注册设备名和设备符号链接名。要注意的是，这个函数提供的功能是为整个设备服务而不是每个适配器都需要注册，所以通过一个全局变量</span><span lang=EN-US>MiniportCount</span><span style="FONT-FAMILY: 宋体">来控制。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-INDENT: 21pt"><span style="FONT-FAMILY: 宋体">在这里，定义了</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">PDRIVER_DISPATCH</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 新宋体"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="COLOR: rgb(1,0,1)">DispatchTable</span>[<span style="COLOR: rgb(1,0,1)">IRP_MJ_MAXIMUM_FUNCTION</span>+1];<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">然后如下的设置：<span lang=EN-US>DispatchTable</span></span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 新宋体">[<span style="COLOR: rgb(1,0,1)">IRP_MJ_CREATE</span>] = <span style="COLOR: rgb(1,0,1)">DevOpen</span>;</span><span lang=EN-US style="FONT-SIZE: 9pt">&#8230;</span><span lang=EN-US style="FONT-SIZE: 9pt; FONT-FAMILY: 新宋体"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">接着调用</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">NdisMRegisterDevice</span><span style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">来</span><span style="FONT-FAMILY: 宋体">注册设备名和设备符号链接名。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><strong><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体">二．卸载过程</span></strong><strong><span lang=EN-US style="FONT-SIZE: 12pt"><o:p></o:p></span></strong></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>1. PtUnbindAdapter</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">针对每个绑定的适配器，首先查看对</span><span lang=EN-US>IM</span><span style="FONT-FAMILY: 宋体">的</span><span lang=EN-US>miniport</span><span style="FONT-FAMILY: 宋体">是否有还在排队的请求，如果有，则先调用</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">PtRequestComplete</span><span style="FONT-FAMILY: 宋体">完成它（返回</span><span lang=EN-US>NDIS_STATUS_FAILURE</span><span style="FONT-FAMILY: 宋体">），然后查看状态是否为</span><span lang=EN-US>pending</span><span style="FONT-FAMILY: 宋体">，是的话则调用</span><span lang=EN-US>NdisIMCancelInitializeDeviceInstance</span><span style="FONT-FAMILY: 宋体">。再调用</span><span lang=EN-US>NdisIMDeInitializeDeviceInstance</span><span style="FONT-FAMILY: 宋体">来卸载设备，在此会触发对</span><span lang=EN-US>MPHalt</span><span style="FONT-FAMILY: 宋体">的调用。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>2. MPHalt</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">在</span><span lang=EN-US>MPHalt</span><span style="FONT-FAMILY: 宋体">里，首先调用</span><span lang=EN-US>PtDeregisterDevice</span><span style="FONT-FAMILY: 宋体">来卸载设备，然后调用</span><span lang=EN-US>NdisCloseAdapter</span><span style="FONT-FAMILY: 宋体">关闭绑定的适配器。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>3. PtDeregisterDevice (MiniportCount == 0?)</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">在</span><span lang=EN-US>PtDeregisterDevice </span><span style="FONT-FAMILY: 宋体">里，调用</span><span lang=EN-US>NdisMDeregisterDevice</span><span style="FONT-FAMILY: 宋体">来卸载设备。同</span><span lang=EN-US>PtRegisterDevice</span><span style="FONT-FAMILY: 宋体">类似，要注意的是，这个函数提供的功能是为整个设备服务而不是每个适配器都需要注册，所以通过一个全局变量</span><span lang=EN-US>MiniportCount</span><span style="FONT-FAMILY: 宋体">来控制。只有最后一个绑定的适配器卸载时，才调用</span><span lang=EN-US>NdisMDeregisterDevice</span><span style="FONT-FAMILY: 宋体">。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>4. PtUnloadProtocol</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">在</span><span lang=EN-US>CloseAdapterComplete</span><span style="FONT-FAMILY: 宋体">完成后，</span><span lang=EN-US>NDIS</span><span style="FONT-FAMILY: 宋体">会调用</span><span lang=EN-US>PtUnloadProtocol</span><span style="FONT-FAMILY: 宋体">来完成下层绑定的协议驱动（</span><span lang=EN-US style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">ProtHandle</span><span style="FONT-SIZE: 9pt; COLOR: rgb(1,0,1); FONT-FAMILY: 新宋体">）的卸载，调用<span lang=EN-US>NdisDeregisterProtocol</span>函数。</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US>5. PtUnload</span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="FONT-FAMILY: 宋体">首先，要说明的是，在</span><span lang=EN-US>DriverEntry</span><span style="FONT-FAMILY: 宋体">函数里，有注册该函数（</span><span lang=EN-US>NdisMRegisterUnloadHandler(NdisWrapperHandle, PtUnload);</span><span style="FONT-FAMILY: 宋体">）。该函数是整个卸载过程的最后一步，在这里，会继续完成对绑定的上层</span><span lang=EN-US>miniport</span><span style="FONT-FAMILY: 宋体">，下层的</span><span lang=EN-US>protocol</span><span style="FONT-FAMILY: 宋体">的卸载（其实</span><span lang=EN-US>protocol</span><span style="FONT-FAMILY: 宋体">的卸载在第</span><span lang=EN-US>4</span><span style="FONT-FAMILY: 宋体">步已经完成），调用如下两个函数</span><span lang=EN-US>PtUnloadProtocol</span><span style="FONT-FAMILY: 宋体">，</span><span lang=EN-US>NdisIMDeregisterLayeredMiniport</span><span style="FONT-FAMILY: 宋体">。</span></p>
<img src ="http://www.cppblog.com/huangjianfu/aggbug/83389.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/huangjianfu/" target="_blank">黄剑父</a> 2009-05-19 17:16 <a href="http://www.cppblog.com/huangjianfu/archive/2009/05/19/83389.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>