老马失蹄浅析:驱动中取磁盘大小导致蓝屏的问题
看之前写的磁盘过滤驱动,经手多人,多年迭代,渐渐只能小修,不能大改(你懂的!)。终于发狠,另起炉灶,重写一版,其实心中也颇为忐忑!一开始搭框架,还是相当轻松,一个下午,边moyu边写, 搭好进入调试,却在AddDevice处蓝屏,看堆栈是因在AddDevice中查询磁盘大小导致:
蓝屏在查询磁盘大小处
而查询磁盘大小函数根据多年经验不该产生什么问题!看堆栈最上方是ExpInterlockedPopEntrySListResume,这类函数通常不检查入参,在此蓝屏也可理解。
用!devnode 0 1查看磁盘设备状态,可见只有第一个磁盘设备在DeviceNodeDriversAdded(0x303)状态:
磁盘在Add状态,正好切合AddDevice调用
此时凭经验推测应当是AddDevice时设备并未启动状态,而我们查询磁盘大小可能需要设备完全启动后才行。直接在Windbg中反汇编调试分析太慢了,参考下reactos的源码(虽然老了点),先看堆栈上CLASSPNP!DequeueFreeTransferPacket调用:
CLASSPNP!DequeueFreeTransferPacket
它一开始就调用了InterlockedPopEntrySList用来弹出一个Entry进行操作,该函数参数为一个单向链表,如果链表不为空则返回要删除的Entry,为空时则返回NULL。但这里它产生了蓝屏,那么只可能是该列表未被初始化,特别是在我们AddDevice的时候。我们查一下该链表初化的地方,在ClassPnpStartDevice函数中:
ClassPnpStartDevice中初始化了该链表
而ClassPnpStartDevice是在ClassDispatchPnp的IRP_MJ_START_DEVICE分支中被调用。至此,可知道蓝屏原因确实是调用早了,做为过滤驱动,先响应AddDevice,再响应IRP_MJ_START_DEVICE。把该调用移动至IRP_MJ_START_DEVICE后问题解决。
以前似乎也碰到过此类蓝屏,却没想深入去了解,实在懒惰!不料今日马失前蹄,朝闻道,夕死可矣!?
本站内容搜集自互联网,版权归原作者所有。如有侵权,请来信告知,我们将删除相关内容。