DDK样例toaster分析(2)

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/lixiangminghate/article/details/51705710

    前一篇 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

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

kd> dd FdoData l1
0x81ec60e8

kd> dt _FDO_DEVICE_DATA 81ec60e8
busenum!_FDO_DEVICE_DATA
	+0x01c UnderlyingPDO    : 0x823e73d0 _DEVICE_OBJECT

kd> !devobj 0x823e73d0 
Device object (823e73d0) is for:
 00000034 \Driver\PnpManager DriverObject 823eb2b0
Current Irp 00000000 RefCount 1 Type 00000004 Flags 00001040
Dacl e1594174 DevExt 823e7488 DevObjExt 823e7490 DevNode 823e7288 
ExtensionFlags (0000000000)  
AttachedDevice (Upper) 81ec6030 \Driver\busenum
Device 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 busenum
Driver object (81dfdda0) is for:
 \Driver\busenum
Driver 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 busenum
Driver object (81dfdda0) is for:
 \Driver\busenum
Driver Extension List: (id , addr)

Device Object list:
82062408<---新加的设备对象  81ec6030 <---原有的设备对象

kd> !devobj 82062408  
Device object (82062408) is for:
 0000008a \Driver\busenum DriverObject 81dfdda0
Current Irp 00000000 RefCount 0 Type 0000002a Flags 000000c0
Dacl 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的HardwardID
kd> dd pdoData l1
b21fdbec  820624c0
kd> dt _PDO_DEVICE_DATA  820624c0
busenum!_PDO_DEVICE_DATA
	+0x020 HardwareIDs      : 0x8213aa50  -> 0x7b
kd> 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=TOASTER
ClassGuid={B85B7C50-6A01-11d2-B841-00C04FAD5171}
Provider=%MSFT%
DriverVer=09/21/2006,6.0.5736.1
CatalogFile=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,因此要在这个函数上下断:

DriverEntry
kd> !drvobj 8216db10 
Driver object (8216db10) is for:
 \Driver\toaster
Driver Extension List: (id , addr)

Device Object list:
kd> bp toaster!ToasterAddDevice;g

kd> dd DriverObject l1
f8aed9e8  8216db10
kd> !drvobj 8216db10
Driver object (8216db10) is for:
 \Driver\toaster
Driver Extension List: (id , addr)

Device Object list:
刚进入ToasterAddDevice时,驱动对象下还没有设备对象。顺带看下ToasterAddDevice的接口

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

kd> dd PhysicalDeviceObject l1 ;<---PhysicalDeviceObject的值
f8ae99ec  82062408

kd> !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\busenum
Driver 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的过渡。




展开阅读全文

没有更多推荐了,返回首页