DDK样例toaster分析(2)

来源:互联网 发布:我的世界为什么用java 编辑:程序博客网 时间:2024/05/16 05:44

    前一篇 DDK样例toaster分析(1) 主要讨论了toaster样例中的busenum总线驱动。本篇将讨论从总线驱动过渡到功能驱动,也就是toaster.sys。

    成功安装busenum.sys后,运行toaster/exe/enum目录下的enum程序模拟一个toaster设备插入:

enum -p 1
    前面busenum.sys!Bus_AddDevice创建Fdo的同时还为Fdo创建一个接口:

status = IoRegisterDeviceInterface (                PhysicalDeviceObject,                (LPGUID) &GUID_DEVINTERFACE_BUSENUM_TOASTER,                NULL,                &deviceData->InterfaceName);DEFINE_GUID (GUID_DEVINTERFACE_BUSENUM_TOASTER,        0xD35F7840, 0x6A0C, 0x11d2, 0xB8, 0x41, 0x00, 0xC0, 0x4F, 0xAD, 0x51, 0x71);//  {D35F7840-6A0C-11d2-B841-00C04FAD5171}
    enum.exe通过SetupDi函数打开并通过ioctl访问这个接口:

hardwareDeviceInfo=SetupDiGetClassDevs(GUID_DEVINTERFACE_BUSENUM_TOASTER,...);SetupDiEnumDeviceInterfaces(hardwareDeviceInfo,...,&deviceInterfaceData);file = CreateFile ( deviceInterfaceDetailData->DevicePath,...);
    调用Ioctl后,最终进入到Bus_Ioctl中,因为是插入设备,所以最终会调用Bus_PlugInDevice

NTSTATUSBus_PlugInDevice (    PBUSENUM_PLUGIN_HARDWARE    PlugIn,    ULONG                       PlugInSize,    PFDO_DEVICE_DATA            FdoData    )
先看下FdoData中的内容,确定enum打开的是busenum.sys创建的Fdo:

kd> dd FdoData l10x81ec60e8kd> dt _FDO_DEVICE_DATA 81ec60e8busenum!_FDO_DEVICE_DATA+0x01c UnderlyingPDO    : 0x823e73d0 _DEVICE_OBJECTkd> !devobj 0x823e73d0 Device object (823e73d0) is for: 00000034 \Driver\PnpManager DriverObject 823eb2b0Current Irp 00000000 RefCount 1 Type 00000004 Flags 00001040Dacl e1594174 DevExt 823e7488 DevObjExt 823e7490 DevNode 823e7288 ExtensionFlags (0000000000)  AttachedDevice (Upper) 81ec6030 \Driver\busenumDevice queue is not busy.
FdoData用UnderlyingPDO指出了堆叠在设备下面的设备。从windbg的输出看出,UnderlyingPDO就是busenum.sys所依赖的pnpmanager设备对象。

    M$的帮助文档将busenum.sys!Bus_AddDevice创建的设备描述为Fdo,而将Bus_PlugInDevice创建的设备描述为Pdo。这是因为在Bus_PlugInDevice中创建出来的devobj代表了busenum总线对象,作为toaster.sys创建的设备对象的堆叠基石。另外也可以从windbg的输出看到,busenum新创建的设备对象并没有attach到任何已有设备对象上:
1).调用Bus_PlugInDevice!IoCreateDeviceSecure前,属于busenum.sys驱动对象的设备对象:

kd> !drvobj busenumDriver object (81dfdda0) is for: \Driver\busenumDriver Extension List: (id , addr)Device Object list:81ec6030 <---是attach在\Driver\PnpManager上的Fdo对象,上一张图中有描述
kd> !devstack 81ec6030    !DevObj   !DrvObj            !DevExt   ObjectName> 81ec6030  \Driver\busenum    81ec60e8    823e73d0  \Driver\PnpManager 823e7488  00000034!DevNode 823e7288 :  DeviceInst is "Root\UNKNOWN\0000"  ServiceName is "busenum"
上图中,busenum.sys只有一个设备对象
2).调用IoCreateDeviceSecure后,busenum.sys会新增一个设备对象:

kd> !drvobj busenumDriver object (81dfdda0) is for: \Driver\busenumDriver Extension List: (id , addr)Device Object list:82062408<---新加的设备对象  81ec6030 <---原有的设备对象kd> !devobj 82062408  Device object (82062408) is for: 0000008a \Driver\busenum DriverObject 81dfdda0Current Irp 00000000 RefCount 0 Type 0000002a Flags 000000c0Dacl e23ad84c DevExt 820624c0 DevObjExt 820624f8 ExtensionFlags (0000000000)  Device queue is not busy.
从windbg输出可以看到,这个新的设备对象下面并没有attach其他设备对象

之后,busenum为这个新创建的设备对象创建HardwareID(总线设备的职责不就是为新加入的设备分配设备ID吗?)

pdoData->HardwareIDs =            ExAllocatePoolWithTag (NonPagedPool, length, BUSENUM_POOL_TAG);RtlCopyMemory (pdoData->HardwareIDs, PlugIn->HardwareIDs, length);后分配busenum pdo的HardwardIDkd> dd pdoData l1b21fdbec  820624c0kd> dt _PDO_DEVICE_DATA  820624c0busenum!_PDO_DEVICE_DATA+0x020 HardwareIDs      : 0x8213aa50  -> 0x7bkd> du 0x8213aa50 <------注意,这是busenum.sys为pdo对象设置的硬件id,之后要按这个id匹配功能驱动8213aa50  "{B85B7C50-6A01-11d2-B841-00C04FA"8213aa90  "D5171}\MsToaster"

最后,Bus_PlugInDevice通过IoInvalidateDeviceRelations,通知pnp管理器:有新的设备加入设备树,pnp管理器要更新设备树关系(说人话,就是为新设备加载匹配的驱动)

    由于系统中并没有安装这个Pdo的驱动,因此会跳出搜索驱动的对话框,这里选择手动安装,选择toaster/inf/sample.inf文件。至于为什么要选这个文件,因为sample.inf文件的硬件兼容列表里表示支持这个设备:

[Manufacturer]%StdMfg%=Standard[Standard]; DisplayName       Section           DeviceId; -----------       -------           --------%ToasterDevice.DeviceDesc%=Toaster_Device, {b85b7c50-6a01-11d2-b841-00c04fad5171}\MsToaster <---硬件兼容列表
这个列表中的内容完全匹配新创建设备对象的HardwareID,因此系统加载sample.inf中指定的sys文件,并创建对应的服务,最后把执行权限交给toaster.sys:
[Version]Signature="$WINDOWS NT$"Class=TOASTERClassGuid={B85B7C50-6A01-11d2-B841-00C04FAD5171}Provider=%MSFT%DriverVer=09/21/2006,6.0.5736.1CatalogFile=toaster.cat...[Toaster_Device.NT]CopyFiles=Toaster_Device.NT.Copy[Toaster_Device.NT.Copy]toaster.sys
驱动安装后,设备管理器里多出一个toaster设备,查看Driver Detail可以看到驱动文件的信息:


   扯点题外话,可以通过Update Driver替换新的inf文件,比如选择toasterf.inf(含设备过滤驱动的toaster.sys),并指定sys文件路径后,再查看Driver Detail可以看到功能驱动和过滤驱动:(tmd公司要做驱动测试,测试老问我加载过滤驱动后,怎么在设备管理器里看到!还一定要在设备管理器里看到,注册表里不算,我折腾很久才发现这个!!)


    当然这种更新操作要底层设备支持disable/enable,像磁盘设备的,不支持disable/enable操作就不能这样更新驱动(这要感谢同事周AM的解释)
    好好,扯远了,回到正题,执行权从busenum.sys过渡到toaster.sys。当然了进入toaster.sys后还会调用toaster的AddDevice函数ToasterAddDevice,因此要在这个函数上下断:

DriverEntrykd> !drvobj 8216db10 Driver object (8216db10) is for: \Driver\toasterDriver Extension List: (id , addr)Device Object list:
kd> bp toaster!ToasterAddDevice;gkd> dd DriverObject l1f8aed9e8  8216db10kd> !drvobj 8216db10Driver object (8216db10) is for: \Driver\toasterDriver Extension List: (id , addr)Device Object list:
刚进入ToasterAddDevice时,驱动对象下还没有设备对象。顺带看下ToasterAddDevice的接口

NTSTATUSToasterAddDevice(    __in PDRIVER_OBJECT DriverObject,    __in PDEVICE_OBJECT PhysicalDeviceObject    )
DriverObject不用说肯定是toaster.sys的,PhysicalDeviceObject,则是前面busenum创建的pdo了(由于刚才更新驱动时停用启用过设备,设备对象跟上文不能连续了,不过还是能通过!drvobj !devstack来观察结果):

kd> dd PhysicalDeviceObject l1 ;<---PhysicalDeviceObject的值f8ae99ec  82062408kd> !devstack 82062408  ;<---通过设备堆栈证明这个是前面busenum创建的Pdo  !DevObj   !DrvObj            !DevExt   ObjectName> 82062408  \Driver\busenum    820624c0  0000008a ;<---这个设备对象下面并没有attach其他设备,跟上文的结论一下,因此可以认为是Pdo!DevNode 82266878 :  DeviceInst is "{B85B7C50-6A01-11d2-B841-00C04FAD5171}\MsToaster\1&1aafb3d5&0&01"  ServiceName is "toaster"kd> !drvobj busenum  ;<---当然,有人不信,那只能列出busenum驱动对象下的设备对象Driver object (81dfdda0) is for: \Driver\busenumDriver Extension List: (id , addr)Device Object list:82062408  81ec6030  <---这个驱动对像目前只有2个设备对象,为了证明82062408对象是Pdo,只要证明81ec6030  是Fdo就行了,剩下的靠排除法就能证明


kd> !devstack 81ec6030 ;<---81ec6030的设备栈显示,这个就是Fdo,attach在pnpmanager设备对象上!DevObj !DrvObj !DevExt ObjectName> 81ec6030 \Driver\busenum 81ec60e8 823e73d0 \Driver\PnpManager 823e7488 00000034!DevNode 823e7288 : DeviceInst is "Root\UNKNOWN\0000" ServiceName is "busenum"

之后,Toaster.sys调用IoCreateDevice创建功能驱动(注意是toaster.sys的Fdo不是busenum.sys的Fdo),把这个Fdo堆叠到busenum.sys的Pdo上:

status = IoCreateDevice (DriverObject,                             sizeof (FDO_DATA),                             NULL,                             FILE_DEVICE_UNKNOWN,                             FILE_DEVICE_SECURE_OPEN,                             FALSE,                             &deviceObject);...fdoData->NextLowerDriver = IoAttachDeviceToDeviceStack (deviceObject,                                                       PhysicalDeviceObject);

这样就完成了从busenum到toaster的过渡。




0 0