irp是Windows内核中的一种非常重要的数据结构。上层应用程序与底层驱动程序通信时,应用程序会发出I/O请求,操作系统将相应的I/O请求转换成相应的IRP,不同的IRP会根据类型被分派到不同的派遣例程中进行处理。
irp相当于ring3下的消息,应用程序对驱动程序进行操作的时候会发出相应的消息,驱动程序根据这些消息做出相应的操作。这些操作通过我们自己编写的派遣函数来决定执行什么样的操作。
看下面流程:
1.为不同的irp类型设置派遣函数
2.编写派遣函数来处理收到不懂类型的irp的不同操作
3.创建设备与符号链接
4.在卸载历程中删除设备与符号链接
流程很简单,但是处理起来就不那么简单了。
代码如下:
#include “ntddk.h”
VOID Unload(IN PDRIVER_OBJECT DriverObject)//卸载时删除符号链接
{
UNICODE_STRING symLinkName;
RtlInitUnicodeString(&symLinkName,L”//??//mysymboliclink”);
IoDeleteSymbolicLink(&symLinkName);
IoDeleteDevice(DriverObject->DeviceObject);
KdPrint((”Device Delete Success/n”));
}
NTSTATUS MyMajor(IN PDEVICE_OBJECT Device,IN PIRP irp)
{
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(irp);//动态获取irp的IO堆栈
irp->IoStatus.Status = STATUS_SUCCESS;//填充返回的状态值
irp->IoStatus.Information = 0;
//判断是否为打开驱动的irp,如果是则输出“IRP_MJ_CREATE”
if (stack->MajorFunction==IRP_MJ_CREATE)
{
KdPrint((”IRP_MJ_CREATE/n”));
}
//判断是否为关闭驱动的irp,如果是则输出“IRP_MJ_CLOS”
if (stack->MajorFunction==IRP_MJ_CLOSE)
{
KdPrint((”IRP_MJ_CLOSE/n”));
}
IoCompleteRequest( irp, IO_NO_INCREMENT );//结束掉irp
return irp->IoStatus.Status;//返回
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT mydevice;//定义设备对象
UNICODE_STRING devicename;//定义设备名称
UNICODE_STRING symboliclinkname;//定义符号连接名称
//为不同的irp类型设置派遣函数
DriverObject->MajorFunction[IRP_MJ_CREATE]=MyMajor;//打开
DriverObject->MajorFunction[IRP_MJ_CLOSE]=MyMajor;//关闭
DriverObject->DriverUnload=Unload;
RtlInitUnicodeString(&devicename,L”//Device//mydevice”);//初始化设备名称
RtlInitUnicodeString(&symboliclinkname,L”//??//mysymboliclink”);//初始化符号连接名称
//创建设备
IoCreateDevice(
DriverObject,//驱动对象
0,
&devicename,//设备名称
FILE_DEVICE_UNKNOWN,//类型
0,
FALSE,
&mydevice//设备对象
);
//创建符号链接
IoCreateSymbolicLink(
&symboliclinkname,//符号链接名称
&devicename//设备名称
);
return STATUS_SUCCESS;
}
下面写一个简单的vc程序打开然后关闭驱动,打开的时候会发送给两个消息转换成irp就是IRP_MJ_CREATE和IRP_MJ_CLOSE,然后截获到输出“IRP_MJ_CREATE和IRP_MJ_CLOSE”。