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

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(("-------------------------------------\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

时间: 2024-10-16 03:36:11

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

《Windows驱动开发技术详解》之HelloDDK

编写如下代码: 运行会报错: 这里的原因是有没有引用到的形参,需要添加如下代码即可: 记得在系统启动时按F8禁用掉数字签名: 将编译好的驱动拖入虚拟机,以管理员身份运行DbgView捕捉内核态输出数据,以管理员身份运行InstDrv以加载驱动,我们就可以看到启动和停止时,DriverEntry和DriverUnload中输出的数据了: 下面,来对上面的实验进行简单的说明: Windows驱动程序的入口函数并不是main函数,而是DriverEntry函数,这个函数由内核中的I/O管理器负责调用.

《Windows驱动开发技术详解》之Windows内存管理

虚拟内存地址 Windows所有的程序(Ring0和Ring3层)可以操作的都是虚拟内存.有一部分单元会和物理内存对应起来,但并非一一对应,多个虚拟内存页可以映射同一个物理内存页.还有一部分单元会被映射成磁盘上的文件,并标记为脏的.读取这段虚拟内存的时候,系统会发出一个异常,此时会出发异常处理函数,异常处理函数会将这个页的磁盘文件读入内存,并将其标记为不脏.可以让那些经常不读写的内存页交换成文件,并设置为脏. Windows之所以如此设计,第一是虚拟的增加了内存的大小:第二是使不同进程的虚拟内存

《Windows驱动开发技术详解》之编程加载NT式驱动

之前我们加载驱动都是利用INSTDRV这个应用,其原理是在注册表中写入相应的字段,这一节我们手动编写代码去加载驱动,其原理类似: 设备驱动程序的动态加载主要由服务控制管理程序(Service Control Manager,SCM)系统组件完成.加载和卸载NT驱动分为四个步骤: 为NT驱动创建新的服务: 开启此服务: 关闭此服务: 删除NT驱动所创建的服务. LoadNTDriver装载驱动代码主要流程如下: 代码如下: 1 BOOL LoadNTDriver(char*lpszDriverNa

《Windows驱动开发技术详解》之IRP的同步

应用程序对设备的同步异步操作: 大部分IRP都是由应用程序的Win32 API函数发起的.这些Win32 API本身就支持同步和异步操作.例如,ReadFile.WriteFile和DeviceIoControl等,它们都有异步和同步两种操作方式.DeviceIoControl的同步操作如图所示: 同步操作时,DeviceIoControl的内部会调用WaitForSingleObject函数去等待一个事件.这个事件直到IRP结束才会触发.如果通过反汇编IoCompleteRequest内核函数

《Windows驱动开发技术详解》之读写操作

缓冲区方式读写操作 读写操作一般是由ReadFile和WriteFile函数引起的,这里先以WriteFile函数为例进行介绍.WriteFile要求用户提供一段缓冲区,并且说明缓冲区的大小,然后WriteFile将这段内存的数据传入到驱动程序中.这种方法,操作系统将应用程序提供缓冲区数据直接复制到内核模式的地址中.这样做,比较简单的解决了将用户地址传入驱动的问题,而缺点是需要在用户模式和内核模式之间复制数据,影响了效率.在少量内存操作时,可以采用这种方法.拷贝到内核模式下的地址由WriteFi

《Windows驱动开发技术详解》之定时器

I/O定时器 I/O定时器是DDK提供的一种定时器.它每个1s钟系统会调用一次I/O定时器例程.I/O定时器例程运行在DISPATCH_LEVEL级别,因此在这个例程中不能使用分页内存,否则会引起页故障从而导致系统崩溃.另外I/O定时器是运行在任一线程的,不一定是IRP发起的线程中,因此不能直接使用应用程序的内存地址. 初始化I/O定时器后,可以开启和停止I/O定时器.开启定时器后,每个1s系统调用一次定时器例程.在听指定是气候,系统就不会进入定时器例程.开启定时器的内核函数是IoStartTi

Windows驱动开发技术详解HelloWDM例子win7下无法安装

HelloWDM例子编译完成之后,在win7下安装显示 查看setupapi.dev看到如下信息 这个C:\MyDriver_Check目录完全不是我指定的,我放到c盘根目录下 查看inf [SourceDisksFiles] HelloWDM.sys = 1,MyDriver_Check, 把该字段修改为 HelloWDM.sys = 1 即可在win7下正确安装,这里“MyDriver_Check”指定了子目录,不过笔者试过在XP下面,没有修改inf安装的话,会弹出一个选择框让你重新选择.s

《Android底层接口与驱动开发技术详解》digest

第一章:IDE:Eclipse ADT for java developer其它: Apache Ant Java SE Development Kit5或6 Linux和Mac上使用Apache Ant 1.65+,Windows上使用1.7+版本:(单独的JRE是不可以的,必须要有JDK),不兼容Gnu Java编译器(gcj) Java_Home x:\xx\xx\java\JDK1.6.0-17classpath:.;%JAVA_HOME%/lib/rt.jar;%JAVA_HOME%/

hadoop应用开发技术详解

<大 数据技术丛书:Hadoop应用开发技术详解>共12章.第1-2章详细地介绍了Hadoop的生态系统.关键技术以及安装和配置:第3章是 MapReduce的使用入门,让读者了解整个开发过程:第4-5章详细讲解了分布式文件系统HDFS和Hadoop的文件I/O:第6章分析了 MapReduce的工作原理:第7章讲解了如何利用Eclipse来编译Hadoop的源代码,以及如何对Hadoop应用进行测试和调试:第8-9章 细致地讲解了MapReduce的开发方法和高级应用:第10-12章系统地讲