【原创】《windows驱动开发技术详解》第4章实验总结二

时间:2022-01-10 13:55:11
1 实验要求(WDM驱动)
 

【原创】《windows驱动开发技术详解》第4章实验总结二

 
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(("-------------------------------------\n"));
16 KdPrint(("Begin dump device stack\n"));
17 for (int i = 0; NULL != pdo; pdo = pdo->AttachedDevice, i++)
18 {
19 KdPrint(("the %d device in device stack\n", i));
20 KdPrint(("device attcheddevice:%#010x", pdo->AttachedDevice));
21 KdPrint(("device nextdevice:%#010x", pdo->NextDevice));
22 KdPrint(("device stacksize:%d\n", pdo->StackSize));
23 KdPrint(("device's driverobject:%#010x", pdo->DriverObject));
24 }
25 KdPrint(("Dump over\n"));
26 KdPrint(("-------------------------------------\n"));
27 }
28
29 #pragma PAGEDCODE
30 NTSTATUS AddDevice(PDRIVER_OBJECT pDriverObject, PDEVICE_OBJECT PhysicalDeviceObject) //形参不知道
31 {
32 PAGED_CODE();
33
34 KdPrint(("Enter AddDevice\n"));
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\n"));
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\n"));
80 KdPrint(("Leave DriverUnLoad\n"));
81 }
82
83 #pragma PAGEDCODE
84 NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP pIrp)
85 {
86 PAGED_CODE();
87 KdPrint(("Enter DefaultPnpHandler\n"));
88 //
89 IoSkipCurrentIrpStackLocation(pIrp);
90 KdPrint(("Leave DefaultPnpHandler\n"));
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\n"));
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\n"));
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\n"));
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\n"));
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\n"));
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)\n", fcnname[fcn]));
209 //!!!根据IRP的MINOR编号,调用相应的请求处理函数
210 status = (*fcntab[fcn])(pdx, Irp);
211 KdPrint(("Leave HelloWDMPnp\n"));
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\n"));
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\n"));
230 return STATUS_SUCCESS;
231 }

 

4 inf文件
;;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, PCI\VEN_9999
&DEV_9999
[Mfg0.NTamd64]
%DeviceDesc%=InstallLauncher, PCI\VEN_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, "System\CurrentControlSet\Services\WDM_Driver\Parameters","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, "System\CurrentControlSet\Services\WDM_Driver\Parameters","BreakOnEntry", 0x00010001, 0

[Strings]
MfgName="cpostute"
DeviceDesc="WDM_Driver"
DiskName="WDM_Driver Source Disk"
DeviceClassName = WDM_Driver

 

本文链接: http://www.cnblogs.com/cposture/p/4734288.html