使用 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 访问用户缓冲区。
注意:在这种情况下,我不确定是第一个还是第二个驱动程序的配置控制传递哪个参数。
我有两个 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 访问用户缓冲区。
注意:在这种情况下,我不确定是第一个还是第二个驱动程序的配置控制传递哪个参数。