1 实验要求(WDM驱动)
2 编写过程
2.1 确立整体架构
2.1.1 入口函数——DriverEntry
(1)作用
- 设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等
(2)注意
- AddDevice在Driver_Object结构体的DriverExtension->AddDevice,原型是NTSTATUS AddDevice (PDRIVER_OBJECT pDriverObject, PDEVICE_OBJECT PhysicaPhysicalDeviceObject);因为它需要一个最基本的驱动对象以及用于附加的物理设备对象
- 注册IRP_MJ_PNP请求函数,IRP请求函数的返回值和形参类型都一样
- 注册IRP_MJ_CREATE、 IRP_MJ_READ、IRP_MJ_WRITE、IRP_MJ_CLOSE请求,这里注册为同一个函数
2.1.2 添加设备——AddDevice
(1)作用
- 该函数由系统调用,用于创建设备对象,符号链接、附加到PDO
(2)注意
- 顺序问题:创建设备对象->符号链接->附加到PDO->设置设备拓展->设置设备对象Flags;符号链接最好紧接放在创建设备对象之后,后面三步位置可以随意,这样做是因为当符号链接创建失败后,要删除设备对象。如果把PDO后面三步放在符号链接前,如果没有对PDO进行脱离,再删除设备对象会产生问题;造成时间浪费。
- 附加到PDO函数:IoAttachDeviceToDeviceStack,注意返回值,返回的是附加设备的下层设备,如果没有过滤驱动,那么就是PDO。
- pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;这一步是必需的,保证设备初始化完毕。
2.1.3 驱动卸载——DriverUnLoad
(1)作用
- 这个和NT驱动有点区别,NT驱动要删除设备对象和符号链接,以及释放资源。而WDM的只需要释放资源即可。
(2)注意
- 返回值为VOID
2.1.4 驱动卸载——IRP_MN_REMOVE_DEVICE请求处理
(1)作用
- 删除设备对象和符号链接,脱离PDO
(2)注意
- 这个请求处理函数,名字自定义,但是返回值NTSTATUS,形参是PDEVICE_OBJECT和PIRP,这和所有PNP请求处理函数都一样
- 要对IRP的返回状态进行设置,主要是IoStatus.Status和IoStatus.Information
- IRP请求可以继续向底层转发,IoCallDriver
- IoDetachDevice的实参是被附加的设备对象
- 删除时,如果设备对象的NextDevice域不为空也要删除
2.1.5 PNP请求处理——IRP_MJ_PNP
(1)作用
- 处理各种类型PNP请求
(2)注意
- (根据Major分,这是一个大类)IRP_MJ_PNP请求,根据其Minor值还分了多种类型的PNP。
- 函数内部,主要就是从当前IRP堆栈里获取Minor值,然后再调用相应的处理函数,比如上文的IRP_MN_REMOVE_DEVICE
- 获取Minor值方法:PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);ULONG fcn = stack->MinorFunction;
- 要知道PNP的请求列表,对于IRP_MN类的请求处理,如果是要转发到下一层则可以不用对IoStatus的返回情况进行设置,否则要对其进行设置
2.1.6 PNP请求Minor值对应的请求的默认处理
(1)作用
- 处理具体类型PNP请求
(2)注意
- 对于IRP_MN类的请求处理,如果是要转发到下一层则可以不用对IoStatus的返回情况进行设置,否则要对其进行设置
- 请求可以转发给下层IoCallDriver,也可以进行完成处理
3 完整代码
1 #include <wdm.h> 2 3 typedef struct { 4 UNICODE_STRING devName; 5 UNICODE_STRING linkName; 6 PDEVICE_OBJECT fdo; 7 PDEVICE_OBJECT nextStackDevice; 8 }DEVICE_EXTENSION, *PDEVICE_EXTENSION; 9 10 #pragma PAGEDCODE 11 void dump(PDEVICE_OBJECT pdo) 12 { 13 PAGED_CODE(); 14 //显示调试信息 15 KdPrint(("------------------------------------- ")); 16 KdPrint(("Begin dump device stack ")); 17 for (int i = 0; NULL != pdo; pdo = pdo->AttachedDevice, i++) 18 { 19 KdPrint(("the %d device in device stack ", i)); 20 KdPrint(("device attcheddevice:%#010x", pdo->AttachedDevice)); 21 KdPrint(("device nextdevice:%#010x", pdo->NextDevice)); 22 KdPrint(("device stacksize:%d ", pdo->StackSize)); 23 KdPrint(("device's driverobject:%#010x", pdo->DriverObject)); 24 } 25 KdPrint(("Dump over ")); 26 KdPrint(("------------------------------------- ")); 27 } 28 29 #pragma PAGEDCODE 30 NTSTATUS AddDevice(PDRIVER_OBJECT pDriverObject, PDEVICE_OBJECT PhysicalDeviceObject) //形参不知道 31 { 32 PAGED_CODE(); 33 34 KdPrint(("Enter AddDevice ")); 35 36 NTSTATUS status; 37 PDEVICE_OBJECT pDeviceObject; 38 UNICODE_STRING devName, linkName; 39 PDEVICE_EXTENSION pDevExt; 40 41 //创建设备对象 42 RtlInitUnicodeString(&devName, L"\Device\WDM_ChenJiaqi"); 43 status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObject); 44 if (!NT_SUCCESS(status)) 45 { 46 return status; 47 } 48 //创建符号链接 49 RtlInitUnicodeString(&linkName, L"\??\WDM_ChenJiaqi"); 50 status = IoCreateSymbolicLink(&linkName, &devName); 51 if (!NT_SUCCESS(status)) 52 { 53 IoDeleteDevice(pDeviceObject); 54 return status; 55 } 56 //将FDO附加到PDO之上 57 PDEVICE_OBJECT pNextStackDevice = IoAttachDeviceToDeviceStack(pDeviceObject, PhysicalDeviceObject); 58 //设置设备扩展 59 pDevExt = reinterpret_cast<PDEVICE_EXTENSION>(pDeviceObject->DeviceExtension); 60 pDevExt->devName = devName; 61 pDevExt->linkName = linkName; 62 pDevExt->fdo = pDeviceObject; 63 pDevExt->nextStackDevice = pNextStackDevice; 64 //设备对象Flags 65 pDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE; 66 pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 67 68 dump(pNextStackDevice); 69 KdPrint(("Leave AddDevice ")); 70 return STATUS_SUCCESS; 71 } 72 73 #pragma PAGEDCODE 74 VOID DriverUnLoad(PDRIVER_OBJECT pDriverObject) 75 { 76 PAGED_CODE(); 77 //释放内存等相关操作 78 pDriverObject; 79 KdPrint(("Enter DriverUnLoad ")); 80 KdPrint(("Leave DriverUnLoad ")); 81 } 82 83 #pragma PAGEDCODE 84 NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP pIrp) 85 { 86 PAGED_CODE(); 87 KdPrint(("Enter DefaultPnpHandler ")); 88 // 89 IoSkipCurrentIrpStackLocation(pIrp); 90 KdPrint(("Leave DefaultPnpHandler ")); 91 // 92 return IoCallDriver(pdx->nextStackDevice, pIrp); 93 } 94 95 //对IRP_MN_REMOVE_DEVICE的处理,从DriverUnLoad的功能分离出来 96 #pragma PAGEDCODE 97 NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pDeviceExtension, PIRP pIrp) 98 { 99 PAGED_CODE(); 100 101 KdPrint(("Enter HandleRemoveDevice ")); 102 //设置IRP的完成状态 103 pIrp->IoStatus.Status = STATUS_SUCCESS; 104 pIrp->IoStatus.Information = 0; //读写字节数 105 //将IRP请求向底层驱动转发 106 NTSTATUS status = DefaultPnpHandler(pDeviceExtension, pIrp); //这个函数由我们自己编写 107 //删除符号链接 108 IoDeleteSymbolicLink(&pDeviceExtension->linkName); 109 //调用IoDetechDevice()把FDO从设备栈脱离开 110 IoDetachDevice(pDeviceExtension->nextStackDevice); 111 //删除FDO 112 IoDeleteDevice(pDeviceExtension->fdo); 113 KdPrint(("Leave HandleRemoveDevice ")); 114 return status; 115 } 116 117 #pragma PAGEDCODE 118 NTSTATUS DefaultDispatchRoutinue(PDEVICE_OBJECT pDeviceObject, PIRP pIrp) 119 { 120 //对IRP的处理 121 PAGED_CODE(); 122 KdPrint(("Enter DefaultDispatchRoutinue ")); 123 pDeviceObject; 124 //设置IRP返回情况 125 pIrp->IoStatus.Status = STATUS_SUCCESS; 126 pIrp->IoStatus.Information = 0; // no bytes xfered 127 //完成对IRP的处理 128 IoCompleteRequest(pIrp, IO_NO_INCREMENT); 129 KdPrint(("Leave DefaultDispatchRoutinue ")); 130 return STATUS_SUCCESS; 131 } 132 133 #pragma PAGEDCODE 134 NTSTATUS WDMPnp(IN PDEVICE_OBJECT fdo,IN PIRP Irp) 135 { 136 PAGED_CODE(); 137 138 KdPrint(("Enter HelloWDMPnp ")); 139 NTSTATUS status = STATUS_SUCCESS; 140 //得到设备拓展 141 PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension; 142 //得到当前IRP堆栈 143 PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp); 144 //定义函数指针列表 145 static NTSTATUS(*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) = 146 { 147 DefaultPnpHandler, // IRP_MN_START_DEVICE 148 DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE 149 HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE 150 DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE 151 DefaultPnpHandler, // IRP_MN_STOP_DEVICE 152 DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE 153 DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE 154 DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS 155 DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE 156 DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES 157 DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES 158 DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS 159 DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT 160 DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS 161 DefaultPnpHandler, // 162 DefaultPnpHandler, // IRP_MN_READ_CONFIG 163 DefaultPnpHandler, // IRP_MN_WRITE_CONFIG 164 DefaultPnpHandler, // IRP_MN_EJECT 165 DefaultPnpHandler, // IRP_MN_SET_LOCK 166 DefaultPnpHandler, // IRP_MN_QUERY_ID 167 DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE 168 DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION 169 DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION 170 DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL 171 }; 172 //得到IRP的Minor编号,了解它是哪种类型的PNP请求 173 ULONG fcn = stack->MinorFunction; 174 if (fcn >= sizeof(fcntab) / sizeof(fcntab[0])) 175 { // 未知的子功能代码 176 status = DefaultPnpHandler(pdx, Irp); // some function we don't know about 177 return status; 178 } 179 //PNP请求名列表 180 static char* fcnname[] = 181 { 182 "IRP_MN_START_DEVICE", 183 "IRP_MN_QUERY_REMOVE_DEVICE", 184 "IRP_MN_REMOVE_DEVICE", 185 "IRP_MN_CANCEL_REMOVE_DEVICE", 186 "IRP_MN_STOP_DEVICE", 187 "IRP_MN_QUERY_STOP_DEVICE", 188 "IRP_MN_CANCEL_STOP_DEVICE", 189 "IRP_MN_QUERY_DEVICE_RELATIONS", 190 "IRP_MN_QUERY_INTERFACE", 191 "IRP_MN_QUERY_CAPABILITIES", 192 "IRP_MN_QUERY_RESOURCES", 193 "IRP_MN_QUERY_RESOURCE_REQUIREMENTS", 194 "IRP_MN_QUERY_DEVICE_TEXT", 195 "IRP_MN_FILTER_RESOURCE_REQUIREMENTS", 196 "", 197 "IRP_MN_READ_CONFIG", 198 "IRP_MN_WRITE_CONFIG", 199 "IRP_MN_EJECT", 200 "IRP_MN_SET_LOCK", 201 "IRP_MN_QUERY_ID", 202 "IRP_MN_QUERY_PNP_DEVICE_STATE", 203 "IRP_MN_QUERY_BUS_INFORMATION", 204 "IRP_MN_DEVICE_USAGE_NOTIFICATION", 205 "IRP_MN_SURPRISE_REMOVAL", 206 }; 207 208 KdPrint(("PNP Request (%s) ", fcnname[fcn])); 209 //!!!根据IRP的MINOR编号,调用相应的请求处理函数 210 status = (*fcntab[fcn])(pdx, Irp); 211 KdPrint(("Leave HelloWDMPnp ")); 212 return status; 213 } 214 215 #pragma INITCODE 216 extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegisterPath) 217 { 218 //设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等 219 KdPrint(("Enter DriverEntry ")); 220 pRegisterPath; 221 //设置AddDevice函数 222 pDriverObject->DriverExtension->AddDevice = AddDevice; 223 //注册PNP 224 pDriverObject->MajorFunction[IRP_MJ_PNP] = WDMPnp; 225 pDriverObject->MajorFunction[IRP_MJ_CREATE] = 226 pDriverObject->MajorFunction[IRP_MJ_WRITE] = 227 pDriverObject->MajorFunction[IRP_MJ_READ] = 228 pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefaultDispatchRoutinue; 229 KdPrint(("Leave DriverEntry ")); 230 return STATUS_SUCCESS; 231 }
;;WDM_Driver inf文件--2015年8月14日 [Version] Signature = "$Windows NT$" Class = WDM_Driver ClassGUID = {EF2962F0-0D55-4bff-B8AA-2221EE8A79B0} Provider = cposture DriverVer = CatalogFile=WDM_Driver.cat CatalogFile.ntamd64=WDM_Driver.cat CatalogFile.nt=WDM_Driver.cat [ClassInstall32.NTamd64] AddReg=Class_AddReg [Class_AddReg] HKR,,,,%DeviceClassName% HKR,,Icon,,"-5" [SourceDisksNames] 1 = %DiskName%,, [SourceDisksFiles] WDM_Driver层次结构.sys = 1 WDM_Driver层次结构.sys = 1 [DestinationDirs] DefaultDestDir = 12 my_files_driver = 12 [my_files_driver] WDM_Driver层次结构.sys [my_files_driver64] WDM_Driver层次结构.sys [Manufacturer] %MfgName%=Mfg0,NT,NTamd64 [Mfg0.NT] %DeviceDesc%=InstallLauncher, PCIVEN_9999&DEV_9999 [Mfg0.NTamd64] %DeviceDesc%=InstallLauncher, PCIVEN_9999&DEV_9999 ;---------- DDInstall Sections ----------------------------------------------- [InstallLauncher.NT] CopyFiles=my_files_driver AddReg=Install_NT_AddReg [InstallLauncher.NT.Services] Addservice = WDM_Driver, 0x00000002, Sys_AddService [Sys_AddService] DisplayName = %DeviceDesc% ServiceType = 1 StartType = 3 ErrorControl = 1 ServiceBinary = %12%WDM_Driver层次结构.sys [Install_NT_AddReg] HKLM, "SystemCurrentControlSetServicesWDM_DriverParameters","BreakOnEntry", 0x00010001, 0 ;---------------------64位支持--------------- [InstallLauncher.NTamd64] CopyFiles=my_files_driver64 AddReg=Install_NT_AddReg64 [InstallLauncher.NTamd64.Services] Addservice = WDM_Driver, 0x00000002, Sys_AddService64 [Sys_AddService64] DisplayName = %DeviceDesc% ServiceType = 1 StartType = 3 ErrorControl = 1 ServiceBinary = %12%WDM_Driver层次结构.sys [Install_NT_AddReg64] HKLM, "SystemCurrentControlSetServicesWDM_DriverParameters","BreakOnEntry", 0x00010001, 0 [Strings] MfgName="cpostute" DeviceDesc="WDM_Driver" DiskName="WDM_Driver Source Disk" DeviceClassName = WDM_Driver