设备IO控制操作 之 直接内存模式IOCTL

在调用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;

}

你可能感兴趣的:(IOC)