这节课先来讲一下IRP是什么?
1、从概念上讲IRP类似于windows应用程序的消息。我们知道在windows中应用程序是由消息驱动的。IRP的全名是I/O Request Package,即输入输出请求包,它是Windows内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求,操作系统将相应的I/O请求转换成相应的IRP,不同的IRP会根据类型被分派到不同的派遣例程中进行处理。
2、与IRP相关的几个常用的事件
驱动层 功能解释 对应于应用层
IRP_MJ_CREATE 请求一个句柄 CreateFile
IRP_MJ_CLOSE 关闭句柄 CloseHandle
IRP_MJ_READ 从设备得到数据 ReadFile
IRP_MJ_WRITE 传送数据到设备 WriteFile
IRP_MJ_DEVICE_CONTROL 控制操作利用IOCTL宏 DeviceIoContro
3、这几个IRP事件放在MajorFunction里,MajorFuncton是驱动的一个数组形式的成员。
driver->MajorFunction[IRP_MJ_CREATE]=DeviceIrpCtl;//CreateFile
driver->MajorFunction[IRP_MJ_CLOSE]=DeviceIrpCtl;//卸载驱动 CloseHandle
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL]=DeviceIrpCtl;//DeviceIoControl
具体代码如下:
#include <ntifs.h>
NTSTATUS IRP_CALL(PDEVICE_OBJECT device, PIRP pirp)
{
device;
pirp;
KdPrint(("zdsoft:进入派遣函数"));
PIO_STACK_LOCATION irpStackL;
irpStackL = IoGetCurrentIrpStackLocation(pirp);//获取应用层传来的参数
switch (irpStackL->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL://DeviceIoControl
{
KdPrint(("zdsoft:用户层调用了DeviceIoControl"));
break;
}
case IRP_MJ_CREATE://CreateFile
{
KdPrint(("zdsoft:用户层调用了CreateFile"));
break;
}
case IRP_MJ_CLOSE://CloseHandle
{
KdPrint(("zdsoft:用户层调用了CloseHandle"));
break;
}
}
pirp->IoStatus.Status = STATUS_SUCCESS;
pirp->IoStatus.Information = 4;//返回给DeviceIoControl中的倒数第二个参数lpBytesReturned
IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作,并且不增加优先级
KdPrint(("zdsoft:离开派遣函数"));
return STATUS_SUCCESS;//返回0,表示成功
}
//卸载驱动时被调用
void DriverUnload(PDRIVER_OBJECT DriverObject)
{
KdPrint(("zdsoft:进入卸载例程DriverObject=%p 行号=%d", DriverObject, __LINE__));
}
//加载驱动时被调用
NTSTATUS
DriverEntry(
_In_ PDRIVER_OBJECT DriverObject,
_In_ PUNICODE_STRING RegistryPath
)
{
DriverObject->DriverUnload = DriverUnload;//注册卸载例程-回调函数
DriverObject->MajorFunction[IRP_MJ_CREATE] = IRP_CALL;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = IRP_CALL;
KdPrint(("zdsoft:进入DriverEntry入口点 DriverObject=%p 行号=%d\n", DriverObject, __LINE__));//Debug
//KdPrint(("zdsoft:RegistryPath=%s\n, RegistryPath->Buffer"));//多字节字符集
KdPrint(("zdsoft:RegistryPath=%ws\n", RegistryPath->Buffer));//Unicode 宽字符
return 0;//返回成功
}
接着编译生成,把生成好的驱动文件放到虚拟机里,如下图:
我们发现无论是加载或是卸载都没有触发IRP事件,这是因为在用户层(也就是R3环 )没有调用CreateFile打开设备也没有绑定符号。这个放在后面讲,今天只讲如何注册IRP。
好了,今天的这节课就到这里,希望看到此文章的朋友给个关注,谢谢!有不懂的可以留言,一般24小时内回复。