使用 RtlCopyMemory 在驱动程序中复制数据

Copying data within drivers with RtlCopyMemory

我有两个 drivers 和 C# 应用程序。有了这个应用程序,我可以从设备写入和读取值。我正在使用第一个 driver 将数据从用户传递到第二个 driver,这是我从第一个调用的。然后我用 RtlCopyMemory 复制数据。问题是这个函数由于 null 参数导致 Access Violation(我将在下面的代码中显示这到底发生在哪里 - 我通过使用 WinDbg 进行调试发现了这一点)。我相信错误在 driver 之一的 DispatchWrite 中。

第一个driver

NTSTATUS DispatchWrite (
        IN PDEVICE_OBJECT   pDevObj,
        IN PIRP             pIrp            ) 
{

    #if DBG==1
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_MASK | 0x77, "\n [ FIRST - DispatchWrite ]\n");
    #endif

    NTSTATUS status = STATUS_SUCCESS;
    PVOID userBuffer;
    ULONG xferSize;

    PIO_STACK_LOCATION pIrpNext;
    PIO_STACK_LOCATION pIrpStack = IoGetNextIrpStackLocation( pIrp );

    IoCopyCurrentIrpStackLocationToNext(pIrp);
    //IoSkipCurrentIrpStackLocation(pIrp);
    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;

    status=IoCallDriver(pDevExt->pTargetDeviceObject, pIrp);


    #if DBG==1
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_MASK | 0x77, "\n [ FIRST - DispatchWrite - End ]\n");
    #endif

    return status;
}

第二个driver

NTSTATUS DispatchWrite (
        IN PDEVICE_OBJECT   pDevObj,
        IN PIRP             pIrp            ) 
{

    #if DBG==1
    DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_MASK | 0x77, "\n [ SECOND - DispatchWrite ]\n");
    #endif

    NTSTATUS status = STATUS_SUCCESS;
    PVOID userBuffer;
    ULONG xferSize;

    PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation( pIrp );

    PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION) pDevObj->DeviceExtension;

    if (pDevExt->deviceBuffer != NULL) 
    {
        ExFreePool(pDevExt->deviceBuffer);
        pDevExt->deviceBuffer = NULL;
        pDevExt->deviceBufferSize = 0;
    }

    xferSize = pIrpStack->Parameters.Write.Length;
    userBuffer = pIrp->AssociatedIrp.SystemBuffer; //this is NULL
    pDevExt->deviceBuffer = ExAllocatePool( PagedPool, xferSize );

    if (pDevExt->deviceBuffer == NULL) 
    {
        status = STATUS_INSUFFICIENT_RESOURCES;
        xferSize = 0;
    } 
    else 
    {
        pDevExt->deviceBufferSize = xferSize;
        RtlCopyMemory( pDevExt->deviceBuffer, userBuffer, xferSize ); //userBuffer is null - access violation
    }

    pIrp->IoStatus.Status = status;
    pIrp->IoStatus.Information = xferSize;
    IoCompleteRequest( pIrp, IO_NO_INCREMENT );

    return status;
}

C# 应用程序

private void button1_Click(object sender, EventArgs e)
        {
            Ster ster = new Ster();
            String devPath = "\\.\";
            devPath += textBox1.Text;
            String userMessage = textBox2.Text;
            ster.driverOpen(devPath);
            ster.driverWrite(userMessage);

        }

斯特尔 class:

public Boolean driverOpen(string deviceName)
        {
            this.DriverHandle = CreateFile(deviceName, GENERIC_WRITE | GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
            if (this.DriverHandle.Equals(IntPtr.Zero))
                return false;
            else
                return true;
        }

unsafe public Boolean driverWrite(string UserMessage)
        {
            uint bW;
            StringBuilder Message = new StringBuilder(UserMessage, 26);

            WriteFile(this.DriverHandle, Message, 26, out bW, 0);
            CloseHandle(this.DriverHandle);
            return true;
        }

IRP 中所述:

AssociatedIrp.SystemBuffer [...]

If the driver is using direct I/O, [...] NULL.

IRP_MJ_WRITE下:

Input Parameters

[...]

The buffer at Irp->AssociatedIrp.SystemBuffer, if the driver uses buffered I/O

The buffer described by the MDL at Irp->MdlAddress, if the [...] driver uses direct I/O

(强调我的。)

IoW,您描述的行为完全符合预期。当驱动程序配置为直接 I/O.

时,SystemBuffer 参数 应该 设置为 NULL

您必须重新配置驱动程序以使用缓冲 I/O,或使用 MDL 访问用户缓冲区。

注意:在这种情况下,我不确定是第一个还是第二个驱动程序的配置控制传递哪个参数。