(二)、windows驱动开发的重要数据结构
一、DRIVER_OBJECT与DEVICE_OBJECT
DRIVER_OBJECT结构体
Major Function指的是分发函数
DriverUnload指的是卸载函数
DriverStart 驱动对象的起始地址
DriverName驱动名字
FastloDispatch快速IO分发函数
DeviceObject设备对象,设备对象链表的开始
Type 结构的类型
Size 结构的大小
DeviceObject
Characteristic: 设备特征
DeviceType:设备类型
CurrentIrp:当前Irp
NextDevice:下一个设备对象(一个驱动可能会创建多个设备对象)
DriverObject:指示该设备对象隶属于哪个驱动对象
DeviceExtension:符号扩展
Attach Device:上一个设备的指针(操作系统 采用使用成员)
ServiceKeyName:注册表项目名称
二、函数返回类型
三、创建设备对象
Exclusive:设置设备为互斥设备(即无法同时打开两个设备)
四、用代码创建设备对象
#include<ntddk.h> VOID DriverUnload(PDRIVER_OBJECT driver) { IoDeleteDevice(driver->DeviceObject);//删除驱动设备// KdPrint(("设备删除")); DbgPrint("Driver is unloading ...\r\n"); } NTSTATUS DriverEntry( PDRIVER_OBJECT driver, PUNICODE_STRING RegistryPath ) { UNREFERENCED_PARAMETER(RegistryPath); //该表明该变量未使用// NTSTATUS status; PDEVICE_OBJECT DeviceObject; //创建设备对象// UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloDDK"); //用宏来初始化字符串//注意这里必须是\\Device\\不然会蓝屏 KdPrint(("驱动加载")); status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);//非分页池// DbgPrint("设备创建\r\n"); DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;//设备已初始化完毕// driver->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
这里,注意设备路径名中的\\Device\\不能变,不然就蓝//
五、创建符号连接对象
下面借助微软提供的winobj工具
winobj中的Symboliclink符号连接相当于别名
比如图中懂得HardddiskVolumeShadow{}那一大串字符串就是起的别名
我们只能通过符号链接对象来找到设备对象
目前还没有符号链接
创建链接
#include<ntddk.h> VOID DriverUnload(PDRIVER_OBJECT driver) { UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\Global??\\HelloDDK"); IoDeleteSymbolicLink(&SymbolicLinkName); IoDeleteDevice(driver->DeviceObject);//删除驱动设备// KdPrint(("删除符号链接")); KdPrint(("设备删除")); DbgPrint("Driver is unloading ...\r\n"); } NTSTATUS DriverEntry( PDRIVER_OBJECT driver, PUNICODE_STRING RegistryPath ) { UNREFERENCED_PARAMETER(RegistryPath); //该表明该变量未使用// NTSTATUS status; PDEVICE_OBJECT DeviceObject; //创建设备对象// UNICODE_STRING DeviceName = RTL_CONSTANT_STRING(L"\\Device\\HelloDDK"); //用宏来初始化字符串//注意这里设备路径名中的\\Device\\不能变不然会蓝屏// UNICODE_STRING SymbolicLinkName = RTL_CONSTANT_STRING(L"\\Global??\\HelloDDK"); //Global可以省略 KdPrint(("驱动加载")); status = IoCreateDevice(driver, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &DeviceObject);//非分页池// if (!NT_SUCCESS(status)) { KdPrint(("设备创建失败\r\n")); return status; } DbgPrint("设备创建\r\n"); status = IoCreateSymbolicLink(&SymbolicLinkName, &DeviceName); //创建符号连接//两个参数都是PUNICODE_STRING,所以需要取地址// if (!NT_SUCCESS(status)) { KdPrint(("符号链接创建失败\n")); IoDeleteDevice(DeviceObject);//删除设备对象// return status; } KdPrint(("符号链接创建成功\n")); DeviceObject->Flags |= DO_BUFFERED_IO; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;//设备已初始化完毕// driver->DriverUnload = DriverUnload; return STATUS_SUCCESS; }
符号链接创建成功
注意,代码中符号链接的名字中 Global可以省略,只写??即可,微软会自动在Global下去创建符号链接
六、设备的层次结构
这里我们介绍一个新工具 DeviceTree
他能查看驱动与设备对象中的信息
IRP命令从上到下分配分发
七、打印一下驱动结构
VOID EnumDriver(PDRIVER_OBJECT DriverObject) { KdPrint(("Driver:%p\n", DriverObject)); KdPrint(("Device:%p\n", DriverObject->DeviceObject)); KdPrint(("驱动对象名:%wZ\n", &DriverObject->DriverName));////打印字符串结构用%Z表示%wZ表示是宽字符// KdPrint(("服务名:%wZ\n", &DriverObject->DriverExtension->ServiceKeyName));//服务名// KdPrint(("%wZ\n", DriverObject->HardwareDatabase));//数据库// }