<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>windows驱动(IFS/NDIS)</title><link>http://blog.vckbase.com/windowssky/category/1137.html</link><description>windows驱动(IFS/NDIS)</description><managingEditor>垃圾一堆</managingEditor><dc:language>zh-CHS</dc:language><generator>.Text Version 0.958.2004.214</generator><item><dc:creator>垃圾一堆</dc:creator><title>Recognizer &amp; FS &amp; Filter</title><link>http://blog.vckbase.com/windowssky/archive/2007/08/08/28144.html</link><pubDate>Wed, 08 Aug 2007 08:55:00 GMT</pubDate><guid>http://blog.vckbase.com/windowssky/archive/2007/08/08/28144.html</guid><wfw:comment>http://blog.vckbase.com/windowssky/comments/28144.html</wfw:comment><comments>http://blog.vckbase.com/windowssky/archive/2007/08/08/28144.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.vckbase.com/windowssky/comments/commentRss/28144.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/windowssky/services/trackbacks/28144.html</trackback:ping><description>&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;注一：&lt;BR&gt;File system recognizer 文件系统识别器(下文简称为recognizer)&lt;BR&gt;File system&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 文件系统&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (下文简称为fs)&lt;BR&gt;File system filter&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 文件系统过滤器(下文简称为filter)&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;文件系统识别器是一个标准的NT内核模式驱动程序;它只实现一项功能:检查物理介质设备,如果它能够识别存储介质的格式便加载相应的文件系统驱动程序,利用它主要是为节约系统内存,文件系统驱动程序没用到时为什么让他在内存中呢?&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 文件系统过滤驱动的一般处理流程(参照sfilter)：&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverEntry&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||初始化dispatch表中的IRP_MJ_FILE_SYSTEM_CONTROL&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||routine &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverObject-&amp;gt;MajorFunction[IRP_MJ_FILE_SYSTEM_CONTROL] = SfFsControl ...&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||注册一个SfFsNotification;当文件系统或文件系统识别器&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||registers or unregisters时被调用&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IoRegisterFsRegistrationChange(DriverObject, SfFsNotification)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \/&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SfFsNotification(PDEVICE_OBJECT DeviceObject, BOOLEAN FsActive)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; || FsActive&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; TRUE &amp;lt;----------\/------------&amp;gt; FALSE&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;IoAttachDeviceToDeviceStack&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IoDetachDevice&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;/-------\/-------&amp;gt;Attach to (Filesystem)-----------------\IRP_MJ_FILE_SYSTEM_CONTROL&lt;BR&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |MN:IRP_MN_MOUNT_VOLUME&lt;BR&gt;&amp;nbsp;\----------------&amp;gt;Attach to (recognizer)&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |你就尽管Mount,只要fs&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |处理状态为STATUS_SUCCESS;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||MJ:IRP_MJ_FILE_SYSTEM_CONTROL&amp;nbsp;&amp;nbsp; |fs中关于卷的Mount处理&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |参见FatMountVolume函数&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; SfFsControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /\filter其他处理参见sfilter&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||MN:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; /--------------\/-----------------------------\&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |IRP_MN_MOUNT_VOLUME&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;filter等待recognizer处理完成&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp; /-----\/--&amp;gt;STATUS_FS_DRIVER_REQUIRED(1)---|\&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; | &lt;BR&gt;&amp;nbsp;&amp;nbsp; |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp; \--------&amp;gt;STATUS_UNRECOGNIZED_VOLUME(2)---||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \/&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |&lt;BR&gt;不论结果是哪一个,filter什么动作也没有;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;但IO管理器收到recognizer处理结果后,处理各不相同:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;(1)表示recognizer认识这个卷,但对应的fs还没启动&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;BR&gt;(2)表示recognizer不认识这个卷,对应的fs不能处理&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;如果是第一种情况I/O管理器就会向这个设备发送---------------||IRP_MN_LOAD_FILE_SYSTEM&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||原来我们一直挂接在recognizer上的&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \/&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IoDetachDevice(recognizer)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; wait recognizer load fs status&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Other status&amp;lt;-----------\/-----------&amp;gt;STATUS_SUCCESS&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||recognizer加载对应的fs失败&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||只好还挂到recognizer上&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; \/&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IoAttachDeviceToDeviceStack(recognizer) &lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;注二：IoRegisterFsRegistrationChange函数&lt;BR&gt;&lt;BR&gt;在winxp,win2003下会对已加载的文件系统重新枚举一遍&lt;BR&gt;而nt4.0和win2000下则不会,具体原因代码见...&lt;BR&gt;(留意一下IopNotifyAlreadyRegisteredFileSystems的作用和实现)&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" size=2&gt;//win2000&lt;BR&gt;NTSTATUS&lt;BR&gt;IoRegisterFsRegistrationChange(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDRIVER_OBJECT DriverObject,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;/*++&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Routine Description:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This routine registers the specified driver's notification routine to be&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; invoked whenever a file system registers or unregisters itself as an active&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; file system in the system.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Arguments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverObject - Pointer to the driver object for the driver.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverNotificationRoutine - Address of routine to invoke when a file system&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; registers or unregisters itself.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Return Value:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; The return status is the final value of the function.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;--*/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PNOTIFICATION_PACKET nPacket;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PAGED_CODE();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Begin by attempting to allocate storage for the shutdown packet.&amp;nbsp; If&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // one cannot be allocated, simply return an appropriate error.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket = ExAllocatePoolWithTag( PagedPool,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sizeof( NOTIFICATION_PACKET ),&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'sFoI' );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!nPacket) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return STATUS_INSUFFICIENT_RESOURCES;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Initialize the notification packet and insert it onto the tail of the&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // list.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket-&amp;gt;DriverObject = DriverObject;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket-&amp;gt;NotificationRoutine = DriverNotificationRoutine;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExAcquireResourceExclusive( &amp;amp;IopDatabaseResource, TRUE );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertTailList( &amp;amp;IopFsNotifyChangeQueueHead, &amp;amp;nPacket-&amp;gt;ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExReleaseResource( &amp;amp;IopDatabaseResource );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Increment the number of reasons that this driver cannot be unloaded.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ObReferenceObject( DriverObject );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return STATUS_SUCCESS;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;//win2003&lt;BR&gt;NTSTATUS&lt;BR&gt;IoRegisterFsRegistrationChange(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDRIVER_OBJECT DriverObject,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;/*++&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Routine Description:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This routine registers the specified driver's notification routine to be&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; invoked whenever a file system registers or unregisters itself as an active&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; file system in the system.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Arguments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverObject - Pointer to the driver object for the driver.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverNotificationRoutine - Address of routine to invoke when a file system&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; registers or unregisters itself.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Return Value:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; STATUS_DEVICE_ALREADY_ATTACHED -&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Indicates that the caller has already registered&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; last with the same driver object &amp;amp; driver notification&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; STATUS_INSUFFICIENT_RESOURCES&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; STATUS_SUCCESS&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;--*/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PNOTIFICATION_PACKET nPacket;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PAGED_CODE();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExAcquireResourceExclusiveLite( &amp;amp;IopDatabaseResource, TRUE );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!IsListEmpty( &amp;amp;IopFsNotifyChangeQueueHead )) {&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Retrieve entry at tail of list&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket = CONTAINING_RECORD( IopFsNotifyChangeQueueHead.Blink, NOTIFICATION_PACKET, ListEntry );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((nPacket-&amp;gt;DriverObject == DriverObject) &amp;amp;&amp;amp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (nPacket-&amp;gt;NotificationRoutine == DriverNotificationRoutine)) {&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExReleaseResourceLite( &amp;amp;IopDatabaseResource);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return STATUS_DEVICE_ALREADY_ATTACHED;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Begin by attempting to allocate storage for the shutdown packet.&amp;nbsp; If&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // one cannot be allocated, simply return an appropriate error.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket = ExAllocatePoolWithTag( PagedPool|POOL_COLD_ALLOCATION,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; sizeof( NOTIFICATION_PACKET ),&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 'sFoI' );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!nPacket) {&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExReleaseResourceLite( &amp;amp;IopDatabaseResource );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return STATUS_INSUFFICIENT_RESOURCES;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Initialize the notification packet and insert it onto the tail of the&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // list.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket-&amp;gt;DriverObject = DriverObject;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket-&amp;gt;NotificationRoutine = DriverNotificationRoutine;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertTailList( &amp;amp;IopFsNotifyChangeQueueHead, &amp;amp;nPacket-&amp;gt;ListEntry );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IopNotifyAlreadyRegisteredFileSystems(&amp;amp;IopNetworkFileSystemQueueHead, DriverNotificationRoutine, FALSE);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IopNotifyAlreadyRegisteredFileSystems(&amp;amp;IopCdRomFileSystemQueueHead, DriverNotificationRoutine, TRUE);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IopNotifyAlreadyRegisteredFileSystems(&amp;amp;IopDiskFileSystemQueueHead, DriverNotificationRoutine, TRUE);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IopNotifyAlreadyRegisteredFileSystems(&amp;amp;IopTapeFileSystemQueueHead, DriverNotificationRoutine, TRUE);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Notify this driver about all already notified filesystems&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // registered as an active file system of some type.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExReleaseResourceLite( &amp;amp;IopDatabaseResource );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Increment the number of reasons that this driver cannot be unloaded.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ObReferenceObject( DriverObject );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return STATUS_SUCCESS;&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&lt;BR&gt;VOID&lt;BR&gt;IopNotifyAlreadyRegisteredFileSystems(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PLIST_ENTRY&amp;nbsp; ListHead,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDRIVER_FS_NOTIFICATION DriverNotificationRoutine,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN BOOLEAN SkipRaw&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;BR&gt;/*++&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Routine Description:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This routine calls the driver notification routine for filesystems&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; that have already been registered at the time of the call.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Arguments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ListHead - Pointer to the filesystem registration list head.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverNotificationRoutine - Pointer to the routine that has to be called.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Return Value:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; None.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;--*/&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PLIST_ENTRY entry;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PDEVICE_OBJECT fsDeviceObject;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; entry = ListHead-&amp;gt;Flink;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (entry != ListHead) {&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Skip raw filesystem notification&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ((entry-&amp;gt;Flink == ListHead) &amp;amp;&amp;amp; (SkipRaw)) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; break;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; fsDeviceObject = CONTAINING_RECORD( entry, DEVICE_OBJECT, Queue.ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; entry = entry-&amp;gt;Flink;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; DriverNotificationRoutine( fsDeviceObject, TRUE );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;注三：IoRegisterFileSystem函数&lt;BR&gt;&lt;BR&gt;是文件系统在DriverEntry中最后要调用的函数,主要是向IO管理器中注册一下,以后有卷需要Mount时通知我...&lt;BR&gt;&lt;BR&gt;VOID&lt;BR&gt;IoRegisterFileSystem(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN OUT PDEVICE_OBJECT DeviceObject&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;/*++&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Routine Description:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This routine inserts the device object for the file system which the device&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; object represents into the list of file systems in the system.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Arguments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DeviceObject - Pointer to device object for the file system.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;Return Value:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; None.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New" size=2&gt;--*/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PNOTIFICATION_PACKET nPacket;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PLIST_ENTRY entry;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PAGED_CODE();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Allocate the I/O database resource for a write operation.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (VOID) ExAcquireResourceExclusive( &amp;amp;IopDatabaseResource, TRUE );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Insert the device object into the appropriate file system queue based on&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the driver type in the device object.&amp;nbsp; Notice that if the device type is&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // unrecognized, the file system is simply not registered.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (DeviceObject-&amp;gt;DeviceType == FILE_DEVICE_NETWORK_FILE_SYSTEM) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertHeadList( &amp;amp;IopNetworkFileSystemQueueHead,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;DeviceObject-&amp;gt;Queue.ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else if (DeviceObject-&amp;gt;DeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertHeadList( &amp;amp;IopCdRomFileSystemQueueHead,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;DeviceObject-&amp;gt;Queue.ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else if (DeviceObject-&amp;gt;DeviceType == FILE_DEVICE_DISK_FILE_SYSTEM) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertHeadList( &amp;amp;IopDiskFileSystemQueueHead,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;DeviceObject-&amp;gt;Queue.ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } else if (DeviceObject-&amp;gt;DeviceType == FILE_DEVICE_TAPE_FILE_SYSTEM) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; InsertHeadList( &amp;amp;IopTapeFileSystemQueueHead,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;DeviceObject-&amp;gt;Queue.ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Ensure that this file system's device is operable.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DeviceObject-&amp;gt;Flags &amp;amp;= ~DO_DEVICE_INITIALIZING;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Notify all of the registered drivers that this file system has been&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // registered as an active file system of some type.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //PS:看到了吧,如果你的filter调用了IoRegisterFsRegistrationChange,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //文件系统注册时就要通过你啦,TRUE-Load/FALSE-unload.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; entry = IopFsNotifyChangeQueueHead.Flink;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; while (entry != &amp;amp;IopFsNotifyChangeQueueHead) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket = CONTAINING_RECORD( entry, NOTIFICATION_PACKET, ListEntry );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; entry = entry-&amp;gt;Flink;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; nPacket-&amp;gt;NotificationRoutine( DeviceObject, TRUE );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Release the I/O database resource.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExReleaseResource( &amp;amp;IopDatabaseResource );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Increment the number of reasons that this driver cannot be unloaded.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ExInterlockedAddUlong( &amp;amp;DeviceObject-&amp;gt;ReferenceCount, 1, &amp;amp;IopDatabaseLock );&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" size=2&gt;注四：&lt;BR&gt;&amp;nbsp;&amp;nbsp; 有兴趣的话可以看看文件识别器,IO管理器,文件系统的实现.&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;以前写的,今天整理了一下,阐述中有错误望指教,谢谢!&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src ="http://blog.vckbase.com/windowssky/aggbug/28144.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>垃圾一堆</dc:creator><title>(转)Hooking into NDIS and TDI</title><link>http://blog.vckbase.com/windowssky/archive/2007/07/05/27229.html</link><pubDate>Thu, 05 Jul 2007 09:46:00 GMT</pubDate><guid>http://blog.vckbase.com/windowssky/archive/2007/07/05/27229.html</guid><wfw:comment>http://blog.vckbase.com/windowssky/comments/27229.html</wfw:comment><comments>http://blog.vckbase.com/windowssky/archive/2007/07/05/27229.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://blog.vckbase.com/windowssky/comments/commentRss/27229.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/windowssky/services/trackbacks/27229.html</trackback:ping><description>&lt;SPAN class=edgeatext&gt;&lt;FONT face=Arial&gt;&lt;SPAN class=edgeatitle&gt;&lt;FONT size=4&gt;&lt;FONT size=5&gt;&lt;FONT size=2&gt;(ps:很老的文章，只是今天在rootkit上找东西，又看到了，所以收藏到blog中)&lt;BR&gt;原文章&amp;nbsp; Part1: &lt;/FONT&gt;&lt;A href="http://www.rootkit.com/newsread.php?newsid=219"&gt;&lt;FONT size=2&gt;http://www.rootkit.com/newsread.php?newsid=219&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;&lt;FONT size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Part2: &lt;/FONT&gt;&lt;A href="http://www.rootkit.com/newsread.php?newsid=253"&gt;&lt;FONT size=2&gt;http://www.rootkit.com/newsread.php?newsid=253&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;&lt;FONT size=2&gt;相关文章&lt;SPAN class=edgeatitle&gt;ktcp: &lt;/SPAN&gt;&lt;/FONT&gt;&lt;A href="http://www.rootkit.com/newsread.php?newsid=591"&gt;&lt;FONT size=2&gt;http://www.rootkit.com/newsread.php?newsid=591&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;&lt;STRONG&gt;Hooking into NDIS and TDI (Part 1)&lt;/STRONG&gt;&lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;BR&gt;This is the fist part in a series of 2 articles on how to hook into the NDIS and TDI layer. In this first one, we will discuss where and how to hook in to the NDIS layer. &lt;BR&gt;&lt;BR&gt;In the second, we will do the same for TDI.&lt;BR&gt;&lt;BR&gt;First, lets take a quick look at a quite simplicit view of the network stack in kernel space:&lt;BR&gt;TDI&lt;BR&gt;NDIS protocol layer&lt;BR&gt;NDIS Intermediate layer&lt;BR&gt;Miniport layer&lt;BR&gt;Hardware&lt;BR&gt;&lt;BR&gt;To be able to control data flow in NDIS, we have 3 potential points where we can either add a device / driver or hook into existing. First, we have the miniport layer, these are the drivers controlling the NIC hardware, which is a bit to low of a level for what we want at this time. Next, we have the intermediate layer. This layer would be perfect for this purpose, since it would allow us to contol the dataflow to all NDIS protocol drivers. But, it has a major drawback: To be able to add a driver to this layer, it has to be signed on a default install. &lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;Depending on what system and under what circumstances we are installing this code, it might not be possible to get past this problem in an easy manner. Last, we have the protocol layer. Adding a driver to this layer would be easy, software such as WinPcap does that. However, in that case we will not be able to control what a user would see through for software relaying on these types of drivers, such as Ethereal. So, is there any way we can get around the driver signing issue in the intermediate layer and at the same time control data in the protocol layer and above? Yes! We can virually add a layer in between intermediate and protocol by hooking all NDIS protocol drivers and their protocol functions.&lt;BR&gt;&lt;BR&gt;When an NDIS protocol is registered, it is recorded in a linked list. Each element in this linked list carries a pointer to a structure named NDIS_OPEN_BLOCK. This structure carries the pointers for all registered function pointers for the protocol. The linked list elements are made out of a structure looking something like the following:&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;CODE&gt;&lt;BR&gt;typedef struct _NDIS_LINKED_LIST {&lt;BR&gt;&amp;nbsp;&amp;nbsp;PNDIS_OPEN_BLOCK pOpenBlock;&lt;BR&gt;&amp;nbsp;&amp;nbsp;PVOID p;&lt;BR&gt;&amp;nbsp;&amp;nbsp;REFERENCE ref;&lt;BR&gt;&amp;nbsp;&amp;nbsp;struct _NDIS_LINKED_LIST *Next;&lt;BR&gt;} NDIS_LINKED_LIST,*PNDIS_LINKED_LIST;&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial&gt;It was a year or so since I played with this code, so I can actually not remember the real name of this struct. Interested persons can find it through google. This will also reflect in the source code later on, since it is relying on absolute offsets instead of the typedef'ed struct.&lt;BR&gt;&lt;BR&gt;To be able to hook into all registered NDIS protocols, we need to find the first element in this linked list. This is actually returned by NdisRegisterProtocol as the NDIS_HANDLE. So, what we have to do is to register a bogus NDIS protocol, save the pointer and then remove the protocol. This will give us the ability to walk through the list of registered NDIS protocols and exchange existing function points to functions we control.&lt;BR&gt;&lt;BR&gt;First, we register the bogus protocol to get the pointer. To make sure the registration does not fail, the protocol we register needs to have a ReceiveHandler:&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;CODE&gt;&lt;BR&gt;NDIS_STATUS DummyNDISProtocolReceive(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN NDIS_HANDLE ProtocolBindingContext,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN NDIS_HANDLE MacReceiveContext,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN PVOID HeaderBuffer,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN UINT HeaderBufferSize,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN PVOID LookAheadBuffer,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN UINT LookAheadBufferSize,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN UINT PacketSize)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return NDIS_STATUS_NOT_ACCEPTED;&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;NDIS_HANDLE RegisterBogusNDISProtocol(void)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NTSTATUS Status = STATUS_SUCCESS;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NDIS_HANDLE hBogusProtocol = NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NDIS_PROTOCOL_CHARACTERISTICS BogusProtocol;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NDIS_STRING ProtocolName;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NdisZeroMemory(&amp;amp;BogusProtocol,sizeof(NDIS_PROTOCOL_CHARACTERISTICS));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BogusProtocol.MajorNdisVersion = 0x04;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BogusProtocol.MinorNdisVersion = 0x0;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NdisInitUnicodeString(&amp;amp;ProtocolName,L"BogusProtocol");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BogusProtocol.Name = ProtocolName;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BogusProtocol.ReceiveHandler = DummyNDISProtocolReceive;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NdisRegisterProtocol(&amp;amp;Status,&amp;amp;hBogusProtocol,&amp;amp;BogusProtocol,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;sizeof(NDIS_PROTOCOL_CHARACTERISTICS));&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Status == STATUS_SUCCESS) return hBogusProtocol;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else return NULL;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial&gt;Once we have the pointer, we can deregister the protocol again:&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;CODE&gt;&lt;BR&gt;void DeregisterBogusNDISProtocol(NDIS_HANDLE hBogusProtocol)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NTSTATUS Status;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NdisDeregisterProtocol(&amp;amp;Status,hBogusProtocol);&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial&gt;Once we start walking the linked list and overwriting function pointers, we need to save the old pointers to be able to call them from our functions. There are atleast 2 ways of doing this:&lt;BR&gt;&lt;BR&gt;1. Create a linked list of "hooked instances", holding the old pointers for each protocol. When our NDIS functions are called, the linked list has to be searched for the right element.&lt;BR&gt;&lt;BR&gt;2. Allocate one instance of our functions for each protocol we hook and write the old pointer directly into the code of the function. This is slighly more work during hooking, but should be faster during run-time than searching through a linked list for every packet.&lt;BR&gt;&lt;BR&gt;When this code was written, I never thought of option number 2, but that is probably the option I would use today. So, enjoy option 1, it works well and I haven't seen any major performance hits from it.&lt;BR&gt;&lt;BR&gt;For every element in the NDIS registered protocol linked list, I allocate one element in my own list and save all important pointers together with 2 context handles. The handles values are later used to find the right element for the current protocol. Relevant pointers are then overwritten to point to my versions of the send and receive functions. We also save a pointer to the NDIS_OPEN_BLOCK itself to make unhooking easy. The code walking the list and hooking into the protocol would look something like this:&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;CODE&gt;&lt;BR&gt;NTSTATUS HookExistingNDISProtocols(void)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UINT *ProtocolPtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NDIS_HANDLE hBogusProtocol = NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PNDIS_OPEN_BLOCK OpenBlockPtr = NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PNDIS_PROTOCOL_HOOK pNode;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;hBogusProtocol = RegisterBogusNDISProtocol();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(hBogusProtocol == NULL) return STATUS_UNSUCCESSFUL;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProtocolPtr = (UINT*)hBogusProtocol;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProtocolPtr = (UINT*)((PBYTE)ProtocolPtr + sizeof(REFERENCE) + 8);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProtocolPtr = (UINT*)(*ProtocolPtr);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while(ProtocolPtr != NULL) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OpenBlockPtr = (PNDIS_OPEN_BLOCK)(*ProtocolPtr);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(OpenBlockPtr != NULL) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pNode = NewNDISNode();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(pNode != NULL) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pNode-&amp;gt;ProtocolBindingContext = OpenBlockPtr-&amp;gt;ProtocolBindingContext;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pNode-&amp;gt;MacBindingContext = OpenBlockPtr-&amp;gt;MacBindingHandle;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pNode-&amp;gt;OpenBlockPtr = OpenBlockPtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pNode-&amp;gt;RealSendHandler = OpenBlockPtr-&amp;gt;SendHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//How about WanSendHandler?&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;pNode-&amp;gt;RealPostNt31ReceiveHandler = OpenBlockPtr-&amp;gt;PostNt31ReceiveHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InsertNDISNode(pNode);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OpenBlockPtr-&amp;gt;SendHandler = NDISSendHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//How about WanSendHandler?&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OpenBlockPtr-&amp;gt;PostNt31ReceiveHandler = NDISPostNt31ReceiveHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProtocolPtr = (UINT*)((PBYTE)ProtocolPtr + sizeof(REFERENCE) + 8);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ProtocolPtr = (UINT*)(*ProtocolPtr);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DeregisterBogusNDISProtocol(hBogusProtocol);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return STATUS_SUCCESS;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial&gt;There are more functions in the NDIS_OPEN_BLOCK that might be of interest to hook, but if you only want to control network traffic, send and receive are enough. Another thing worth mentioning is that the NDIS_OPEN_BLOCK changes with OS versions. It looks different in Win2K compared to XP, mostly due to member names changing.&lt;BR&gt;&lt;BR&gt;The next thing to do now is to implement send and recieve functions which searches through the linked list to find the original function pointers and then calls them if the traffic is to be passed on. If the traffic is to be altered, that is performed before calling the real protocol function. If the traffic is supposed to be dropped, we can just skip calling the real function and return with the appropriate status:&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;CODE&gt;&lt;BR&gt;NDIS_STATUS NDISSendHandler(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN NDIS_HANDLE MacBindingHandle,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN PNDIS_PACKET Packet)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PNDIS_PROTOCOL_HOOK Node;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Node = FindNDISNode(MacBindingHandle,2);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Node == NULL) return NDIS_STATUS_SUCCESS;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Node-&amp;gt;RealSendHandler(MacBindingHandle,Packet);&lt;BR&gt;}&lt;BR&gt;&lt;BR&gt;NDIS_STATUS NDISPostNt31ReceiveHandler(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN NDIS_HANDLE ProtocolBindingContext,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN NDIS_HANDLE MacReceiveContext,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN PVOID HeaderBuffer,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN UINT HeaderBufferSize,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN PVOID LookAheadBuffer,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN UINT LookAheadBufferSize,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;IN UINT PacketSize)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PNDIS_PROTOCOL_HOOK Node;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Node = FindNDISNode(ProtocolBindingContext,1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Node == NULL) return NDIS_STATUS_SUCCESS;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Node-&amp;gt;RealPostNt31ReceiveHandler(ProtocolBindingContext,MacReceiveContext,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HeaderBuffer,HeaderBufferSize,LookAheadBuffer,LookAheadBufferSize,PacketSize);&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial&gt;Now, there is only one thing left, unhooking. We do this by walking our linked list of "hooked instances" and replace all pointers:&lt;BR&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;CODE&gt;&lt;BR&gt;NTSTATUS ReleaseExistingNDISProtocols(void)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PNDIS_PROTOCOL_HOOK CurrentNode;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PNDIS_OPEN_BLOCK OpenBlockPtr = NULL;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CurrentNode = GetFirstNDISNode();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(CurrentNode == NULL) return STATUS_UNSUCCESSFUL;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while(CurrentNode != NULL) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OpenBlockPtr = CurrentNode-&amp;gt;OpenBlockPtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(OpenBlockPtr != NULL) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OpenBlockPtr-&amp;gt;SendHandler = CurrentNode-&amp;gt;RealSendHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;OpenBlockPtr-&amp;gt;PostNt31ReceiveHandler = CurrentNode-&amp;gt;RealPostNt31ReceiveHandler;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CurrentNode = GetNextNDISNode(CurrentNode);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return STATUS_SUCCESS;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;FONT face=Arial&gt;What is left to be done? The code does not hook into NDIS protocol being registred after NDIS is hooked into. This is left up to the reader to figure out, one way to do it can be found in the win32 version of sebek.&lt;BR&gt;&lt;BR&gt;Does the code work? Sure, I use it in a win32 version of knockd called sesame that can be found at &lt;/FONT&gt;&lt;A href="http://www.toolcrypt.org/" target=_blank&gt;&lt;FONT face=Arial color=#223355&gt;.http://www.toolcrypt.org/.&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;SPAN class=edgeatext&gt;&lt;FONT face=Arial&gt;&lt;SPAN class=edgeatitle&gt;&lt;STRONG&gt;Hooking into NDIS and TDI (Part 2)&lt;BR&gt;&lt;BR&gt;&lt;/STRONG&gt;&lt;SPAN class=edgeatext&gt;This is the second and last article on how to hook into the NDIS and TDI &lt;BR&gt;layer. The approach we will use will be slightly different from the NDIS &lt;BR&gt;case. However, a neat side effect is that this method can be used to hook &lt;BR&gt;into any device chain, for example the keyboard to sniff key strokes. It all boils down to getting a pointer to the device object and replace all major functions with our own dispatch function.&lt;BR&gt;&lt;BR&gt;To be able to fully control the TDI layer, we need access to the IRP both &lt;BR&gt;before and after the original driver has processed it. If we have that, we &lt;BR&gt;can choose what the original driver should process and we can also alter &lt;BR&gt;results before they are returned to user-space. The "before filtering" can &lt;BR&gt;be accomplished in our own, new dispatch function and the "after filtering" can be accomplished in a completion routine.&lt;BR&gt;&lt;BR&gt;First, to be able to overwrite and insert our own dispatch function, we need a pointer to the driver object we are going to hook into. An easy way to get this pointer is to call ObReferenceObjectByName with the appropriate driver name. Then we only have to save all old function pointers and overwrite the existing ones with our own. The code to do this would look something like the following:&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;&lt;BR&gt;DRIVER_OBJECT RealTDIDriverObject;&lt;BR&gt;&lt;BR&gt;NTSTATUS HookTDI(void)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NTSTATUS Status;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UNICODE_STRING usDriverName;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PDRIVER_OBJECT DriverObjectToHookPtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UINT i;&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RtlInitUnicodeString(&amp;amp;usDriverName,L"\\Driver\\Tcpip");&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Status = &lt;BR&gt;ObReferenceObjectByName(&amp;amp;usDriverName,OBJ_CASE_INSENSITIVE,NULL,0,IoDriverObjectType,KernelMode,NULL,&amp;amp;DriverObjectToHookPtr);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Status != STATUS_SUCCESS) return Status;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(i = 0;i &amp;lt; IRP_MJ_MAXIMUM_FUNCTION;i++) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RealTDIDriverObject.MajorFunction[i] = &lt;BR&gt;DriverObjectToHookPtr-&amp;gt;MajorFunction[i];&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DriverObjectToHookPtr-&amp;gt;MajorFunction[i] = TDIDeviceDispatch;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return STATUS_SUCCESS;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;RealTDIDriverObject is a DRIVER_OBJECT where we save the original &lt;BR&gt;information to both be able to call the old functions and also be able to &lt;BR&gt;unhook once we are done. The orignal driver gets all its major functions &lt;BR&gt;overwritten with a pointer to our own dispatch function, TDIDeviceDispatch.&lt;BR&gt;&lt;BR&gt;We now have control over the IRPs before TDI can process them. But, we still have to make sure we can also control them once TDI is done with it but before it is returned to the IO handler and user-space. We will solve this in our dispatch function with the help of a completion routine. It is not as straight forward as it sounds, since we might be hooking the last entity in the chain, we can't just insert a completion routine with &lt;BR&gt;IoSetCompletionRoutine (see the DDK docs), since it in that case never will be called. Completion routines are set in the next IRP stack location, not the current. If we are the last entity, there will be no next stack location in the IRP. Searching through the header files reveal IoSetCompletionRoutine as a macro which only gets the next IRP stack location and sets the CompletionRoutine pointer together with the Control element. Following the same principcal, we can set our own completion routine to regain control over the IRP with the following dispach function:&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;&lt;BR&gt;NTSTATUS TDIDeviceDispatch(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NTSTATUS Status;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PIO_STACK_LOCATION StackLocationPtr;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Irp == NULL) return STATUS_SUCCESS;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StackLocationPtr = IoGetCurrentIrpStackLocation(Irp);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(StackLocationPtr-&amp;gt;CompletionRoutine != NULL) StackLocationPtr-&amp;gt;Context = &lt;BR&gt;StackLocationPtr-&amp;gt;CompletionRoutine;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else StackLocationPtr-&amp;gt;Context = NULL;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StackLocationPtr-&amp;gt;CompletionRoutine = &lt;BR&gt;(PIO_COMPLETION_ROUTINE)TDICompletionRoutine;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StackLocationPtr-&amp;gt;Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR | &lt;BR&gt;SL_INVOKE_ON_CANCEL;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Status = &lt;BR&gt;RealTDIDriverObject.MajorFunction[StackLocationPtr-&amp;gt;MajorFunction](DeviceObject,Irp);&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return Status;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;What we actually do is faking a scenario where the layer above set the &lt;BR&gt;completion routine for us. We also save a potentially already existing &lt;BR&gt;completion routine in the Context element of the IRP. Control is set to &lt;BR&gt;invoke the completion routine in all cases. There are 2 potential issues &lt;BR&gt;with this code. First, we overwrite whatever is in the Context element. &lt;BR&gt;Second, we never save the Control element, so we don't know when to invoke &lt;BR&gt;an already existing completion routine. So far, I have not seen any &lt;BR&gt;side-effects from doing this.&lt;BR&gt;&lt;BR&gt;The completion routine would look something like:&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;&lt;BR&gt;NTSTATUS TDICompletionRoutine(PDEVICE_OBJECT DeviceObject,PIRP Irp,PVOID &lt;BR&gt;Context)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;COMPLETIONROUTINE RealCompletionRoutine = (COMPLETIONROUTINE)Context;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Context != NULL) return RealCompletionRoutine(DeviceObject,Irp,NULL);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;else return STATUS_SUCCESS;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;It invokes a potential completion routine as soon as it is done and returns the status from it. Finally, unhooking the driver is just a question of restoring the pointers we overwrote in the hooking function:&lt;BR&gt;&lt;BR&gt;&lt;CODE&gt;&lt;BR&gt;NTSTATUS ReleaseTDIDevices(void)&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;NTSTATUS Status;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UNICODE_STRING usDriverName;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;PDRIVER_OBJECT DriverObjectToHookPtr;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UINT i;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;RtlInitUnicodeString(&amp;amp;usDriverName,L"\\Driver\\Tcpip");&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Status = &lt;BR&gt;ObReferenceObjectByName(&amp;amp;usDriverName,OBJ_CASE_INSENSITIVE,NULL,0,IoDriverObjectType,KernelMode,NULL,&amp;amp;DriverObjectToHookPtr);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if(Status != STATUS_SUCCESS) return Status;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;for(i = 0;i &amp;lt; IRP_MJ_MAXIMUM_FUNCTION;i++)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DriverObjectToHookPtr-&amp;gt;MajorFunction[i] = &lt;BR&gt;RealTDIDriverObject.MajorFunction[i];&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return STATUS_SUCCESS;&lt;BR&gt;}&lt;BR&gt;&lt;/CODE&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;There is another way to accomplish the same result which utilizes a more &lt;BR&gt;offically supported mode of operation. It is based upon attaching to the &lt;BR&gt;device chain with GetDeviceObject and AttachToDevice, which will allow us to process all IRPs before the real device. Once in the dispatch function we contruct a new IRP and add a completion routine to regain control of the IRP before it is returned to the IO system and user-space.&lt;BR&gt;&lt;BR&gt;One last important thing to mention; This code is quite untested. It seems &lt;BR&gt;to work as intended but it has never been used in any major applications, so use it on your own risk. With that said, hope you have enjoyed this little article series.&lt;BR&gt;&lt;BR&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/SPAN&gt;&lt;/SPAN&gt;&lt;img src ="http://blog.vckbase.com/windowssky/aggbug/27229.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>垃圾一堆</dc:creator><title>如何写windows系统已保护的内存区域</title><link>http://blog.vckbase.com/windowssky/archive/2007/05/23/26594.html</link><pubDate>Wed, 23 May 2007 08:29:00 GMT</pubDate><guid>http://blog.vckbase.com/windowssky/archive/2007/05/23/26594.html</guid><wfw:comment>http://blog.vckbase.com/windowssky/comments/26594.html</wfw:comment><comments>http://blog.vckbase.com/windowssky/archive/2007/05/23/26594.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.vckbase.com/windowssky/comments/commentRss/26594.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/windowssky/services/trackbacks/26594.html</trackback:ping><description>&lt;P&gt;&lt;FONT face="Courier New"&gt;windows系统在某些版本下对某些内存区域启用了写保护的功能，因为这些区域一般合法程序是不可能修改其内容的，那么我们如何来写这些内存呢？&lt;BR&gt;&lt;BR&gt;PS:1) 这些系统包括:windows xp与windows 2003&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;2) CPU提供写保护的功能是从486开始的&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;3) 一般合法程序不包括杀毒软件，因为他们在Hook SSDT中是直接改ServiceTableBase，而没有用inline的方法&lt;BR&gt;&amp;nbsp;&amp;nbsp; &lt;BR&gt;我们就用SSDT做例子吧，在Hook SSDT时不用innline hook方法，我们就要修改SSDT这个系统服务描述表；而这个表是被写保护了，在ring0下也是没有写的权限。&lt;BR&gt;&lt;BR&gt;方法一：&lt;BR&gt;首先我们来看一下CR0寄存器的格式&lt;BR&gt;&lt;U&gt;|31|30|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; |18|17|16|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 5|4|3|2|0|1|&lt;BR&gt;&lt;/U&gt;|P |C |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|A |&amp;nbsp; |W |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;N|E|T|E|M|P|&lt;BR&gt;&lt;U&gt;|G |D |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|M&amp;nbsp;|&amp;nbsp;&amp;nbsp;|P |&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; E|T|S|M|P|E|&lt;BR&gt;&lt;/U&gt;&lt;BR&gt;我们主要注意这个WP这位,其他的请参考IA-32 Volume 3A；&lt;BR&gt;WP&amp;#8212;&amp;#8212;Write Protect，当设置为1时只提供读页权限&lt;BR&gt;PE&amp;#8212;&amp;#8212;Paging，当设置为1时提供分页&lt;BR&gt;MP&amp;#8212;&amp;#8212;Protection Enable，当设置为1时进入保护模式&lt;BR&gt;所以我们只要把WP这一位设置为0时，就可以修改SSDT了&lt;BR&gt;&lt;BR&gt;&amp;nbsp;//1 关闭写保护&lt;BR&gt;&amp;nbsp;__asm&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp; push eax&lt;BR&gt;&amp;nbsp;&amp;nbsp;mov&amp;nbsp; eax, CR0&lt;BR&gt;&amp;nbsp; and&amp;nbsp; eax, 0FFFEFFFFh&lt;BR&gt;&amp;nbsp; mov&amp;nbsp; CR0, eax&lt;BR&gt;&amp;nbsp; pop&amp;nbsp; eax&lt;BR&gt;&amp;nbsp;}&lt;BR&gt;&lt;BR&gt;&amp;nbsp;//2 打开写保护&lt;BR&gt;&amp;nbsp;__asm&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp; push eax&lt;BR&gt;&amp;nbsp; mov&amp;nbsp; eax, CR0&lt;BR&gt;&amp;nbsp; or&amp;nbsp;&amp;nbsp; eax, NOT 0FFFEFFFFh&lt;BR&gt;&amp;nbsp; mov&amp;nbsp; CR0, eax&lt;BR&gt;&amp;nbsp; pop&amp;nbsp; eax&lt;BR&gt;&amp;nbsp;}&lt;BR&gt;通过上面的第一组指令我们就可以正常修改SSDT，记得修改后要还原。&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;方法二：&lt;BR&gt;此方法是盖茨提供的，在内存描述表(MDL)中描述一块内存区域，MDL包含此内存区域的起始地址，拥有者进程，字节数量以及标志。&lt;BR&gt;//在ddk中的描述&lt;BR&gt;typedef struct _MDL {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct _MDL *Next;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CSHORT Size;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CSHORT MdlFlags;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; struct _EPROCESS *Process;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PVOID MappedSystemVa;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PVOID StartVa;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ULONG ByteCount;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ULONG ByteOffset;&lt;BR&gt;} MDL, *PMDL;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;#define MDL_MAPPED_TO_SYSTEM_VA&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0001&lt;BR&gt;#define MDL_PAGES_LOCKED&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0002&lt;BR&gt;#define MDL_SOURCE_IS_NONPAGED_POOL 0x0004&lt;BR&gt;#define MDL_ALLOCATED_FIXED_SIZE&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0008&lt;BR&gt;#define MDL_PARTIAL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0010&lt;BR&gt;#define MDL_PARTIAL_HAS_BEEN_MAPPED 0x0020&lt;BR&gt;#define MDL_IO_PAGE_READ&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0040&lt;BR&gt;#define MDL_WRITE_OPERATION&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0080&lt;BR&gt;#define MDL_PARENT_MAPPED_SYSTEM_VA 0x0100&lt;BR&gt;#define MDL_LOCK_HELD&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0200&lt;BR&gt;#define MDL_PHYSICAL_VIEW&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0400&lt;BR&gt;#define MDL_IO_SPACE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x0800&lt;BR&gt;#define MDL_NETWORK_HEADER&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x1000&lt;BR&gt;#define MDL_MAPPING_CAN_FAIL&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0x2000&lt;BR&gt;#define MDL_ALLOCATED_MUST_SUCCEED&amp;nbsp; 0x4000&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;// Declarations&lt;BR&gt;&lt;BR&gt;#pragma pack(1)&lt;BR&gt;&lt;BR&gt;typedef struct ServiceDescriptorEntry {&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned int *ServiceTableBase;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned int *ServiceCounterTableBase;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned int NumberOfServices;&lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; unsigned char *ParamTableBase;&lt;BR&gt;&lt;BR&gt;} SSDT;&lt;BR&gt;&lt;BR&gt;#pragma pack()&lt;BR&gt;&lt;BR&gt;__declspec(dllimport) SSDTKeServiceDescriptorTable;&lt;BR&gt;&lt;BR&gt;PMDL&amp;nbsp; g_pmdlSystemCall;&lt;BR&gt;PVOID *MappedSystemCallTable;&lt;BR&gt;&lt;BR&gt;// save old system call locations&lt;BR&gt;// Map the memory into our domain to change the permissions on&lt;BR&gt;// the MDL&lt;BR&gt;g_pmdlSystemCall = MmCreateMdl(NULL,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; KeServiceDescriptorTable.ServiceTableBase,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; KeServiceDescriptorTable.NumberOfServices*4);&lt;BR&gt;&lt;BR&gt;if(!g_pmdlSystemCall)&lt;BR&gt;&amp;nbsp;&amp;nbsp; return STATUS_UNSUCCESSFUL;&lt;BR&gt;&lt;BR&gt;MmBuildMdlForNonPagedPool(g_pmdlSystemCall);&lt;BR&gt;&lt;BR&gt;// Change the flags of the MDL&lt;BR&gt;g_pmdlSystemCall-&amp;gt;MdlFlags = g_pmdlSystemCall-&amp;gt;MdlFlags |&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MDL_MAPPED_TO_SYSTEM_VA;&lt;BR&gt;&lt;BR&gt;MappedSystemCallTable = MmMapLockedPages(g_pmdlSystemCall, KernelMode);&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;MappedSystemCallTable就是SSDT的地址，现在可以放心的操作它吧！用完了最好MmFreePagesFromMdl。&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;img src ="http://blog.vckbase.com/windowssky/aggbug/26594.html" width = "1" height = "1" /&gt;</description></item><item><dc:creator>垃圾一堆</dc:creator><title>windows driver中的IO_STACK_LOCATION </title><link>http://blog.vckbase.com/windowssky/archive/2007/04/17/25543.html</link><pubDate>Tue, 17 Apr 2007 08:00:00 GMT</pubDate><guid>http://blog.vckbase.com/windowssky/archive/2007/04/17/25543.html</guid><wfw:comment>http://blog.vckbase.com/windowssky/comments/25543.html</wfw:comment><comments>http://blog.vckbase.com/windowssky/archive/2007/04/17/25543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://blog.vckbase.com/windowssky/comments/commentRss/25543.html</wfw:commentRss><trackback:ping>http://blog.vckbase.com/windowssky/services/trackbacks/25543.html</trackback:ping><description>&lt;FONT face="Courier New"&gt;define IoSkipCurrentIrpStackLocation( Irp ) \&lt;BR&gt;(Irp)-&amp;gt;CurrentLocation++; \&lt;BR&gt;(Irp)-&amp;gt;Tail.Overlay.CurrentStackLocation++; &lt;/FONT&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;#define IoCopyCurrentIrpStackLocationToNext&amp;nbsp; ( Irp )&amp;nbsp;&amp;nbsp; &lt;BR&gt;Value:&lt;BR&gt;{ \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PIO_STACK_LOCATION irpSp; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PIO_STACK_LOCATION nextIrpSp; \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; RtlCopyMemory( nextIrpSp, irpSp, FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); \&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; nextIrpSp-&amp;gt;Control = 0; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;NTSTATUS&lt;BR&gt;IoCallDriver(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDEVICE_OBJECT DeviceObject,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN OUT PIRP Irp&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return IofCallDriver (DeviceObject, Irp);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;BR&gt;&lt;FONT face="Courier New"&gt;NTSTATUS&lt;BR&gt;FASTCALL&lt;BR&gt;IofCallDriver(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDEVICE_OBJECT DeviceObject,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN OUT PIRP Irp&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This routine will either jump immediately to IopfCallDriver, or rather&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // IovCallDriver.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return pIofCallDriver(DeviceObject, Irp);&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;NTSTATUS&lt;BR&gt;FASTCALL&lt;BR&gt;IopfCallDriver(&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN PDEVICE_OBJECT DeviceObject,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IN OUT PIRP Irp&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; )&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;/*++&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Routine Description:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; This routine is invoked to pass an I/O Request Packet (IRP) to another&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; driver at its dispatch routine.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Arguments:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DeviceObject - Pointer to device object to which the IRP should be passed.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Irp - Pointer to IRP for request.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Return Value:&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Return status from driver's dispatch routine.&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;--*/&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PIO_STACK_LOCATION irpSp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PDRIVER_OBJECT driverObject;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NTSTATUS status;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Ensure that this is really an I/O Request Packet.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ASSERT( Irp-&amp;gt;Type == IO_TYPE_IRP );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Update the IRP stack to point to the next location.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Irp-&amp;gt;CurrentLocation--;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Irp-&amp;gt;CurrentLocation &amp;lt;= 0) {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; KeBugCheckEx( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0, 0 );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; irpSp = IoGetNextIrpStackLocation( Irp );&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Irp-&amp;gt;Tail.Overlay.CurrentStackLocation = irpSp;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Save a pointer to the device object for this request so that it can&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // be used later in completion.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; irpSp-&amp;gt;DeviceObject = DeviceObject;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Invoke the driver at its dispatch routine entry point.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; driverObject = DeviceObject-&amp;gt;DriverObject;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PERFINFO_DRIVER_MAJORFUNCTION_CALL(Irp, irpSp, driverObject);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; status = driverObject-&amp;gt;MajorFunction[irpSp-&amp;gt;MajorFunction]( DeviceObject,&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Irp );&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PERFINFO_DRIVER_MAJORFUNCTION_RETURN(Irp, irpSp, driverObject);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return status;&lt;BR&gt;}&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;img src ="http://blog.vckbase.com/windowssky/aggbug/25543.html" width = "1" height = "1" /&gt;</description></item></channel></rss>