IoCompleteRequest routine

本文详细介绍了IoCompleteRequest例程在Windows驱动程序中的使用方法及注意事项,包括参数解释、返回值、相关要求和DDI合规性规则等关键信息。

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

IoCompleteRequest routine

调用 IoCompleteRequest 例程表示调用者已经处理完一个给定的I/O请求,并将指定的IRP返回给I/O manager.

Syntax

 

VOID IoCompleteRequest(
  _In_ PIRP  Irp,
  _In_ CCHAR PriorityBoost
);

 

Parameters

Irp [in]

指向将完成的IRP

PriorityBoost [in]

指定一个系统定义的常量,此常量用以提升请求该操作的线程的运行时优先级。若线程请求的操作是一个可以迅速完成的操作(so the requesting thread is not compensated for its assumed wait for I/O to be completed) ,或者是IRP以一个错误结束,这个值设置为IO_NO_INCREMENT 否则这个PriorityBoost常量是设备类型相关的值,关于这些常量见Ntddk.h or Wdm.h

Return value

None

Remarks

当驱动程序完成了对一个给定IRP的所有处理过程时调用IoCompleteRequestI/O manager检查确认是否有一个更高层级的驱动程序在这个IRP设置了IoCompletion 例程,如果则依次调用每一个IoCompletion ,直到所有层上的驱动程序都完成了IRP

When all drivers have completed a given IRP, the I/O manager returns status to the original requester of the operation. Note that a higher-level driver that sets up a driver-created IRP must supply an IoCompletion routine to release the IRP it created.

Never call IoCompleteRequest while holding a spin lock. Attempting to complete an IRP while holding a spin lock can cause deadlocks.当所有的驱动程序都完成了给定的IRPI/O manager返回状态值给最初的操作请求者。注意一个创建了一个“驱动创建”的IRP的高层级的驱动程序必须提供一个IoCompletion 以释放它创建的IRP。请勿在获得一个 spin lock时调用IoCompleteRequest 。在获得一个spin lock 时试图完成一个IRP将可能导致死锁。

Requirements

Target platform

Universal

Version

Available starting with Windows 2000.

Header

Wdm.h (include Wdm.h, Ntddk.h, or Ntifs.h)

Library

NtosKrnl.lib

DLL

NtosKrnl.exe

IRQL

<= DISPATCH_LEVEL

DDI compliance rules

CompleteRequestCompleteRequestStatusCheckDoubleCompletionIoAllocateCompleteIoBuildFsdComplete,IoSetCompletionExCompleteIrpIrpProcessingCompleteMarkIrpPendingPendedCompletedRequest,PendedCompletedRequest2PendedCompletedRequest3PendedCompletedRequestExPnpIrpCompletionSpinLockSafe,WmiCompleteHwStorPortProhibitedDDIsSpinLockSafe(storport)

See also

IoSetCompletionRoutine

 

/* 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
<think>好的,我现在需要帮用户给提供的C++内核模式驱动代码添加注释。首先,我要仔细阅读并理解这段代码的结构和功能。代码位于Kmd.cpp文件中,属于Kmd命名空间,包含Kmd类的Create和KmdControl两个方法。 首先看Create方法。这个方法的作用应该是初始化驱动程序,创建设备对象和符号链接。用户可能不太熟悉Windows内核驱动的结构,所以我需要解释每个关键函数的作用,比如IoCreateDevice、IoCreateSymbolicLink,以及设置DO_BUFFERED_IO标志的意义。还要注意Lambda表达式处理IRP_MJ_CREATE和IRP_MJ_CLOSE的情况,以及将IRP_MJ_DEVICE_CONTROL指向KmdControl方法。 接下来是KmdControl方法,处理设备控制请求。这里需要解释IO控制码的分发,比如attach、read、write操作。特别是PsLookupProcessByProcessId和MmCopyVirtualMemory这些内核API的作用,以及它们如何实现进程内存的读写。同时,需要注意静态变量process和reserved的作用,可能用于跨请求保持进程状态。 用户可能希望注释详细但不过于冗长,所以每个关键步骤和函数调用都需要简明扼要的解释。还需要注意代码中的错误处理部分,比如NTSTATUS状态检查,设备对象删除等,说明为什么这些步骤是必要的。 另外,要确保注释符合代码规范,使用中文,并且遵循用户提供的系统级指令,比如数学表达式的格式,但这段代码中没有数学内容,所以可能不需要。注释需要结构清晰,分块解释,帮助用户逐步理解代码的功能和实现细节。 最后,检查是否有遗漏的部分,比如命名空间、头文件包含、宏定义等,确保注释覆盖所有重要部分,帮助用户全面理解这段内核驱动代码的工作原理。</think>以下是为代码添加的中文注释,按照功能模块分块解释: ```cpp /* 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; } // 设置设备标志(使用缓冲I/O) SetFlag(_deviceObject->Flags, DO_BUFFERED_IO); // 设置IRP处理函数(使用Lambda表达式) 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; // 获取当前IRP栈 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, // 目标进程ID &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; } } ``` 代码功能总结: 1. **驱动初始化**:创建`\Device\Kmd`设备对象和`\DosDevices\Kmd`符号链接,设置缓冲I/O模式 2. **IRP处理**: - 基础请求:直接完成`CREATE`/`CLOSE`请求 - 设备控制:通过`KmdControl`处理核心逻辑 3. **内存操作**: - `attach`:通过进程ID获取进程对象 - `read`:从目标进程读取内存到当前进程 - `write`:从当前进程写入内存到目标进程 4. **安全机制**: - 使用`MmCopyVirtualMemory`进行安全内存拷贝 - 内核模式访问验证 - 严格的参数有效性检查
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值