irp概述

Windows驱动开发模式(WDM)编程基础 WDM(Windows Driver Model)是微软公司开发的一种驱动程序架构,用于实现硬件设备与Windows操作系统的通信。它支持多个设备和设备类别,包括键盘、鼠标、显示器、打印机等。WDM驱动不仅管理硬件资源,还负责将硬件的物理特性抽象化,提供给上层应用程序一个统一的接口。WDM驱动程序通常被分为功能驱动(Function Driver)和过滤驱动(Filter Driver)。功能驱动直接与设备进行交互,处理设备特定的任务; 阅读详情
一、简述
任何内核模式程序在创建一个IRP时,都同时创建了一个与之关联的IO_STACK_LOCATION结构数组:数组中的每个堆栈单元都对应一个将处理该IRP的驱动程序,另外还有一个堆栈单元供IRP的创建者使用。堆栈单元中包含该IRP的类型代码和参数信息以及完成函数的地址。IRP的CurrentLocation为当前IO堆栈单元的索引,IRP的Tail.Overlay.CurrentStackLocation就是指向它的指针。CurrentLocation的最小值是1(注意:不是0)并且从上到下依次变小.每一层驱动程序都必须负责设置下一层IO堆栈的内容,这样下一层驱动调用IoGetCurrentIrpStackLocation()时总能得到相应的数据。 Irp->StackCount的值等于IoAllocateIrp()的第一个参数,这个值不包括IRP的建立者拥有的那个堆栈。
二、跟IO堆栈操作相关的几个宏的说明:

1、#define IoGetNextIrpStackLocation( Irp ) (\

(Irp)->Tail.Overlay.CurrentStackLocation - 1 )

上面已经说明,CurrentLocation的值从上到下依次变小,而CurrentStackLocation与它相对应。现在返回比CurrentStackLocation小1的堆栈单元,实际上就是下一个单元,也就是上面的Filter Driver对应的那个堆栈单元。

注意:这个宏不会导致原来堆栈指针的变化。

2、#define IoSetNextIrpStackLocation( Irp ) {      \

    (Irp)->CurrentLocation--;                  \

(Irp)->Tail.Overlay.CurrentStackLocation--; }

这个宏把堆栈指针指向下一个堆栈单元。一般由IoCallDriver()在内部调用这个宏,因为调用IoCallDriver()时,下层驱动程序的派遣例程被调用,在那些派遣例程里边调用IoGetCurrentStackLocation()时得到的堆栈指针必须与下层驱动程序相对应,所以必须提前推进堆栈指针指向那个堆栈单元。

下面是IoCallDriver()的一个伪码:

NTSTATUS IoCallDriver(PDEVICE_OBJECT device, PIRP Irp)
{
  IoSetNextIrpStackLocation(Irp);
  PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
  stack->DeviceObject = device;
  ULONG fcn = stack->MajorFunction;
  PDRIVER_OBJECT driver = device->DriverObject;
  return (*driver->MajorFunction[fcn])(device, Irp);
}

3、#define IoGetCurrentIrpStackLocation( Irp ) ( (Irp)->Tail.Overlay.CurrentStackLocation )

得到当前堆栈指针。

4、#define IoCopyCurrentIrpStackLocationToNext( Irp ) { \

    PIO_STACK_LOCATION irpSp; \

    PIO_STACK_LOCATION nextIrpSp; \

    irpSp = IoGetCurrentIrpStackLocation( (Irp) ); \

    nextIrpSp = IoGetNextIrpStackLocation( (Irp) ); \

    RtlCopyMemory(nextIrpSp,irpSp,FIELD_OFFSET(IO_STACK_LOCATION, CompletionRoutine)); \

nextIrpSp->Control = 0; }

这个例程把“除了完成例程以外”的其它所有IO堆栈单元数据拷贝到下一个堆栈单元,以备下层驱动程序调用。

5、#define IoSkipCurrentIrpStackLocation( Irp ) \

    (Irp)->CurrentLocation++; \

(Irp)->Tail.Overlay.CurrentStackLocation++;

有些时候并不需要拷贝整个堆栈单元数据到下层堆栈,而是直接引用当前堆栈。利用这个宏就可以达到这个目的。这个宏把堆栈指针推回到上一层堆栈,回想一下上面给出的IoCallDriver()的伪码,在里边调用了IoSetNextIrpStackLocation(),而那个宏把堆栈指针推向下一层堆栈,两者中和的结果就是堆栈指针不变,这样当下层驱动调用IoGetCurrentStackLocation()时,它得到的堆栈指针和我们得到的指针完全一样。

三、推迟IRP地完成

如果一个驱动不能立刻完成一个IRP,则它可以返回STATUS_PENDING状态标明它还不能完成这个IRP,并且以后在完成该IRP会调用IoCompleteRequest()来完成这个IRP。

Code1:

IoMarkIrpPending(Irp)

Return STATUS_SUCCESS;

Code2:

Irp->IoStatus.Status = <Final-Status>

Irp->IoStatus.Information = <Size>

IoCompleteRequest(Irp);

Return <Final->Status>

四、IRP完成例程

本驱动的完成例程是设置在下一层IO堆栈中的

调用IoSetCompletionRoutine(
  IN PIRP  Irp,
  IN PIO_COMPLETION_ROUTINE  CompletionRoutine,
  IN PVOID  Context,
  IN BOOLEAN  InvokeOnSuccess,
  IN BOOLEAN  InvokeOnError,
  IN BOOLEAN  InvokeOnCancel

    );

#define IoSetCompletionRoutine( Irp, Routine, CompletionContext, Success, Error, Cancel ) { \

    PIO_STACK_LOCATION irpSp;                                               \

    ASSERT( (Success) | (Error) | (Cancel) ? (Routine) != NULL : TRUE );    \

    irpSp = IoGetNextIrpStackLocation( (Irp) );                             \

    irpSp->CompletionRoutine = (Routine);                                   \

    irpSp->Context = (CompletionContext);                                   \

    irpSp->Control = 0;                                                     \

    if ((Success)) { irpSp->Control = SL_INVOKE_ON_SUCCESS;

}               \

    if ((Error)) { irpSp->Control |= SL_INVOKE_ON_ERROR; }                  \

    if ((Cancel)) { irpSp->Control |= SL_INVOKE_ON_CANCEL; } }

可以设置一个完成例程。实际上这是一个宏,它的任务就是设置完成例程到下层驱动程序对应的IO堆栈中。当下层驱动调用IoCompleteRequest()时,这个函数将检查下层驱动对应的堆栈里边是否已经设置了完成例程。如果设置了,则调用相应的完成例程。IoCompleteRequest()将重复这个过程,直到已经到达了最上层驱动或者中间某个完成例程返回了STATUS_MORE_PROCESSING_REQUIRED状态。

完成例程一般如下:
NTSTATUS CompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID context)
{
  if (Irp->PendingReturned)
        IoMarkIrpPending(Irp);
  ...
  return <some status code>;
}

其中DeviceObject就是设置完成例程的当前设备对象,调用IoGetCurrentIrpStackLocation()得到的堆栈也是当前设备对象对应的堆栈。

注意前面两行代码,任何一个不返回STATUS_MORE_PROCESSING_REQUIRED状态的完成例程都应该有两行代码,这是为了保证IoCompleteRequest()可以一直重复调用上一层驱动的完成例程。

如果一个完成例程返回STATUS_MORE_PROCESSING_REQUIRED状态,IoCompleteRequest()将停止继续调用上一层驱动设置的完成例程,这时候的IRP处于一个中间状态,因此相应驱动的派遣例程有责任继续完成这个IRP,如下所示:

NTSTATUS

SfDirectoryControl(

    IN PDEVICE_OBJECT DeviceObject,

    IN PIRP Irp

    )

{

    PIO_STACK_LOCATION        IrpStack;

    IrpStack = IoGetCurrentIrpStackLocation(Irp);

    //

    // DO something at here

    //       

    Irp->IoStatus.Status = Status;

    IoCompleteRequest(Irp, IO_NO_INCREMENT);

    return Status;

}

//---------------------------------------------------------------------------

//

// 处理IRP_MJ_DIRECTORY_CONTROL的完成例程

//

NTSTATUS

SfDirectoryControlCompletion(

    IN PDEVICE_OBJECT   DeviceObject,

    IN PIRP             Irp,

    IN PVOID            Context

    )

{                               

    UNREFERENCED_PARAMETER(DeviceObject);

    UNREFERENCED_PARAMETER(Irp);

//

// 不能再调用IoMarkIrpPending()函数,因为返回值是

// STATUS_MORE_PROCESSING_REQUIRED。

//

    KeSetEvent((PKEVENT)Context,IO_NO_INCREMENT,false);

   

    return STATUS_MORE_PROCESSING_REQUIRED;

}
USB驱动开发实例与测试流程 USB驱动程序是操作系统与USB设备通信的桥梁,它负责将高层的应用程序请求转化为USB设备能理解的硬件请求。没有驱动程序,USB设备就像一个无法理解人类语言的外国人,无法与计算机系统有效交互。开发USB驱动程序需要一个特定的环境,这个环境包含了软件工具、编译器、调试器和各种库文件。下面的章节将详细介绍如何设置和配置这些组件,以便于进行高效的USB驱动程序开发。在开发USB驱动程序之前,首先要熟悉与之相关的开发工具。以下是三个主要的开发工具:VC6.0、DDK2600、DriverStudio。 阅读详情

相关推荐

低电压高效率能源管理芯片BQ25570的基本用法及应用电路实例

BQ25570是一款低电压、高效率、集成了可编程功率追踪(MPPT)功能、BOOST升压功能和BUCK降压功能的综合型能源管理电路。冷启动工作电压为330mV,热启动工作电压为100mV。主要应用于温差发电片TEG、压电、摩擦发电和太阳能板的能量收集,也可以用于人体可穿戴自取能传感设备的能量管理。本文主要介绍了BQ25570相关参数计算、MPPT功能验证、工作逻辑和应用场景,并设计了一版测试电路,给出了不同应用需求的电路配置建议。

weixin_49213602的博客 3450

Windows驱动开发系列之三:WDF驱动开发入门

我将带领大家学习WDM驱动开发,包括重要的理论与实践。我们逐步深入,在系列一和二的基础上慢慢推进,开始学习WDF驱动模型,包括面向对象和事件机制、重要的WDF对象,具体章节包括:1)WDF编程框架:面向对象和事件机制2)WDF重要对象:驱动对象、设备对象、IO队列、IO请求、等3)事件回调函数:从派遣函数到事件回调函数的原理流程解析4)WDF过滤驱动:掌握WDF对IRP的处理,以及过滤驱动的应用5)WDF驱动安装:掌握驱动安装原理和INF文件的重要概念 Windows内核开发寄语:1、Windows内核非常复杂,相关图书和课程都很少,让很多初学者望而生畏;没关系,我带领大家别有兴致地来领略Windows内核的神秘,解开面纱,层层深入。2、本书以Windows10x64位基准,所有程序都编译、运行在Vmware的Win10x64位机器上。vs2019+wdk3、内核学习并不可怕,授人以鱼不如授人以渔,艺多不压身,学习能提升人的综合能力,尤其是核心技术。

SAP ABAP实战:手把手教你用BAPI_BILLINGDOC_CREATEMULTIPLE批量开票(附完整代码与避坑指南)

本文详细解析了SAP ABAP中BAPI_BILLINGDOC_CREATEMULTIPLE批量开票的全流程,包括参数配置、事务控制、错误处理及性能优化。通过实战案例和完整代码示例,帮助开发者高效处理大批量发票生成任务,避免常见陷阱,提升开发效率。

weixin_34101914的博客 265

IoGetCurrentIrpStackLocation routine

IoGetCurrentIrpStackLocation routine IoGetCurrentIrpStackLocation 返回调用者在指定IRP中的 I/O stack location。 Syntax   PIO_STACK_LOCATION IoGetCurrentIrpStackLocation( _In_ PIRP Irp );   Parameters

死胖子的博客 3718

手把手教你用STM32F103的普通IO口读取SSI编码器(附完整代码与示波器调试心得)

本文详细介绍了如何利用STM32F103的普通IO口读取SSI绝对式编码器数据,提供完整的硬件连接方案、精确时序控制的软件实现及示波器调试技巧。通过低成本方案实现高精度位置反馈,适用于工业自动化和机器人控制领域。

weixin_29172963的博客 452

帆软报表开发-快速入门

数据可视化展示功能特点如下:选择权限管理 > 用户最终权限 > 汤姆(Tom) > 选择图表设计入门 > 打开查看权限。

郭宝的博客 5968

【IRP】Windows 驱动之IRP

什么是IRP: I/O request packets,简称IRP。即输入输出请求包。它是WINDOWS内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求。操作系统将相应的I/O请求转换为相应的IRP。不同的IRP会根据类型被分派的不同的派遣历程中进行处理。 作用: 上层应用程序于底层驱动之间的通讯,即EXE程序和SYS之间的通讯。 应用程序 想要访问内核数据,必须通过IRP数据。又叫IRP请求,当应用程序和驱动交互时,发送一个IRP请求,IRP会在各层设备驱动个之间

dr0op's blog 4914

180.在 Vue3 中使用 OpenLayers 实现多个多边形的绘制、编辑、删除与清空

【摘要】本文介绍如何在Vue3+TypeScript环境下使用OpenLayers实现多边形地图交互功能。通过Composition API封装核心逻辑,实现了多边形绘制、编辑、删除及清空等操作。关键技术包括:使用VectorLayer管理图形数据,Draw/Modify/Select交互控制,以及通过ref()管理交互状态。文中提供了完整代码示例,并解决了交互对象叠加问题,为开发GIS应用提供了基础模块。该方案支持扩展为数据库存储、后端交互等高级功能。

小彭的博客 769

关于windows驱动中的IO_STACK_LOCATION

理解IO_STACK_LOCATION是驱动入门的一个重要知识点,该结构体是理解驱动工作过程的核心知识之一。闲话不多时,直接看代码,看完下面几段windows源码,你要还不能理解,直接来找我。

要把所有那些负面的信息当做对自身行为的评价,而不是对自身价值的评判。 970

如何解除“无法完成操作 因为文件包含病毒或潜在垃圾软件”

当运行软件遇到“无法完成操作 因为文件包含病毒或潜在垃圾软件”时,如何解决?控制面板-系统和安全-Windows Defender防火墙-自定义设置,将专用网络及公用网络关闭。点击后,选择“病毒和威胁防护”-管理配置。进入安全中心后,选择“病毒和威胁防护”将需要排斥的选项输入后,保存配置即可。2:打开windows安全中心。

笔者从事电信媒体开发多年,愿意将多年的开发经验分享给同行 6万+

高精度导航 | RTK:2025年高精度导航算法综述,包括:原理,数据,公式,完整代码,开源代码链接

中国科学院国家授时中心的最新研究表明,PPP-AR/PPP-RTK增强算法使时间传递链路的稳定性提升超过30%,模糊度固定成功率高达93.57%,首次固定时间缩短至20分钟内。当这一愿景实现,人类社会的生产效率和资源利用率将迎来革命性提升,高精度定位将成为像电力、互联网一样的基础服务,深刻重塑我们的生活方式和文明形态。PPP-RTK作为GNSS定位领域的最前沿技术,成功融合了精密单点定位(PPP)和实时动态定位(RTK)的双重优势。,实现在无GNSS信号环境下(如隧道、地下停车场)的连续厘米级定位。

尘世冰封的专栏 1604

I/O Request Packet

第5章 I/O Request Packet 5.1 数据结构 在处理 I/O 请求上,有两个重要的数据结构:IRP(I/O request packet)和 IO_STACK_LOCATION 5.1.1 IRP 的结构 下面是在 windbg 里得到的 IRP 结构: nt!_IRP +0x000 Type : Int2B +0x002 Size

zhuo_zhibin的专栏 6094

Java全栈开发:充电桩管理系统项目实战

技术收获深入理解分布式系统架构掌握高并发场景解决方案提升系统设计能力经验教训前期需求分析的重要性技术选型需要考虑长期维护测试覆盖率的重要性未来展望引入AI预测故障支持更多支付方式优化用户体验通过此项目的开发,不仅实现了充电桩的智能化管理,也积累了宝贵的全栈开发经验。项目中的很多技术方案和架构设计都具有普遍适用性,可以在其他类似项目中借鉴使用。@Componentstatic {// 初始化状态转换规则。

exlink2012的专栏 1251

IRP概述

一、简述<br />任何内核模式程序在创建一个IRP时,都同时创建了一个与之关联的IO_STACK_LOCATION结构数组:数组中的每个堆栈单元都对应一个将处理该IRP的驱动程序,另外还有一个堆栈单元供IRP的创建者使用。堆栈单元中包含该IRP的类型代码和参数信息以及完成函数的地址。IRP的CurrentLocation为当前IO堆栈单元的索引,IRP的Tail.Overlay.CurrentStackLocation就是指向它的指针。CurrentLocation的最小值是1(注意:不是0)并且从上到下

houjinfeng210的专栏 1173

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

IRP结构体之Flag成员

IRP_DEALLOCATE_BUFFER //在I/O管理器将在该IRP完成阶段释放缓冲区。IRP_SYNCHRONOUS_API //该操作是一个同步分页I/O操作。IRP_BUFFERED_IO //该操作是一个缓冲的I/O操作。IRP_OB_QUERY_NAME //该操作是异步的名称查询。IRP_DEFER_IO_COMPLETION //I/O操作完成被推迟。IRP_HOLD_DEVICE_QUEUE //保留。

weixin_44628381的博客 198

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

TDI网络过滤驱动开发指南

首先我们来看一下Windows的网络模块架构,如下:ws2_32.dll提供了基本的socket相关函数(例如socketbindlisten等)。Windows在用户层提供了一种过滤网络数据包的HOOK方案,这个就是Layered service provider(也就是我们通常说的LSP),通过这种技术我们对网络包进行HOOK了,国内很多大厂用的都是这种技术。Socket是一种统一的规范,无论是Windows还是Linux他们对外提供的接口都是一样的。

xsinlink的博客 1352

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

函数指针、函数数组的使用

在学习驱动编程的过程中,碰到函数指针的使用,如下: pDriverObject->MajorFunction[IRP_MJ_CREATE]=ddk_DispatchRoutine_CONTROL; //IRP_MJ_CREATE相关IRP处理函数 NTSTATUS ddk_DispatchRoutine_CONTROL(IN PDEVICE_OBJECT pDevobj,IN PIRP p

h_james的博客 526

Windows 驱动开发 新手入门(一)

Windows 驱动开发 新手入门(一)引言驱动介绍Win10 WDK建立一个驱动项目建立MyDriver.cpp理论知识驱动入口派遣函数 MajorFunctionDevice和SymbolicLinkDeviceExtensionIRP 引言 本文是对Windows下的驱动开发有一个简单的介绍,我尽可能写的小白文一些,因为大多数的驱动开发书籍对新手来说还是过于难理解。 驱动介绍 在介绍驱动开发之前,先了解一下基础知识,驱动是什么的? 驱动这个词是由Driver直译的,这和平常开发中的测试驱动开发(TD

Doub1's Blog 2万+

Linux驱动与应用层通信,USB设备驱动层与应用层和硬件的通信过程.

1、USB设备驱动程序(1)驱动程序的基本概念设备驱动程序是一个包含了许多操作系统可调用例程的软件容器,它可以使得应用程序访问硬件设备,这些例程可以使硬件设备执行相应的动作。也就是处理硬件设备连接到CPU通信的细节的代码。硬件设备可能是任何连接到计算机的电子电路。一个设备驱动应使得应用程序远离细节,使应用程序不必知道物理连接、信号和与一个设备通信需要的协议等。应用程序是用户运行的程序,包括支持自定...

weixin_42501077的博客 494

驱动编程---来个例子感性认识下

from:http://blog.sina.com.cn/s/blog_61d65e360100gd7p.html 驱动编程---来个例子感性认识下 (2009-12-17 01:03:46) 转载▼ 标签: 杂谈   下面是个例子,代码作者是张帆,我来详细解释,从中遇到知识点,我延伸出来分析。 忘记说了,前些日子,公司搬家,好了之后有累

kendyhj9999的专栏 1329

深度剖析WinPcap之(八)——打开与关闭适配器(17)

本文转自http://eslxf.blog.51cto.com/918801/209247   1.6      NPF中对应的函数接口 1.6.1        关键结构体 _OPEN_INSTANCE 结构体 _OPEN_INSTANCE包含NPF驱动程序一个运行实例的状态;这是NPF最重要的结构体:它被几乎所有驱动程序的函数使用;一个_OPEN_INSTANCE结构体与每个用户层

理性的幻想 581

驱动中的IRP

文章作者:grayfox 作者主页:http://nokyo.blogbus.com 原始出处:http://nokyo.blogbus.com/logs/34005738.html       此前我们可能曾经多次听说过IRP这个名词,那么它究竟是什么呢?       IRP的全名是I/O Request Package,即输入输出请求包,它是Windows内核中的一种非常重要的数据

ALCAT的专栏 6228
上一篇: IoSetCompletionRoutine
下一篇: IoMarkIrpPending
vbsourcecode
博客等级 码龄17年 19粉丝 3原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值