在调用DeviceIoControl时,应用层的输入缓冲区的内容被复制到IRP中的Irp->AssociatedIrp.SystemBuffer内存地址中。这个步骤和缓冲区模式IOCTL处理一样。
但是,对于DeviceIoControl指定的输出缓冲区的处理,操作系统将该缓冲区锁定,然后在内核模式地址空间中重新映射一段地址。
在驱动程序中,METHOD_IN_DIRECT 和 METHOD_OUT_DIRECT模式都以相同方式处理,仅有的不同是它们访问用户模式缓冲区所需要的访问权限:
METHOD_IN_DIRECT: 需要读权限
METHOD_OUT_DIRECT:需要读和写权限。
使用这两种模式,IO管理器会为输入数据提供一个内核模式拷贝缓冲区,该缓冲区地址存放在Irp->AssociatedIrp.SystemBuffer中,将应用层传递的数据拷贝到该内核缓冲区中。但是为输出数据缓冲区创建一个MDL。我们可以使用MmGetSystemAddressForMdlSafe来获得该应用层虚拟缓冲区所对应的内核地址。从而对其进行访问。
例子:
NTSTATUS DeviceIoControl(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION IrpSp;
ULONG InputLength;
PVOID InputBuffer;
ULONG OutputLength;
PVOID OutputBuffer;
// 获得当前堆栈位置
IrpSp = IoGetCurrentIrpStackLocation(Irp);
// 得到输入缓冲区的大小
InputLength = IrpSp->Parameters.DeviceIoControl.InputBufferLength;
// 得到输入缓冲区的地址
InputBuffer = Irp->AssociatedIrp.SystemBuffer;
// 得到输出缓冲区的大小
OutputLength = IrpSp->Parameters.DeviceIoControl.OutputBufferLength;
// 得到输出缓冲区在内核层的映射地址
OutputBuffer = MmGetSystemAddressForMdlSafe(Irp->MdlAddress);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp,IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具