挂海论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
 友情提示:文字/图片广告均非网站意见,请担保交易勿直接付款,由此产生的责任自负
玩游戏来117游戏网(H5不下载也能玩手游传奇,吃鸡,竞技都有)不懂社区·好资源不错过·各位资源站大佬欢迎来采集搬运IOS签名/udid证书出售/送证书加群1040456405 ██【我要租此广告位】██
... .
查看: 2086|回复: 2
打印 上一主题 下一主题

[分享] 对IRP的一些理解

[复制链接]
4中级会员
520/600

520

积分

223

主题

5

听众
已帮网友解决0 个问题
好评
0
贡献
297
海币
3998
交易币
0
跳转到指定楼层
楼主
发表于 2015-2-10 00:16:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
提醒:若下载的软件是收费的"请不要付款",可能是骗子,请立即联系本站举报,执意要付款被骗后本站概不负责。(任何交易请走第三方中介,请勿直接付款交易以免被骗!切记).

友情提示:文字/图片广告均非本站意见,请担保交易勿直接付款,由此产生的责任自负!!!↑↑


假设某过滤驱动的分层结构如下:

1 FIDO  <-- 此时你在这里调用IoAllocateIrp()创建一个先的IRP往下层驱动FDO传送
2 FDO
3 PDO

这时创建出来的新IRP[假设用new_IRP来表示],那么new_IRP的StackCount只能是 >= 2,因为FIDO的下层驱动有2个分别是FDO和PDO。
此时new_IRP的IO堆栈单元为StackCount+1。 假设IO堆栈单元有3个,第3个IO堆栈单元表示new_IRP当前IO堆栈单元 第2个表示FDO的IO堆栈单元 第1个表示PDO的堆栈单元

那么如果要发送此IRP到下层驱动FDO,则预先初始化new_IRP的FDO的IO堆栈单元,也就是第二个IO堆栈单元。

此时new_IRP 的 StackCount = 2, CurrentLocation = 3 这里的3表示new_IRP的当前IO堆栈单元 如果你需要把此IRP完FDO驱动传递,那么不用初始化这个IO堆栈单元,为什么呢?

因为IoCallDriver() 内部会调用 类似 IoSetNextIrpStackLocation() 的操作来调整 CurrentLocation的索引。也就是 索引-1 ;

所以要调用IoCallDriver() 把new_IRP传递到FDO这个下层驱动,需要先调用IoGetNextIrpStackLocation() 获取FDO对应的IO堆栈单元,并进行初始化。
初始化完成后才能调用IoCallDriver()
此时new_IRP的 CurrentLocation = 2 这个索引才是指向FDO的IO堆栈单元

下面是来自WMD一书的例子:我上面的话就是为了理解下面的代码片断

发往派遣例程
创建完IRP后,你可以调用IoGetNextIrpStackLocation函数获得该IRP第一个堆栈单元的指针。然后初始化这个堆栈单元。在初始化过程的最后,你需要填充MajorFunction代码。堆栈单元初始化完成后,就可以调用IoCallDriver函数把IRP发送到设备驱动程序:

PDEVICE_OBJECT DeviceObject;     //something gives you this
PIO_STACK_LOCATION stack = IoGetNextIrpStackLocation(Irp);
stack->MajorFunction = IRP_MJ_Xxx;
<other initialization of "stack">
NTSTATUS status = IoCallDriver(DeviceObject, Irp);


IoCallDriver函数的第一个参数是你在某处获得的设备对象的地址。我将在本章的结尾处描述获得设备对象指针的两个常用方法。在这里,我们先假设你已经有了这个指针。

IRP中的第一个堆栈单元指针被初始化成指向该堆栈单元之前的堆栈单元,因为I/O堆栈实际上是IO_STACK_LOCATION结构数组,你可以认为这个指针被初始化为指向一个不存在的“-1”元素,因此当我们要初始化第一个堆栈单元时我们实际需要的是“下一个”堆栈单元。IoCallDriver将沿着这个堆栈指针找到第0个表项,并提取我们放在那里的主功能代码,在上例中为IRP_MJ_Xxx。然后IoCallDriver函数将利用DriverObject指针找到设备对象中的MajorFunction表。IoCallDriver将使用主功能代码索引这个表,最后调用找到的地址(派遣函数)。

你可以把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);
}

另:

1) Irp = IoAllocateIrp( IN CCHAR StackSize, IN BOOLEAN ChargeQuota);  

分配一个IRP,看看ms是怎么做的吧:

  a. ) packetSize = IoSizeOfIrp(StackSize);  



#define IoSizeOfIrp( StackSize ) \
    ((USHORT) (sizeof( IRP ) + ((StackSize) * (sizeof( IO_STACK_LOCATION )))))
计算 IRP的大小,看来一个IRP包括IRP头本身和stack location × StackSize,

  b.) irp = ExAllocatePoolWithTag(NonPagedPool, allocateSize, ' prI');

  分别空间,并且是分配在非分页内存池中。

c) IopInitializeIrp(irp, allocateSize, StackSize);

  初始化一个IRP。

#define IopInitializeIrp( Irp, PacketSize, StackSize ) {          \
    RtlZeroMemory( (Irp), (PacketSize) );                         \
    (Irp)->Type = (CSHORT) IO_TYPE_IRP;                           \
    (Irp)->Size = (USHORT) ((PacketSize));                        \
    (Irp)->StackCount = (CCHAR) ((StackSize));                    \
    (Irp)->CurrentLocation = (CCHAR) ((StackSize) + 1);           \
    (Irp)->ApcEnvironment = KeGetCurrentApcEnvironment();         \
    InitializeListHead (&(Irp)->ThreadListEntry);                 \
    (Irp)->Tail.Overlay.CurrentStackLocation =                    \
        ((PIO_STACK_LOCATION) ((UCHAR *) (Irp) +                  \
            sizeof( IRP ) +                                       \
            ( (StackSize) * sizeof( IO_STACK_LOCATION )))); }

一个IRP初始化是 当前栈要+1,然后指到分配空间的最后,一个IRP初始化之后,在内存中应该是这个样子:

----------------

|              |

|IRP头

|

|

|Tail.Overlay.CurrentStackLocation  

|                                                   |

|

|------------

|

|               

|

|                                                  |

|

|

|

|                                                   |

|

|

----------------  <----------------------|

  2)  PIO_STACK_LOCATION irpSp = IoGetNextIrpStackLocation(Irp);

#define IoGetNextIrpStackLocation( Irp ) (\
    (Irp)->Tail.Overlay.CurrentStackLocation - 1 )

由于刚开始CurrentStackLocation  指向处于分配范围之外的地址,所以此处 -1 得到真正的第一个STACK_LOCATION  

3) IoCallDriver(DeviceObject, Irp);  

将IRP发送到目的驱动

这是IoCallDriver的部分实现

view plaincopy to clipboardprint?
Irp->CurrentLocation--;   

   if (Irp->CurrentLocation <= 0) {   
       KiBugCheck3( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0 );   
   }   

   irpSp = IoGetNextIrpStackLocation( Irp );   
   Irp->Tail.Overlay.CurrentStackLocation = irpSp;   

   //   
   // Save a pointer to the device object for this request so that it can   
   // be used later in completion.   
   //   

   irpSp->DeviceObject = DeviceObject;   


   //   
   // Invoke the driver at its dispatch routine entry point.   
   //   

   driverObject = DeviceObject->DriverObject;   

   //   
   // Prevent the driver from unloading.   
   //   


   status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject,   
                                                             Irp );   
Irp->CurrentLocation--;

    if (Irp->CurrentLocation <= 0) {
        KiBugCheck3( NO_MORE_IRP_STACK_LOCATIONS, (ULONG_PTR) Irp, 0, 0 );
    }

    irpSp = IoGetNextIrpStackLocation( Irp );
    Irp->Tail.Overlay.CurrentStackLocation = irpSp;

    //
    // Save a pointer to the device object for this request so that it can
    // be used later in completion.
    //

    irpSp->DeviceObject = DeviceObject;


    //
    // Invoke the driver at its dispatch routine entry point.
    //

    driverObject = DeviceObject->DriverObject;

    //
    // Prevent the driver from unloading.
    //


    status = driverObject->MajorFunction[irpSp->MajorFunction]( DeviceObject,
                                                              Irp );


可以看到当calldriver时候,IoCallDriver 会将当前栈-1 ,同时将下一个STACK_LOCATION  最为当前栈单元,通过设备对象找到其关联的驱动对象,调用MJ函数,IoCallDriver 返回。



联系我时,请说是在 挂海论坛 上看到的,谢谢!



上一篇:win32k.sys在System进程空间无法访问的原因
下一篇:驱动开发中应该注意的事项
免责声明:
1、本主题所有言论和图片纯属会员个人意见,与本论坛立场无关。一切关于该内容及资源商业行为与www.52ghai.com无关。

2、本站提供的一切资源内容信息仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。

3、本站信息来自第三方用户,非本站自制,版权归原作者享有,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑或手机中彻底删除上述内容。

4、如果您喜欢该程序,请支持正版,购买注册,得到更好的正版服务。如有侵犯你版权的,请邮件与我们联系删除(邮箱:xhzlw@foxmail.com),本站将立即改正。

15

积分

4

主题

4

听众
已帮网友解决0 个问题
好评
0
贡献
11
海币
647
交易币
0
沙发
发表于 2015-4-22 04:07:01 | 只看该作者
看帖回帖,楼主辛苦了!       

17

积分

11

主题

2

听众
已帮网友解决0 个问题
好评
0
贡献
6
海币
1403
交易币
0
板凳
发表于 2015-5-6 14:00:54 | 只看该作者
硬实厉害啊  
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

免责声明|Archiver|手机版|小黑屋|挂海论坛

GMT+8, 2025-4-5 06:12 , Processed in 0.078468 second(s), 33 queries , Gzip On.

Powered by Discuz! X3.2

本站资源来自互联网用户收集发布,如有侵权请邮件与我们联系处理。xhzlw@foxmail.com

快速回复 返回顶部 返回列表