IRP和IO_STACK_LOCATION

本文详细解析了操作系统中IRP(I/O Request Packet)及其IRP_STACK_LOCATION数组的工作原理,阐述了驱动程序如何通过这些数据结构进行上下层之间的交互,并介绍了关键函数如IoGetCurrentStackLocation、IoGetNextIrpStackLocation等的使用方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

当一个应用程序调用函数去操作某个设备时,比如调用createFile,deviceIOControl,等等时,I/O管理器为此函数创建一个IRP数据结构对象和一个IRP_STACK_LOCATION数据结构对象数组。

(数组个数等于驱动程序堆栈上驱动的个数)。IRP对象中的数据成员是已经被填充好了的,其中有一个CurrentLocation是当前IRP_STACK_LOCATION堆栈单元的索引,Tail.Overlay.CurrentStackLocation

是当前IRP_STACK_LOCATION单元的指针。

一开始的时候,它当然是指向IRP_STACK_LOCATION数组的第一个元素。

这调用某个驱动程序的分发函数时,IRP作为参数传给了该分发函数,这样,该函数就可以访问IRP中的Tail.Overlay.CurrentStackLocation, 这样就可以访问IRP_STACK_LOCATION的

成员了(当然我们不需要直接这样做,而是调用IoGetCurrentStackLocation来实现)。因为OS并不会为我们初始化IRP_STACK_LOCATION数组中的每一个对象,所以初始化下一层驱动要使用的IRP_STACK_LOCATION就由它的上一层驱动来完成。要初始化它们,首先要找到它们,方法是调用IoGetNextStackLocation(它内部实现只是将CurrentStackLocation++),得到下一个IRP_STACK_LOCATION

对象指针。然后为其赋值。然后调用IOCALLDRIVER().

理解的关键点是:

一 OS为我们生成IRP,IPR_STACK_LOCATION数组,注意,是个数组。IRP中的CurrentStackLocation指向IRP_STACK_LOCATION中的某一个元素。

二 OS 并不会为我们填充好IRP_STACK_LOCATION数组,每一个元素是由上一层驱动负责填充的。

三 IRP_STACK_LOCATION数组,它们的元素之间不需要指针联系。

四 OS只负责把IRP包给最上层的驱动程序,至于如何向下层,就是驱动程序自己的事情了。所以下层对就的那些IRP_STACK_LOCATION,完全由上层驱动函数负责填充,OS不管。

 

驱动程序如何填充一层驱动需要用的IRP_STACK_LOCATION呢?

可以通过调用IoGetNextIrpStackLocation调用得到。其实该函数内部就是返回CurrentStackLocation加1而已。对数组值加1,当然就是得到数组的下一个值了。

这样就可以对它进行赋值了。然后调用IoCallDriver(),IoCallDriver()会将irp包中的CurrentStackLocation值加1,然后调用那个DRIVER.

 

如果下一层的驱动需要的IRP_STACK_LOCATION和本层驱动的一样,则可以直接调用IoSkipCurrentIrpStackLocation或IoCopyCurrentIrpStackLocationToNext.

IoSkipCurrentIrpStackLocation将CurrentStackLocation减1. 正好与IoCallDriver的加1抵消。所以相当于下层驱动和本层驱动用的是同一个IRP_STACK_LOCATIN元素。

/* File Kmd.cpp By WzrterFX */ #include "Kmd.h" namespace Kmd { NTSTATUS Kmd::Create(PDRIVER_OBJECT driverObject) { NTSTATUS status = STATUS_UNSUCCESSFUL; UNICODE_STRING deviceName { }; RtlInitUnicodeString(&deviceName, L"\\Device\\Kmd"); status = IoCreateDevice( driverObject, NULL, &deviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &_deviceObject ); if (!NT_SUCCESS(status)) { DbgPrintEx(0, 0, "Fatal, failed to create driver device.\n" ); return status; } UNICODE_STRING symbolicLink { }; RtlInitUnicodeString(&symbolicLink, L"\\DosDevices\\Kmd"); status = IoCreateSymbolicLink(&symbolicLink, &deviceName); if (!NT_SUCCESS(status)) { DbgPrintEx(0, 0, "Fatal, failed to establish driver link.\n" ); IoDeleteDevice(_deviceObject); return status; } SetFlag(_deviceObject->Flags, DO_BUFFERED_IO); driverObject->MajorFunction[IRP_MJ_CREATE] = [](PDEVICE_OBJECT, PIRP io) -> NTSTATUS { IoCompleteRequest(io, IO_NO_INCREMENT); return io->IoStatus.Status; }; driverObject->MajorFunction[IRP_MJ_CLOSE] = [](PDEVICE_OBJECT, PIRP io) -> NTSTATUS { IoCompleteRequest(io, IO_NO_INCREMENT); return io->IoStatus.Status; }; driverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = &this->KmdControl; ClearFlag(_deviceObject->Flags, DO_DEVICE_INITIALIZING); return STATUS_SUCCESS; } NTSTATUS Kmd::KmdControl(PDEVICE_OBJECT, PIRP io) { NTSTATUS status = STATUS_UNSUCCESSFUL; PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(io); if (!stack) { IoCompleteRequest(io, IO_NO_INCREMENT); DbgPrintEx(0, 0, "Fatal, missing driver stack location.\n" ); return status; } PKmdRequest request = reinterpret_cast<PKmdRequest>(io->AssociatedIrp.SystemBuffer); if (!request) { IoCompleteRequest(io, IO_NO_INCREMENT); DbgPrintEx(0, 0, "Fatal, missing driver associated request.\n" ); return status; } static PEPROCESS process { }; static SIZE_T reserved { }; switch (stack->Parameters.DeviceIoControl.IoControlCode) { case ::Kmd::_IoCtls::attach: { status = ::Kmd::_NtifsApi::PsLookupProcessByProcessId( request->attachRequest.process, &process ); break; } case ::Kmd::_IoCtls::read: { if (process) { status = ::Kmd::_NtifsApi::MmCopyVirtualMemory( process, request->copyMemoryRequest.from, PsGetCurrentProcess(), request->copyMemoryRequest.to, request->copyMemoryRequest.requested, MODE::KernelMode, &reserved ); } break; } case ::Kmd::_IoCtls::write: { if (process) { status = ::Kmd::_NtifsApi::MmCopyVirtualMemory( PsGetCurrentProcess(), request->copyMemoryRequest.to, process, request->copyMemoryRequest.from, request->copyMemoryRequest.requested, MODE::KernelMode, &reserved ); } break; } default: { status = STATUS_INVALID_DEVICE_REQUEST; break; } } io->IoStatus.Status = status; io->IoStatus.Information = sizeof(KmdRequest); IoCompleteRequest(io, IO_NO_INCREMENT); return status; } }帮我全部加上注释
最新发布
03-22
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值