DDK样例toaster分析(1)

来源:互联网 发布:2009知乎 编辑:程序博客网 时间:2024/04/29 17:34

    msddk样例中toaster是一个比较完整和值得学习的pnp驱动,包括了一个完整的设备栈(含总线驱动/功能驱动,以及设备栈中各层过滤驱动)和驱动安装程序(含驱动安装包/类安装程序/协安装程序)。本篇记录在xp下调试busenum驱动入口(关于环境的搭建网上一搜一大把,这里就省了,当然也可以参考这篇:win7 x64部署和串口调试虚拟驱动toaster)。

    通过添加硬件的方式安装busenum.sys后,会依次进入busenum.c!DriverEntry和pnp.c!Bus_AddDevice。AddDevice是本篇的重点,因此进入DriverEntry后在这个函数上下一个断点:

kd> lmvm busenum //查看驱动和调试符号加载是否正确start    end        module nameb20e9000 b20f2b80   busenum    (private pdb symbols)  d:\winddk\7600.16385.1\src\general\toaster\wdm\bus\objchk_wxp_x86\i386\BusEnum.pdb    Loaded symbol image file: busenum.sys kd> !itoldyouso busenumbusenum.sys    Timestamp: 57639546  SizeOfImage: 9B80          pdb: d:\winddk\7600.16385.1\src\general\toaster\wdm\bus\objchk_wxp_x86\i386\BusEnum.pdb      pdb sig: A0EB3691-6995-416E-9BF4-C25A160C9318          age: 1Loaded pdb is d:\winddk\7600.16385.1\src\general\toaster\wdm\bus\objchk_wxp_x86\i386\BusEnum.pdbBusEnum.pdb      pdb sig: A0EB3691-6995-416E-9BF4-C25A160C9318          age: 1MATCH: BusEnum.pdb and busenum.sys
确定sys文件加载正确后,查找函数并下断点,然后继续运行:
kd> x busenum!Bus_AddDeviceb20eca60 busenum!Bus_AddDevice (struct _DRIVER_OBJECT *, struct _DEVICE_OBJECT *)kd> bp busenum!Bus_AddDevicekd> bl 1 e b20eca60     0001 (0001) busenum!Bus_AddDevice
当windbg进入Bus_AddDevice遇到断点时,函数有两个参数:PDRIVER_OBJECT DriverObject和PDEVICE_OBJECT PhysicalDeviceObject。DriverObject很好理解,就是busenum.sys,有windbg为证:

kd> dd DriverObject l1f8ae99e8  8227a3b8kd> !drvobj 8227a3b8Driver object (8227a3b8) is for: \Driver\busenum

PhysicalDeviceObject是什么 呢?如果是pnp设备驱动,那很简单,这就是底层总线驱动对应的设备。但busenum本身是总线驱动,谁提供底层设备?答案是pnp管理器

kd> dd PhysicalDeviceObject l1f8ae99ec  81f41030kd> !devobj 81f41030 ---> 这个设备是pnp创建的设备Device object (81f41030) is for: 00000082 \Driver\PnpManager DriverObject 823eb2b0 ---> windbg指出,创建设备对象的驱动对象kd> !drvobj 823eb2b0Driver object (823eb2b0) is for: \Driver\PnpManager  --->驱动对象Driver Extension List: (id , addr)该驱动对象的设备对象Device Object list:81f41030  823e73d0  823e7610  823e7850
原来,pnp管理器为了维护一颗设备树,在加载总线驱动前会为总线设备创建一个pnpmanage设备对象,作为设备栈的栈底对象,让总线设备attach上去。在busenum.sys代码中也有这种设备栈的上下体现:

NTSTATUSBus_AddDevice(    __in PDRIVER_OBJECT DriverObject,    __in PDEVICE_OBJECT PhysicalDeviceObject    ){    status = IoCreateDevice (                    DriverObject,...,&deviceObject);    deviceData->UnderlyingPDO = PhysicalDeviceObject;    deviceData->NextLowerDriver = IoAttachDeviceToDeviceStack (                                    deviceObject,                                    PhysicalDeviceObject);}

首先代码创建busenum.sys的设备对象,然后attach到pnpmanager设备对象上。难怪toaster的帮助文档中注释这个对象为Fdo,而把Bus_AddDevice的第二个参数认为是Pdo。

来看下创建设备后设备栈情况:

kd> !drvobj 8227a3b8Driver object (8227a3b8) is for: \Driver\busenumDriver Extension List: (id , addr);相比刚进入DriverEntry时,现在busenum驱动对象下已经有一个设备对象了,这个就是调用IoCreateDevice时创建的Device Object list:81f2a930
kd> dd deviceObject l1f8ae99dc  81f2a930 ;设备对象的地址kd> !devobj 81f2a930 ;验证一下设备对象的属主Device object (81f2a930) is for:  \Driver\busenum DriverObject 8227a3b8 Current Irp 00000000 RefCount 0 Type 0000002a Flags 00000088DevExt 81f2a9e8 DevObjExt 81f2aa90 ExtensionFlags (0000000000)  Device queue is not busy.
kd> !devstack 81f2a930 ;81f2a930就是前面IoCreateDevice创建的设备对象  !DevObj   !DrvObj            !DevExt   ObjectName > 81f2a930  \Driver\busenum    81f2a9e8    81f41030  \Driver\PnpManager 00000000  00000082  !DevNode 81f2a008 :  DeviceInst is "ROOT\UNKNOWN\0000" ;设备实例  ServiceName is "busenum"          ;设备对应的服务名

至此busenum的设备栈已经成形了,可以创建Fdo了。

在结束本文前,还有一些琐碎的东西需要记录。就是busenum.inf中DDinstall section

    安装busenum驱动后,打开设备管理器,在system devices下可以看到设备对象。



如图所示,设备出现在system devices下,设备实例是ROOT\Unknow\0000。问题来了,为什么会这样?

首先,设备管理器是以类设备为视图,不同的设备类归入不同的类下(物以类聚)。因此出现在system devices下一定是刻意设定,那么这由谁来设定?当然是inf文件了,在version节中指定:下面的内容摘自bus.inf

[Version]Signature="$WINDOWS NT$"Class=System ;指明busenum属于system类ClassGuid={4D36E97D-E325-11CE-BFC1-08002BE10318} ;类的guidProvider=%MSFT%DriverVer=09/21/2006,6.0.5736.1CatalogFile=toaster.cat
其次,硬件ID,由inf文件DDinstall节指定,msdn文档上一般将DDinstall节认为是从Manufacturer开始:

[Manufacturer]%StdMfg%=Standard[Standard]; These are the toaster bus pnp ids%ToasterBus.DeviceDesc%=ToasterBus_Device, root\busenum ;root\busenum指定了设备的HardwareID
有了这两项,在结合驱动在注册表下的路径可以找到相应的信息:

先确定设备的总线关系,inf文件中已经指出了busenum属于root总线,它在注册表中的路径为:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\Root

设备实例ROOT\Unknow\0000表明,busenum在root总线的Unknow\0000下,在这个项中可以找到驱动的service和class信息:



1)通过ROOT\Unknow\0000索引驱动的service为busenum

在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\{SerivceName}下可以找到各种驱动注册的服务相关的注册表值:

对于busenum驱动ServiceName是busenum


ImagePath是驱动程序被安装的路径,这些信息在Inf文件中都有对应内容,

[ToasterBus_Device.NT.Services] ;这个节是服务安装节AddService = busenum,%SPSVCINST_ASSOCSERVICE%, busenum_Service_Inst 
;AddService对应驱动在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\下创建的服务名{4D36E97D-E325-11CE-BFC1-08002BE10318}; -------------- busenum driver install sections[busenum_Service_Inst]DisplayName    = %busenum.SVCDESC% ;<span style="font-family: Arial, Helvetica, sans-serif;">busenum.SVCDESC</span><span style="font-family: Arial, Helvetica, sans-serif;">=busenum.SVCDESC = "Toaster Bus Enumerator"对应注册表项DisplayName和在设备管理器上显示的名字</span>ServiceType    = 1               ; SERVICE_KERNEL_DRIVER StartType      = 3               ; SERVICE_DEMAND_START <span style="font-family: Arial, Helvetica, sans-serif;">;对应注册表的Start</span>ErrorControl   = 1               ; SERVICE_ERROR_NORMALServiceBinary  = %12%\busenum.sys                       ;对应注册表中ImagePathLoadOrderGroup = Extended Base

2)通过ROOT\Unknow\0000索引驱动的class信息

在HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{ClassGuid}
对于busenum驱动ClassGuid是{4D36E97D-E325-11CE-BFC1-08002BE10318},挨个找过去可以找到busenum注册表项:


这里InfPath名为oem12.inf,是因为系统把所有inf文件拷到系统路径后(c:\windows\inf),统一命名为oemxx.inf形式。而InfSection应该对应了设备的DDInstall节,这个节可能是当系统重启时需要加载设备时到对应的oemxx.inf中寻找DDInstall进行驱动安装的依据


0 0
原创粉丝点击