IO Stack Location

本文详细介绍了IRP(I/O请求包)及其在驱动程序中的作用方式,特别是IO堆栈区的构建和使用。文章解释了IO管理器如何为每个驱动分配IO堆栈区,以及这些堆栈如何用于传递IO请求信息。此外,还探讨了不同类型的主功能代号和辅功能代号,以及它们在处理IO请求中的角色。
为了驱动的构建,在IRP建立时,IO管理器给每个驱动分配一个IO堆栈区,每个IO堆栈区由 IO_STACK_LOCATION 结构组成。
    IO管理器为每个IRP建立了一个IO堆栈序列,这个序列中每个IO堆栈可以给驱动使用。每个驱动拥有这个序列中的一个堆栈结构,并且
可以通过IoGetCurrentIrpStackLocation函数取得这个IO操作的详细信息。
    驱动程序可以通过调用IoGetNextIrpStackLocation函数来设置下一个IO堆栈,此时序列前面的IO堆栈也能被某些操作使用。所以我们
应该使用IoCompletion来完成最终的清除任理。
    这个“在每层驱动中处理IRP”的模型告诉我们最初的IRP包含了两个IO堆栈也就是两个驱动。一个是文件系统驱动、另一个是块存储设
备,已分配IRP的驱动在这个模型中并不拥有FSD堆栈,高层驱动为低层驱动分配IRP并决定低层驱动可以使用多少堆栈多少IRP,低层设备对
象可以根据StackSize的值得知。
    
    这个模型的IO堆栈通常还需要包含下面一些信息。
    ·主功能代号(IRP_MJ_XXX),标志着这个驱动程序的基本功能。
    ·辅功能代号(IRP_MN_XXX),高层SCSI驱动和所有的即插即用设备驱动中使用它们表示处理这些操作的子情况。
    ·设置操作细节的参数,例如 一个缓冲区的起始点和长度、向哪里输出或从哪里输入。
    ·一个已创建设备的指针,表示操作的目标(物理设备、逻辑设备或虚拟设备)。
    ·一个文件对象的指针,表示一个打开的文件、设备、目录或被看作文件的IO堆栈。驱动程序通常会忽略它。
    IRP使用的主功能代号和辅功能代号受驱动程序细节限制,不过低层驱动和中间层驱动(包含即插即用设备和过滤驱动)通常实现下面这
些基本功能:
    IRP_MJ_CREATE    打开一个设备对象,标志着引用并使用IO操作。
    IRP_MJ_READ    从设备中读取数据。
    IRP_MJ_WRITE    向设备中写入数据。
    IRP_MJ_DEVICE_CONTROL    建立(或重置)设备,依据系统依赖性和这类设备具体IO控制代号(IOCTL)。
    IRP_MJ_CLOSE    关闭这个设备对象。
    IRP_MJ_PNP    完成“插入并使用”操作。这个请求由即插即用设备管理器通过IO管理器发出。
    IRP_MJ_POWER    完成设备的电源操作。这个请求由电源管理器通过IO管理器发出。
    关于更多IRP主功能代号的信息请查阅“IRP Major Function Codes”。
    
    一般IO管理器发送的IRP至少带着两个堆栈。文件系统层是在驱动层之后,所以驱动层需要块存储设备来组织存储。IO管理器发送IRP到
最底层的驱动。
    无论如何,IO管理器都应该支持向驱动链中添加一个驱动程序。例如,一个镜像驱动器是己有硬盘分驱一部分数据的备份,就像一个文
件系统和底层驱动之间的上面所说的IRP模型。当新驱动把它自己添加到驱动堆栈时,IO管理器调整所有IRP的IO堆栈的数目然后通知文件系
统、镜像、和底层驱动。文件系统的每个IRP请求处理链中将包含这个IO堆栈就像添加一个新镜像。
    需要注意的是,这个添加驱动到现有驱动链的设计使应用到某些设备上将会受到一些约束。
    ·一个高层驱动在某些IRP情况下可以安全访问它自己拥有的低层IO堆栈。这样的驱动必须安装这个IO堆栈给给这IRP链上的下一层驱动
,无论如何在设计这样的高层驱动,你不能预料到新驱动是不是会或者什么时候安装驱动链下面的位置中。
    所以,你应该假设以后添加的驱动将会处理相同的IRP主功能代号(IRP_MJ_XXX)取代你所要处理的硬件设备。
    ·在某些IRP情况下低层驱动可以安全访问它自己拥有的IO堆栈。当设计驱动时,你不能预知是否或何时新驱动安装在更高层,。
    在设计低层驱动时,应假设新驱动能够使用你的驱动的IO堆栈中的信息继续处理,而无论新驱动的来源或是有多少层。
/* 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
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值