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

- 设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等
- 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请求,这里注册为同一个函数
- 该函数由系统调用,用于创建设备对象,符号链接、附加到PDO
- 顺序问题:创建设备对象->符号链接->附加到PDO->设置设备拓展->设置设备对象Flags;符号链接最好紧接放在创建设备对象之后,后面三步位置可以随意,这样做是因为当符号链接创建失败后,要删除设备对象。如果把PDO后面三步放在符号链接前,如果没有对PDO进行脱离,再删除设备对象会产生问题;造成时间浪费。
- 附加到PDO函数:IoAttachDeviceToDeviceStack,注意返回值,返回的是附加设备的下层设备,如果没有过滤驱动,那么就是PDO。
- pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;这一步是必需的,保证设备初始化完毕。
- 这个和NT驱动有点区别,NT驱动要删除设备对象和符号链接,以及释放资源。而WDM的只需要释放资源即可。
- 返回值为VOID
- 删除设备对象和符号链接,脱离PDO
- 这个请求处理函数,名字自定义,但是返回值NTSTATUS,形参是PDEVICE_OBJECT和PIRP,这和所有PNP请求处理函数都一样
- 要对IRP的返回状态进行设置,主要是IoStatus.Status和IoStatus.Information
- IRP请求可以继续向底层转发,IoCallDriver
- IoDetachDevice的实参是被附加的设备对象
- 删除时,如果设备对象的NextDevice域不为空也要删除
- 处理各种类型PNP请求
- (根据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的返回情况进行设置,否则要对其进行设置
- 处理具体类型PNP请求
- 对于IRP_MN类的请求处理,如果是要转发到下一层则可以不用对IoStatus的返回情况进行设置,否则要对其进行设置
- 请求可以转发给下层IoCallDriver,也可以进行完成处理
#include <wdm.h>
typedef struct {
UNICODE_STRING devName;
UNICODE_STRING linkName;
PDEVICE_OBJECT fdo;
PDEVICE_OBJECT nextStackDevice;
}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
#pragma PAGEDCODE
void dump(PDEVICE_OBJECT pdo)
{
PAGED_CODE();
//显示调试信息
KdPrint(("-------------------------------------\n"));
KdPrint(("Begin dump device stack\n"));
for (int i = ; NULL != pdo; pdo = pdo->AttachedDevice, i++)
{
KdPrint(("the %d device in device stack\n", i));
KdPrint(("device attcheddevice:%#010x", pdo->AttachedDevice));
KdPrint(("device nextdevice:%#010x", pdo->NextDevice));
KdPrint(("device stacksize:%d\n", pdo->StackSize));
KdPrint(("device's driverobject:%#010x", pdo->DriverObject));
}
KdPrint(("Dump over\n"));
KdPrint(("-------------------------------------\n"));
}
#pragma PAGEDCODE
NTSTATUS AddDevice(PDRIVER_OBJECT pDriverObject, PDEVICE_OBJECT PhysicalDeviceObject) //形参不知道
{
PAGED_CODE();
KdPrint(("Enter AddDevice\n"));
NTSTATUS status;
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING devName, linkName;
PDEVICE_EXTENSION pDevExt;
//创建设备对象
RtlInitUnicodeString(&devName, L"\\Device\\WDM_ChenJiaqi");
status = IoCreateDevice(pDriverObject, sizeof(DEVICE_EXTENSION), &devName, FILE_DEVICE_UNKNOWN, , TRUE, &pDeviceObject);
if (!NT_SUCCESS(status))
{
return status;
}
//创建符号链接
RtlInitUnicodeString(&linkName, L"\\??\\WDM_ChenJiaqi");
status = IoCreateSymbolicLink(&linkName, &devName);
if (!NT_SUCCESS(status))
{
IoDeleteDevice(pDeviceObject);
return status;
}
//将FDO附加到PDO之上
PDEVICE_OBJECT pNextStackDevice = IoAttachDeviceToDeviceStack(pDeviceObject, PhysicalDeviceObject);
//设置设备扩展
pDevExt = reinterpret_cast<PDEVICE_EXTENSION>(pDeviceObject->DeviceExtension);
pDevExt->devName = devName;
pDevExt->linkName = linkName;
pDevExt->fdo = pDeviceObject;
pDevExt->nextStackDevice = pNextStackDevice;
//设备对象Flags
pDeviceObject->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
dump(pNextStackDevice);
KdPrint(("Leave AddDevice\n"));
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
VOID DriverUnLoad(PDRIVER_OBJECT pDriverObject)
{
PAGED_CODE();
//释放内存等相关操作
pDriverObject;
KdPrint(("Enter DriverUnLoad\n"));
KdPrint(("Leave DriverUnLoad\n"));
}
#pragma PAGEDCODE
NTSTATUS DefaultPnpHandler(PDEVICE_EXTENSION pdx, PIRP pIrp)
{
PAGED_CODE();
KdPrint(("Enter DefaultPnpHandler\n"));
//
IoSkipCurrentIrpStackLocation(pIrp);
KdPrint(("Leave DefaultPnpHandler\n"));
//
return IoCallDriver(pdx->nextStackDevice, pIrp);
}
//对IRP_MN_REMOVE_DEVICE的处理,从DriverUnLoad的功能分离出来
#pragma PAGEDCODE
NTSTATUS HandleRemoveDevice(PDEVICE_EXTENSION pDeviceExtension, PIRP pIrp)
{
PAGED_CODE();
KdPrint(("Enter HandleRemoveDevice\n"));
//设置IRP的完成状态
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = ; //读写字节数
//将IRP请求向底层驱动转发
NTSTATUS status = DefaultPnpHandler(pDeviceExtension, pIrp); //这个函数由我们自己编写
//删除符号链接
IoDeleteSymbolicLink(&pDeviceExtension->linkName);
//调用IoDetechDevice()把FDO从设备栈脱离开
IoDetachDevice(pDeviceExtension->nextStackDevice);
//删除FDO
IoDeleteDevice(pDeviceExtension->fdo);
KdPrint(("Leave HandleRemoveDevice\n"));
return status;
}
#pragma PAGEDCODE
NTSTATUS DefaultDispatchRoutinue(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
//对IRP的处理
PAGED_CODE();
KdPrint(("Enter DefaultDispatchRoutinue\n"));
pDeviceObject;
//设置IRP返回情况
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = ; // no bytes xfered
//完成对IRP的处理
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
KdPrint(("Leave DefaultDispatchRoutinue\n"));
return STATUS_SUCCESS;
}
#pragma PAGEDCODE
NTSTATUS WDMPnp(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
{
PAGED_CODE();
KdPrint(("Enter HelloWDMPnp\n"));
NTSTATUS status = STATUS_SUCCESS;
//得到设备拓展
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)fdo->DeviceExtension;
//得到当前IRP堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
//定义函数指针列表
static NTSTATUS(*fcntab[])(PDEVICE_EXTENSION pdx, PIRP Irp) =
{
DefaultPnpHandler, // IRP_MN_START_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_REMOVE_DEVICE
HandleRemoveDevice, // IRP_MN_REMOVE_DEVICE
DefaultPnpHandler, // IRP_MN_CANCEL_REMOVE_DEVICE
DefaultPnpHandler, // IRP_MN_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_CANCEL_STOP_DEVICE
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_RELATIONS
DefaultPnpHandler, // IRP_MN_QUERY_INTERFACE
DefaultPnpHandler, // IRP_MN_QUERY_CAPABILITIES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCES
DefaultPnpHandler, // IRP_MN_QUERY_RESOURCE_REQUIREMENTS
DefaultPnpHandler, // IRP_MN_QUERY_DEVICE_TEXT
DefaultPnpHandler, // IRP_MN_FILTER_RESOURCE_REQUIREMENTS
DefaultPnpHandler, //
DefaultPnpHandler, // IRP_MN_READ_CONFIG
DefaultPnpHandler, // IRP_MN_WRITE_CONFIG
DefaultPnpHandler, // IRP_MN_EJECT
DefaultPnpHandler, // IRP_MN_SET_LOCK
DefaultPnpHandler, // IRP_MN_QUERY_ID
DefaultPnpHandler, // IRP_MN_QUERY_PNP_DEVICE_STATE
DefaultPnpHandler, // IRP_MN_QUERY_BUS_INFORMATION
DefaultPnpHandler, // IRP_MN_DEVICE_USAGE_NOTIFICATION
DefaultPnpHandler, // IRP_MN_SURPRISE_REMOVAL
};
//得到IRP的Minor编号,了解它是哪种类型的PNP请求
ULONG fcn = stack->MinorFunction;
if (fcn >= sizeof(fcntab) / sizeof(fcntab[]))
{ // 未知的子功能代码
status = DefaultPnpHandler(pdx, Irp); // some function we don't know about
return status;
}
//PNP请求名列表
static char* fcnname[] =
{
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
};
KdPrint(("PNP Request (%s)\n", fcnname[fcn]));
//!!!根据IRP的MINOR编号,调用相应的请求处理函数
status = (*fcntab[fcn])(pdx, Irp);
KdPrint(("Leave HelloWDMPnp\n"));
return status;
}
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegisterPath)
{
//设置pDriverObject结构体,注册AddDevice和相关PNP函数,包括IRP_MJ_PNP,IRP_MJ_CREATE等
KdPrint(("Enter DriverEntry\n"));
pRegisterPath;
//设置AddDevice函数
pDriverObject->DriverExtension->AddDevice = AddDevice;
//注册PNP
pDriverObject->MajorFunction[IRP_MJ_PNP] = WDMPnp;
pDriverObject->MajorFunction[IRP_MJ_CREATE] =
pDriverObject->MajorFunction[IRP_MJ_WRITE] =
pDriverObject->MajorFunction[IRP_MJ_READ] =
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = DefaultDispatchRoutinue;
KdPrint(("Leave DriverEntry\n"));
return STATUS_SUCCESS;
}
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
【原创】《windows驱动开发技术详解》第4章实验总结二的更多相关文章
- Windows驱动——读书笔记《Windows驱动开发技术详解》
=================================版权声明================================= 版权声明:原创文章 谢绝转载 请通过右侧公告中的“联系邮 ...
- 【原创】《windows驱动开发技术详解》第4章实验总结一
目录 1 实验要求 2 编写过程 2.1 确立整体架构 2.1.1 入口函数——DriverEntry 2.1.2 自定义创建设备函数——CreateDevice 2.1.3 卸载函数——Driver ...
- 《Windows驱动开发技术详解》之分层驱动程序
分层驱动程序概念 分层的目的是将功能复杂的驱动程序分解成多个简单的驱动程序.一般来说,他们是指两个或两个 以上的驱动程序,它们分别创建设备对象,并且形成一个由高到低的设备对象栈.IRP请求一般会被传送 ...
- 《Windows驱动开发技术详解》之IRP的同步
应用程序对设备的同步异步操作: 大部分IRP都是由应用程序的Win32 API函数发起的.这些Win32 API本身就支持同步和异步操作.例如,ReadFile.WriteFile和DeviceIoC ...
- 《Windows驱动开发技术详解》之Windows内存管理
虚拟内存地址 Windows所有的程序(Ring0和Ring3层)可以操作的都是虚拟内存.有一部分单元会和物理内存对应起来,但并非一一对应,多个虚拟内存页可以映射同一个物理内存页.还有一部分单元会被映 ...
- 《Windows驱动开发技术详解》之HelloDDK
编写如下代码:
- 《Windows驱动开发技术详解》之驱动程序调用驱动程序——通过设备指针调用其他驱动程序
本节介绍“手动”构造各个IRP,然后将IRP传递到相应驱动程序的派遣函数里. 获得设备指针 每个内核中的句柄都会和一个内核对象的指针联系起来.ZwCreateFile内核函数可以通过设备名打开设备句柄 ...
- 《Windows驱动开发技术详解》之自定义StartIO
自定义StartIO 系统定义的StartIO队列只能使用一个队列(DDK提供的StartIO内部只有一个队列),这个队列将所有的IRP进行处理化.例如,读.写操作都会混在一起进行串行处理.然而,有时 ...
- 《Windows驱动开发技术详解》之驱动程序的同步处理
中断请求级 中断请求被分为软件中断和硬件中断两种,这些中断都映射成不同级别的中断请求级.每个中断请求都有各自的优先级别,正在运行的线程随时都可以被中断打断,进入到中断处理程序.优先级高的中断来临时,处 ...
随机推荐
- DataTransfer对象的一些总结
所有元素都支持防止目标事件,但是这些元素默认是不允许释放的,如果拖动元素经过不允许放置的元素无论用户如何操作,都不会触发drop事件,不过可以把任何元素变成有效的放置目标.方法是重写dropenter ...
- web测试和app测试的区别
功能上: 功能上没有什么区别,都是用同样的方法来写用例(等效.边界值...) 架构上: web是B/S架构(浏览器和服务器)代码更新后数据会同步,可以保证所有客户一致 app是C/S架构(客户端和服务 ...
- Ubuntu修改系统时间
在新版的ubuntu中,使用timedatectl 替换了ntpdate来进行时间管理. 1.查看当前时间状态 查看当前时间状态 timedatectl status : res@ubuntu:~$ ...
- JAVA:简单添加菜单界面(swing)第二版
环境:jdk1.8 package com.le.tool; import java.awt.Color; import java.awt.Container; import java.awt.Flo ...
- shell 日常技巧
批量注释: :<<COMMENT code COMMENT 循环: #!/bin/bash for varible1 in {1..5} #for varible1 in 1 2 3 ...
- 蓝桥杯_算法训练_Torry的困惑(基本型)
这个题目就是求质数的乘积,在加一个模,思路比较简单,直接上代码: #include<iostream> using namespace std; bool isPrime(int a) { ...
- 简易webpack 入门
webpack 模块打包机 作用:将浏览器不识别的语言转化成浏览器识别的语言 工作流程 通过一个入口文件 找到这个入口文件所依赖的所有模块,将这些文件打包成一个或多个文件 如何使用: 1.安装 cnp ...
- Python基础理论 - 常用模块
time模块:时间戳.时间字符串.时间对象以及如何转换 random模块:随机小数.整数.区间,随机列表元素,打散列表 os模块:与操作系统交互的一个接口,os.path操作文件的路径 sys模块:s ...
- TDD:什么是桩(stub)和模拟(mock)?
背景 本文假设你对TDD.Stub和Mock已经有了初步的认识,本文简单解释一下stub和mock的区别和使用场景,先看看他们之间的关系: 由上图可以知道mock框架可以非常容易的开发stub和moc ...
- 快速制作U盘启动盘和U盘安装盘的方法
制作U盘启动盘的方法: 1. 安装UltraISO; 2. 安装完成后,用管理员权限打开UltraISO; 3. 打开启动盘文件,一般为ISO文件: 4. 插入U盘: 5. 选择 启动 -> 写 ...