首页
社区
课程
招聘
[原创]过滤驱动中创建IRP时IO堆栈单元的细节处理
发表于: 2008-2-26 21:29 12101

[原创]过滤驱动中创建IRP时IO堆栈单元的细节处理

2008-2-26 21:29
12101

过滤驱动中创建IRP时IO堆栈单元的细节处理

作者:猪头三
网站:http://www.x86asm.com

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

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);
}


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (11)
雪    币: 321
活跃值: (271)
能力值: ( LV13,RANK:1050 )
在线值:
发帖
回帖
粉丝
2
嗯,不错,这是一种办法。还有一种办法是直接利用上层的堆栈单元。
2008-2-26 23:08
0
雪    币: 223
活跃值: (10)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
3
学习ing...
不错....
2008-2-27 19:25
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
不错!好好学习!
2008-2-29 14:48
0
雪    币: 248
活跃值: (42)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
好文,顶起来...
2008-3-1 13:11
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
学习中。。。。。能有这水平真不错了
2008-4-2 07:49
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
猪头三,那个RING3下穿影子的程序的作者?拜见了
2008-4-2 21:53
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dem
8
请问阁下是原来华夏那位猪头三吗,就是写名噪一时dirshell的作者吗
2008-4-10 19:06
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
久仰大名,我用您的RING3穿还原高调了自己的机子
2008-5-14 18:39
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
穿透影子的代码我过段时间发上来 呵呵
2008-5-23 12:32
0
雪    币: 212
活跃值: (13)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
请问楼主,IoCalldriver是同步还是异步的,象你这样想象的话肯定的同步的哦
我有一点不明白,请大家指教:
  对于分层驱动程序,最高层执行时的上下文就是调用该例程的应用程序,但是到了底层驱动,上下文肯定不是当前进程的,而是任意的,所以对于IoCallDriver如果一直是同步调用,那么到了底层,驱动的上下文就没改变,仍然是最初进程的上下文。
请大侠指教!
2008-8-28 16:46
0
雪    币: 236
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
收藏
。。。。。。。。。。。。
2008-10-9 17:39
0
游客
登录 | 注册 方可回帖
返回
//