【驱动之二】IO_STACK_LOCATION总结

IO_STACK_LOCATION是I/O堆栈中的一个条目,与每个IRP相关联。文章详细介绍了MajorFunction、MinorFunction、Parameters、DeviceObject、FileObject、CompletionRoutine和Context等成员,以及其在驱动程序中的作用和设置规则。每个IRP为驱动程序栈中的每个驱动程序提供一个IO_STACK_LOCATION结构。

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

IO_STACK_LOCATION

I/O堆栈 

   任何内核模式程序在创建一个IRP时,同时还创建了一个与之关联的 IO_STACK_LOCATION 结构数组:数组中的每个堆栈单元都对应一个将处理该IRP的驱动程序,另外还有一个堆栈单元供IRP的创建者使用。堆栈单元中包含该IRP的类型代码和参数信息以及完成函数的地址。图显示了堆栈单元的结构。 
图 — 驱动程序和I/O堆栈之间的平行关系

 

I/O堆栈单元数据结构:

图 — I/O堆栈单元数据结构

 

下面就这几个数据结构进行详细说明,完整的数据结构代码见下面的英文,从微软官方拿过来的,不做翻译了,顺便还可以学下英语:    

      MajorFunction(UCHAR)是该IRP的主功能码。这个代码应该为类似 IRP_MJ_READ一样的值,并与驱动程序对象中MajorFunction表的某个派遣函数指针相对应。如果该代码存在于某个特殊驱动程序的I/O堆栈单元中,它有可能一开始是,例如IRP_MJ_READ,而后被驱动程序转换成其它代码,并沿着驱动程序堆栈发送到低层驱动程序。我将在第十一章(USB总线)中举一个这样的例子,USB驱动程序把标准的读或写请求转换成内部控制操作,以便向USB总线驱动程序提交请求。 
  MinorFunction(UCHAR)是该IRP的副功能码。它进一步指出该IRP属于哪个主功能类。例如,IRP_MJ_PNP请求就有约一打的副功能码,如IRP_MN_START_DEVICE、IRP_MN_REMOVE_DEVICE,等等。 
  Parameters(union)是几个子结构的联合,每个请求类型都有自己专用的参数,而每个子结构就是一种参数。这些子结构包括Create(IRP_MJ_CREATE请求)、Read(IRP_MJ_READ请求)、StartDevice(IRP_MJ_PNP的IRP_MN_START_DEVICE子类型),等等。 
  DeviceObject(PDEVICE_OBJECT)是与该堆栈单元对应的设备对象的地址。该域由IoCallDriver函数负责填写。 
  FileObject(PFILE_OBJECT)是内核文件对象的地址,IRP的目标就是这个文件对象。驱动程序通常在处理清除请求(IRP_MJ_CLEANUP)时使用FileObject指针,以区分队列中与该文件对象无关的IRP。 
  CompletionRoutine(PIO_COMPLETION_ROUTINE)是一个I/O完成例程的地址,该地址是由与这个堆栈单元对应的驱动程序的更上一层驱动程序设置的。你绝对不要直接设置这个域,应该调用IoSetCompletionRoutine函数,该函数知道如何参考下一层驱动程序的堆栈单元。设备堆栈的最低一级驱动程序并不需要完成例程,因为它们必须直接完成请求。然而,请求的发起者有时确实需要一个完成例程,但通常没有自己的堆栈单元。这就是为什么每一级驱动程序都使用下一级驱动程序的堆栈单元保存自己完成例程指针的原因。 
  Context(PVOID)是一个任意的与上下文相关的值,将作为参数传递给完成例程。你绝对不要直接设置该域;它由IoSetCompletionRoutine函数自动设置,其值来自该函数的某个参数。


The IO_STACK_LOCATION structure defines an I/O stack location, which is an entry in the I/O stack that is associated with each IRP. Each I/O stack location in an IRP has some common members and some request-type-specific members.

typedef struct _IO_STACK_LOCATION {
  UCHAR  MajorFunction;
  UCHAR  MinorFunction;
  UCHAR  Flags;
  UCHAR  Control;
  union {
        //
        // Parameters for IRP_MJ_CREATE 
        //
        struct {
            PIO_SECURITY_CONTEXT  SecurityContext;
            ULONG  Options;
            USHORT POINTER_ALIGNMENT  FileAttributes;
            USHORT  ShareAccess;
            ULONG POINTER_ALIGNMENT  EaLength;
        } Create;
        //
        // Parameters for IRP_MJ_READ 
        //
        struct {
            ULONG  Length;
            ULONG POINTER_ALIGNMENT  Key;
            LARGE_INTEGER  ByteOffset;
        } Read;
        //
        // Parameters for IRP_MJ_WRITE 
        //
        struct {
            ULONG  Length;
            ULONG POINTER_ALIGNMENT  Key;
            LARGE_INTEGER  ByteOffset;
        } Write;
        //
        // Parameters for IRP_MJ_QUERY_INFORMATION 
        //
        struct {
            ULONG  Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT  FileInformationClass;
        } QueryFile;
        //
        // Parameters for IRP_MJ_SET_INFORMATION 
        //
        struct {
            ULONG  Length;
            FILE_INFORMATION_CLASS POINTER_ALIGNMENT  FileInformationClass;
            PFILE_OBJECT  FileObject;
            union {
                struct {
                    BOOLEAN  ReplaceIfExists;
                    BOOLEAN  AdvanceOnly;
                };
                ULONG  ClusterCount;
                HANDLE  DeleteHandle;
            };
        } SetFile;
        //
        // Parameters for IRP_MJ_QUERY_VOLUME_INFORMATION 
        //
        struct {
            ULONG  Length;
            FS_INFORMATION_CLASS POINTER_ALIGNMENT  FsInformationClass;
        } QueryVolume;
        //
        // Parameters for IRP_MJ_DEVICE_CONTROL and IRP_MJ_INTERNAL_DEVICE_CONTROL 
        //
        struct {
            ULONG  OutputBufferLength;
            ULONG POINTER_ALIGNMENT  InputBufferLength;
            ULONG POINTER_ALIGNMENT  IoControlCode;
            PVOID  Type3InputBuffer;
        } DeviceIoControl;
        //
        // Nonsystem service parameters.
        //
        // Parameters for IRP_MN_MOUNT_VOLUME 
        //
        struct {
            PVOID  DoNotUse1;
            PDEVICE_OBJECT  DeviceObject;
        } MountVolume;
        //
        // Parameters for IRP_MN_VERIFY_VOLUME 
        //
        struct {
            PVOID  DoNotUse1;
            PDEVICE_OBJECT  DeviceObject;
        } VerifyVolume;
        //
        // Parameters for Scsi using IRP_MJ_INTERNAL_DEVICE_CONTROL 
        //
        struct {
            struct _SCSI_REQUEST_BLOCK  *Srb;
        } Scsi;
        //
        // Parameters for IRP_MN_QUERY_DEVICE_RELATIONS 
        //
        struct {
            DEVICE_RELATION_TYPE  Type;
        } QueryDeviceRelations;
        //
        // Parameters for IRP_MN_QUERY_INTERFACE 
        //
        struct {
            CONST GUID  *InterfaceType;
            USHORT  Size;
            USHORT  Version;
            PINTERFACE  Interface;
            PVOID  InterfaceSpecificData;
        } QueryInterface;
        //
        // Parameters for IRP_MN_QUERY_CAPABILITIES 
        //
        struct {
            PDEVICE_CAPABILITIES  Capabilities;
        } DeviceCapabilities;
        //
        // Parameters for IRP_MN_FILTER_RESOU
/* 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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值