Friday, August 26, 2011

驱动对象、设备对象、设备栈----驱动程序基础概念(一)

刚开始接触驱动的时候,总是搞不清楚驱动对象、设备对象、设备栈等等基本概念,所以对驱动的开发也总是会出现一些奇怪的错误。但想要一下子说明白这些基本结构,也不是一件容易的事,最好的办法就是接触多了,了解多了,慢慢会清楚的。这里做一个总结,也希望能对初学者有所帮助。
一、 为了后面的叙述方便,首先列出驱动对象和设备对象的结构。
1.1 驱动对象结构 DRIVER_OBJECT ,结构图如下:

1.2 DDK 中有对于一些域的说明

[00] IRP_MJ_CREATE
[01] IRP_MJ_CREATE_NAMED_PIPE
[02] IRP_MJ_CLOSE
[03] IRP_MJ_READ
[04] IRP_MJ_WRITE
[05] IRP_MJ_QUERY_INFORMATION
[06] IRP_MJ_SET_INFORMATION
[07] IRP_MJ_QUERY_EA
[08] IRP_MJ_SET_EA
[09] IRP_MJ_FLUSH_BUFFERS
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION
[0b] IRP_MJ_SET_VOLUME_INFORMATION
[0c] IRP_MJ_DIRECTORY_CONTROL
[0d] IRP_MJ_FILE_SYSTEM_CONTROL
[0e] IRP_MJ_DEVICE_CONTROL
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL
[10] IRP_MJ_SHUTDOWN
[11] IRP_MJ_LOCK_CONTROL
[12] IRP_MJ_CLEANUP
[13] IRP_MJ_CREATE_MAILSLOT
[14] IRP_MJ_QUERY_SECURITY
[15] IRP_MJ_SET_SECURITY
[16] IRP_MJ_POWER
[17] IRP_MJ_SYSTEM_CONTROL
[18] IRP_MJ_DEVICE_CHANGE
[19] IRP_MJ_QUERY_QUOTA
[1a] IRP_MJ_SET_QUOTA
[1b] IRP_MJ_PNP
1.3 驱动对象扩展 _DRIVER_EXTENSION (sizeof=24),结构图如下:

2. 设备对象结构 DEVICE_OBJECT ,定义如下
struct _DEVICE_OBJECT (sizeof=184)
+00 int16 Type
+02 uint16 Size
+04 int32 ReferenceCount
+08 struct _DRIVER_OBJECT *DriverObject
+0c struct _DEVICE_OBJECT *NextDevice
+10 struct _DEVICE_OBJECT *AttachedDevice
+14 struct _IRP *CurrentIrp
+18 struct _IO_TIMER *Timer
+1c uint32 Flags
+20 uint32 Characteristics
+24 struct _VPB *Vpb
+28 void *DeviceExtension
+2c uint32 DeviceType
+30 char StackSize
+34 union __unnamed62 Queue
+34 struct _LIST_ENTRY ListEntry
+34 struct _LIST_ENTRY *Flink
+38 struct _LIST_ENTRY *Blink
+34 struct _WAIT_CONTEXT_BLOCK Wcb
+34 struct _KDEVICE_QUEUE_ENTRY WaitQueueEntry
+34 struct _LIST_ENTRY DeviceListEntry
+34 struct _LIST_ENTRY *Flink
+38 struct _LIST_ENTRY *Blink
+3c uint32 SortKey
+40 byte Inserted
+44 function *DeviceRoutine
+48 void *DeviceContext
+4c uint32 NumberOfMapRegisters
+50 void *DeviceObject
+54 void *CurrentIrp
+58 struct _KDPC *BufferChainingDpc
+5c uint32 AlignmentRequirement
+60 struct _KDEVICE_QUEUE DeviceQueue
+60 int16 Type
+62 int16 Size
+64 struct _LIST_ENTRY DeviceListHead
+64 struct _LIST_ENTRY *Flink
+68 struct _LIST_ENTRY *Blink
+6c uint32 Lock
+70 byte Busy
+74 struct _KDPC Dpc
+74 int16 Type
+76 byte Number
+77 byte Importance
+78 struct _LIST_ENTRY DpcListEntry
+78 struct _LIST_ENTRY *Flink
+7c struct _LIST_ENTRY *Blink
+80 function *DeferredRoutine
+84 void *DeferredContext
+88 void *SystemArgument1
+8c void *SystemArgument2
+90 uint32 *Lock
+94 uint32 ActiveThreadCount
+98 void *SecurityDescriptor
+9c struct _KEVENT DeviceLock
+9c struct _DISPATCHER_HEADER Header
+9c byte Type
+9d byte Absolute
+9e byte Size
+9f byte Inserted
+a0 int32 SignalState
+a4 struct _LIST_ENTRY WaitListHead
+a4 struct _LIST_ENTRY *Flink
+a8 struct _LIST_ENTRY *Blink
+ac uint16 SectorSize
+ae uint16 Spare1
+b0 struct _DEVOBJ_EXTENSION *DeviceObjectExtension
+b4 void *Reserved
2.1 设备对象扩展_DEVOBJ_EXTENSION
struct _DEVOBJ_EXTENSION (sizeof=36)
+00 int16 Type
+02 uint16 Size
+04 struct _DEVICE_OBJECT *DeviceObject
+08 uint32 PowerFlags
+0c *Dope
+10 uint32 ExtensionFlags
+14 void *DeviceNode
+18 struct _DEVICE_OBJECT *AttachedTo
+1c struct _LIST_ENTRY FileObjectList
+1c struct _LIST_ENTRY *Flink
+20 struct _LIST_ENTRY *Blink
二、简要说明
1. 向内存中载入一个驱动程序文件,就会有一个驱动对象(DRIVER_OBJECT)产生
2. 以驱动 i8042prt 为例简要说明过程(在这里我先做个说明,对于同时插有 ps/2 键盘和 ps/2 鼠标的计算机上, i8042prt 会创建两个设备对象,一个用于键盘,一个用于鼠标。i8042prt 是完成 ps/2 键盘驱动主要功能的驱动程序。)
2.1 驱动 i8042prt 是在系统初始化阶段,IO 管理器调用函数 nt!IopLoadDriver 读取注册表,获得驱动程序文件 i8042prt.SYS 的路径,将这个文件载入内存。
2.2 之后会调用 nt!ObCreateObject 创建一个驱动对象,并初始化这个驱动对象。
3. 设备对象的创建
设备对象(DEVICE_OBJECT)由驱动创建。一个驱动可以创建多个设备对象(DEVICE_OBJECT)。通过驱动对象(DRIVER_OBJECT),可以找到由该驱动创建的所有设备对象(DEVICE_OBJECT)。一个驱动创建的所有设备对象(DEVICE_OBJECT)链成一条链,该驱动的驱动对象(DRIVER_OBJECT)可以找到这个链。一个设备对象(DEVICE_OBJECT)也可以找到创建它的驱动的驱动对象(DRIVER_OBJECT)。
三、实际观察驱动 i8042prt
工具: WinDbg

No comments:

Post a Comment