WIN98下的WDM
作者:陆麟
转载请征得作者同意.
1999.9.24

    今天,写了'WDM'版的DYKBD. 正如我以前所说,WDM不过是扩展的KMD. 所以,WIN98本身就支持有限的KMD.KMD和WDM的最根本的区别在于:
    KMD必须自己探索硬件的存在.而WDM不需要.
    为什么不需要?WDM其实根据PNP的功能而来.到目前为止,所有的PNP的规范甚至其他新的规范都在硬件中定义了设备的ID,供应商字符串.供区别于其他设备.这就构成了WDM存在的基础.老式的ISA是不可能被WDM所支持的.因为他们缺乏用来识别设备的ID,不能由OS自动配置IO空间.
    那么WDM在98里是如何实现的呢?
    WDM的DRIVER在98下,被SOFTICE解释成NT MINIPORT.也就是说,他本身无法提供任何VXD,V86,PM,W32服务.所有的服务归根结底都是由NTOSKRNL完成的.NTOSKRNL会根据USER MODE的请求将调用转发到合适的地方.也就是相应的WDM DRIVER例程.
    我们通过分析WDM DRIVER的引入函数表可以清楚地看到.他们都或多或少地调用了NTOSKRNL.EXE的函数.但是,98本身根本就没有NTOSKRNL.EXE.那么我们如何实现对NTOSKRNL.EXE的调用呢?下面我会讲到.
    所有的WDM DRIVER是被VXD加载的.加载WDM DRIVER的VXD是个特殊的VXD.这个VXD的名字叫NTKERN.VXD.他的最特殊之处在于它还提供了NTOSKRNL.EXE的功能.NTOSKRNL.EXE是NT的核心.NTOSKRNL.EXE在NT下是个PE文件.所以,对他的调用可以通过分析PE文件的引出函数表分析.但是NTKERN.VXD本身是个LX文件.根本不能引出任何函数.因为他的格式不是PE LOADER能识别的.而所有的WDM DRIVER都依赖于KERNEL MODE的PE引入表.所以,为了能够提供WDM的支持,NTKERN.VXD还在OS内核数据结构里动了手脚.他伪造了NTOSKRNL.EXE的模块和函数表.具体的实现可以通过调用PELDR_AddExportTable完成.(这是VXDLDR的功能之一.:))这样,当一个WDM DRIVER被加载时,系统就会根据内存里的'NTOSKRNL.EXE'的引出函数表来重定位WDM DRIVER的引入函数.
    在98下,我强烈不推荐用WDM写DRIVER.因为实际运作速度实在太慢,而且代码变得十分长.根本的问题是有很多在VXD下很轻松就能解决的问题变得麻烦起来.例如监测进程的创建,系统初始化等.尤其是目前我们决大多数朋友并不写真正驱动硬件的DRIVER.只不过写个有RING0权限的工具.所以,还是VXD更能够解决实际问题.
    WDM的慢体现在:一个DEVICE IO,将先查找\DOSDEVICES\是否有相应的DEVICE对象.经过NTKERN.VXD,先分析,后分配IRP,分配核心内存区域,将用户数据COPY到核心区,在IRP填入大堆的数据,包括用户数据在核心地址区域的地址.然后调用DRIVER.等返回后调用IOCOMPLETE ROUTINE,分析NTSTATUS...太复杂太慢.
    倒是有一点我第一次看到.就是WDM的出错不象平时的出错报告,先个兰屏,后什么一个0D保护错发生在XXX地址.还让你可继续运行,然后反复兰屏.WDM的出错太爽气了.一个兰屏.显示出错的部分.然后就HALT.一动不动了.连CAD也不能REBOOT了.:DDD
    需要看看WDM版的DYKBD的朋友给我个MAIL.我不打算在WEB上放了.(其实WDMDYKBD不是个真正的WDM DRIVER.是个KMD.98支持的KMD:)不能移植到NT上.)