10、Windows驱动开发技术详解笔记(6) 基本语法回顾

简介: 7、I/O Request Package,输入输出请求包 1)基本概念 IRP 的全名是I/O Request Package,即输入输出请求包,它是Windows 内核中的一种非常重要的数据结构。

<?xml:namespace prefix = o />

7I/O Request Package,输入输出请求包

1)基本概念

IRP 的全名是I/O Request Package,即输入输出请求包,它是Windows 内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时,应用程序会发出I/O 请求,操作系统将相应的I/O 请求转换成相应的IRP,不同的IRP 会根据类型被分派到不同的派遣例程中进行处理。

IRP有两个基本的属性,即MajorFunction MinorFunction,分别记录IRP 的主类型和子类型。操作系统根据MajorFunction 决定将IRP 分发到哪个派遣例程,然后派遣例程根据MinorFunction 进行细分处理。

IRP的概念类似于Windows 应用程序中消息的概念。在Win32 编程中,程序由消息驱动,不同的消息被分发到不同的处理函数中,否则由系统默认处理。

文件I/O的相关函数例如CreateFileReadFileWriteFileCloseHandle等分别会引发操作系统产生 IRP_MJ_CREATEIRP_MJ_READIRP_MJ_WRITEIRP_MJ_CLOSE等不同的IRP,这些IRP会被传送到驱动程序的相应派遣例程中。

wps_clip_image-7876

IRP常见类型

typedef struct _IO_STATUS_BLOCK {

NTSTATUS Status;

ULONG Information;

}IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;

2IRP处理

以前知道:在DriverEntry中为不同的IRP设置相应的派遣例程。在派遣例程中处理IRP最简单做法就是将IRP的状态设置为成功,然后结束IRP请求并返回成功,同时还要记得设置这个IRP请求操作了多少字节。

我们在派遣函数中设置IRP的完成状态为STATUS_SUCCESS,发起I/O请求的Win32 API才能返回TRUE,否则Win32 API将返回FALSE,在这个时候可以通过GetLastError获得错误代码,这个错误代码会和此时IRP 被设置的状态一致。

如我们以前描述的派遣函数:

/************************************************************************

* 函数名称:HelloDDKDispatchRoutine

* 功能描述:对读IRP进行处理

* 参数列表:

pDevObj:功能设备对象

pIrp:IO请求包

* 返回 值:返回状态

*************************************************************************/

#pragma PAGEDCODE

NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,

IN PIRP pIrp)

{

KdPrint(("Enter HelloDDKDispatchRoutine\n"));

NTSTATUS status = STATUS_SUCCESS;

// 完成IRP

pIrp->IoStatus.Status = status;

pIrp->IoStatus.Information = 0; // bytes xfered

IoCompleteRequest( pIrp, IO_NO_INCREMENT );

KdPrint(("Leave HelloDDKDispatchRoutine\n"));

return status;

}

3IRPIO_STACK_LOCATION

开发一个驱动要有可能要处理各种IRP。我们先学习应用程序和驱动交互而产生的IRP。应用程序为了和驱动通信,首先必须打开设备。然后发送或者接收信息,最后关闭它;这至少需要三个IRP:第一个是打开请求,第二个发送或者接收信息,第三个是关闭请求。

IRP的种类取决于主功能号。主功能号就是前面的说的DRIVER_OBJECT中的分发函数指针数组中的索引,打开请求的主功能号是IRP_MJ_CREATE,而关闭请求的主功能号是IRP_MJ_CLOSE

如果写有独立的处理IRP_MJ_CREATEIRP_MJ_CLOSE的分发函数,就没有必要自然判断IRP的主功能号。使用一个函数处理所有的IRP,那么首先就要得到IRP的主功能号。IRP的主功能号在IRP的当前栈空间中。

IRP总是发送给一个设备栈,到每个设备上的时候拥有一个当前栈空间来保存在这个设备上的请求信息。

NTSTATUS MyDispatchFunction(PDEVICE_OBJECT device,PIRP irp)

{

// 获得当前irp调用栈空间

PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation(irp);

NTSTATUS status = STATUS_UNSUCCESSFUL;

swtich(irpsp->MajorFunction)

{

// 处理打开请求

case IRP_MJ_CREATE:

……

break;

// 处理关闭请求

case IRP_MJ_CLOSE:

……

break;

// 处理设备控制信息

case IRP_MJ_DEVICE_CONTROL:

……

break;

// 处理读请求

case IRP_MJ_READ:

……

break;

// 处理写请求

case IRP_MJ_WRITE:

……

break;

default:

break;

}

return status;

}

4)打开和关闭

在一些有同步限制的驱动中(比如每次只允许一个进程打开设备)编程要更加复杂一点,现在忽略这些问题。

简单的返回一个IRP成功(或者直接失败)是三部曲,如下:

·设置irp->IoStatus.Information0

·设置irp->IoStatus.Status的状态。如果成功则设置STATUS_SUCCESS,否则设置错误码。

·调用IoCompleteRequest (irp,IO_NO_INCREMENT),这个函数完成IRP

以上三步完成后,直接返回irp->IoStatus.Status即可。

NTSTATUS

MyCreateClose(

IN PDEVICE_OBJECT device,

IN PIRP irp)

{

irp->IoStatus.Information = 0;

irp->IoStatus.Status = STATUS_SUCCESS;

IoCompleteRequest (irp,IO_NO_INCREMENT);

return irp->IoStatus.Status;

}

当然,在前面设置分发函数的时候,应该加上:

DriverObject->MajorFunctions[IRP_MJ_CREATE] = MyCreateClose;

DriverObject->MajorFunctions[IRP_MJ_CLOSE] = MyCreateClose;

在应用层,打开和关闭这个设备的代码如下:

HANDLE device=CreateFile("\\\\.\\MyCDOSL",

GENERIC_READ|GENERIC_WRITE,0,0,

OPEN_EXISTING,

FILE_ATTRIBUTE_SYSTEM,0);

if (device == INVALID_HANDLE_VALUE)

{

// …. 打开失败,说明驱动没加载,报错即可

}

// 关闭

CloseHandle(device);

目录
相关文章
|
11天前
|
安全 固态存储 文件存储
Windows 7纯净版重装教程|附微软原版镜像下载+驱动安装避坑技巧
本文详细介绍如何安全、高效地重装电脑系统,解决蓝屏、崩溃等问题。基于10年经验,涵盖从官方镜像获取、启动盘制作、数据备份到系统部署的全流程,并针对老旧机型优化。提供驱动一键安装工具和系统激活指南,确保无后门风险。文中还列出常见问题解决方案及操作禁忌,帮助用户顺利完成系统重装,让电脑重获新生。建议收藏并转发给有需要的朋友,欢迎留言咨询疑难问题。
|
3天前
|
算法 关系型数据库 测试技术
WHQL微软驱动签名方案,让驱动程序在Windows系统流畅运行
WHQL认证(Windows徽标认证)是微软设立的严格测试标准,旨在确保驱动程序的兼容性、稳定性和互通性。本文介绍了三种WHQL微软驱动签名方案:单系统签名、多系统签名和硬件兼容性测试方案,分别满足不同开发商的需求。通过WHQL认证,不仅能消除Windows安装警告,提升用户体验,还能获得“Designed for Windows”徽标授权,入列全球Windows Catalog及HCL产品表,提升品牌权威性和采购优先权。此外,访问微软OCA可获取错误反馈,助力产品质量改进。选择合适的签名方案,让驱动在Windows系统中流畅运行!
|
5月前
|
监控 Ubuntu Linux
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
这篇文章介绍了如何在Ubuntu和Windows系统中通过设置相同的时区并使用ntp服务来解决时间同步问题。
133 4
视频监控笔记(五):Ubuntu和windows时区同步问题-your clock is behind
|
5月前
|
Ubuntu Linux Python
如何利用wsl-Ubuntu里conda用来给Windows的PyCharm开发
如何在WSL(Windows Subsystem for Linux)的Ubuntu环境中使用conda虚拟环境来为Windows上的PyCharm开发设置Python解释器。
479 1
|
5月前
|
监控 关系型数据库 MySQL
PowerShell 脚本编写 :自动化Windows 开发工作流程
PowerShell 脚本编写 :自动化Windows 开发工作流程
235 0
|
7月前
|
vr&ar C# 图形学
WPF与AR/VR的激情碰撞:解锁Windows Presentation Foundation应用新维度,探索增强现实与虚拟现实技术在现代UI设计中的无限可能与实战应用详解
【8月更文挑战第31天】增强现实(AR)与虚拟现实(VR)技术正迅速改变生活和工作方式,在游戏、教育及工业等领域展现出广泛应用前景。本文探讨如何在Windows Presentation Foundation(WPF)环境中实现AR/VR功能,通过具体示例代码展示整合过程。尽管WPF本身不直接支持AR/VR,但借助第三方库如Unity、Vuforia或OpenVR,可实现沉浸式体验。例如,通过Unity和Vuforia在WPF中创建AR应用,或利用OpenVR在WPF中集成VR功能,从而提升用户体验并拓展应用功能边界。
155 1
|
6月前
|
存储 安全 程序员
Windows任务管理器开发原理与实现
Windows任务管理器开发原理与实现
|
7月前
|
开发者 C# Windows
WPF与游戏开发:当桌面应用遇见游戏梦想——利用Windows Presentation Foundation打造属于你的2D游戏世界,从环境搭建到代码实践全面解析新兴开发路径
【8月更文挑战第31天】随着游戏开发技术的进步,WPF作为.NET Framework的一部分,凭借其图形渲染能力和灵活的UI设计,成为桌面游戏开发的新选择。本文通过技术综述和示例代码,介绍如何利用WPF进行游戏开发。首先确保安装最新版Visual Studio并创建WPF项目。接着,通过XAML设计游戏界面,并在C#中实现游戏逻辑,如玩家控制和障碍物碰撞检测。示例展示了创建基本2D游戏的过程,包括角色移动和碰撞处理。通过本文,WPF开发者可更好地理解并应用游戏开发技术,创造吸引人的桌面游戏。
372 0
|
7月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
559 0
|
7月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
721 0