关于使用IoBuildAsynchronousFsdRequest创建读写IRP出现蓝屏(蓝屏错误码:0x000000BE)的问题

        最近学习使用IoBuildAsynchronousFsdRequest创建读写IRP进行驱动间通讯的方式,在使用IoBuildAsynchronousFsdRequest成功创建读IRP后进行安装,安装时出现蓝屏,蓝屏提示错误0x000000BE:Write Read-Only Memory。
        进过研究分析,发现 IoBuildAsynchronousFsdRequest创建读IRP时我传入的输入缓冲区为局部变量缓冲区地址,而在IRP的完成例程中使用了此地址,局部变量的有效性只限于当前函数,所以非法使用导致出现蓝屏。所以在使用 IoBuildAsynchronousFsdRequest创建读写IRP时,如果在其它函数中需要使用到输入输出缓冲区时,应该传入全局的缓冲区地址。
        下面是一个例子:

char g_szbuffer[4096] = "";
//用来处理等待请求
void CompleteWait(WDFQUEUE Queue)
{
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK IoStatus;
WDFREQUEST WaitRequest = NULL;
int nRes = 1;
HANDLE            hReadEvent;
PKEVENT           pEvent;
PDEVICE_CONTEXT   pDeviceContext;
PIRP irp;
        //char szBuf[4096] = "";
LARGE_INTEGER StartingOffset = { 0 };
PDEVICE_OBJECT    pUsbDeviceObject = NULL;
PDRIVER_OBJECT    pParentDriverObject = NULL;
PIRP pNewIrp;
KEVENT event;
PIO_STACK_LOCATION stack;
IO_STATUS_BLOCK status_block;
// 将32位整数转为64位的整数
LARGE_INTEGER offsert = RtlConvertLongToLargeInteger(0);
UNICODE_STRING DeviceName;

PDEVICE_OBJECT DeviceObject = NULL;
PFILE_OBJECT FileObject = NULL;

PAGED_CODE();

RtlInitUnicodeString( &DeviceName, L"\\DosDevices\\ScannerUSBDriver03" );

DbgPrint("begin CompleteWait\n");

// 初始化一个同步对象
KeInitializeEvent(&event,NotificationEvent,FALSE);

pDeviceContext = GetDeviceContext(WdfIoQueueGetDevice(Queue));

if(pDeviceContext->bOpen)
DbgPrint("pDeviceContext->bOpen is true\n");
else
DbgPrint("pDeviceContext->bOpen is false\n");

pUsbDeviceObject = pDeviceContext->pPdoDeviceObject->NextDevice;

if (pUsbDeviceObject && pDeviceContext->bOpen)
{
                        KdPrint(("pUsbDeviceObject:%x\n",pUsbDeviceObject));

//创建ReadIRP
irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ, pUsbDeviceObject, g_szbuffer,sizeof(g_szbuffer), &StartingOffset, NULL); //此处只能用全局的缓冲区(g_szbuffer),不能使用此函数里的局部缓冲区(szBuf),否则蓝屏
if (irp != NULL)
{
DbgPrint("IoBuildAsynchronousFsdRequest success\n");

status = IoAcquireRemoveLock(&pDeviceContext->RemoveLock, irp);
if (NT_SUCCESS(status))
{
IoSetCompletionRoutineEx(pUsbDeviceObject, irp,
AsynReadCompletion,
pDeviceContext,
TRUE,
TRUE,
TRUE);


status = IoCallDriver(pUsbDeviceObject, irp);
if (!NT_SUCCESS(status))
{
DbgPrint("Failed to send async Read irp (status=%x)\n", status);

}
else
{
IoFreeIrp(irp);
DbgPrint("IoAcquireRemoveLock failed\n");
}
}
else
{
DbgPrint("IoBuildAsynchronousFsdRequest failed\n");

}
}

NTSTATUS
AsynReadCompletion(
__in PDEVICE_OBJECT  DeviceObject,
__in PIRP  Irp,
__in PVOID  Context
)
{
NTSTATUS status = Irp->IoStatus.Status;
WDFREQUEST WaitRequest = NULL;
int nRes = 1;

PDEVICE_CONTEXT pDevExt = (PDEVICE_CONTEXT)Context;

UNREFERENCED_PARAMETER(DeviceObject);

DbgPrint((PCHAR)(Irp->AssociatedIrp.SystemBuffer));
DbgPrint(g_szbuffer);


  if (status == STATUS_CANCELLED)
{
DbgPrint("AsynRead IRP was cancelled\n");
}
else if (!NT_SUCCESS(status)) 
{
DbgPrint("AsynRead IRP failed (status=%x)\n", status);
}
else  //Read成功
{
DbgPrint("begin Write ringbuffer\n"); 

//结束等待请求
if ((pDevExt->wdfQueue) && (nRes >= 0))
{
//取出自定义队列中的WAIT请求
status = WdfIoQueueRetrieveNextRequest(pDevExt->wdfQueue, &WaitRequest);
if (NT_SUCCESS(status))
{
if (WaitRequest)
{
//结束等待
WdfRequestComplete(WaitRequest, STATUS_SUCCESS);
DbgPrint("Complete Wait Mask succeed\n");
WaitRequest = NULL;

}
else
DbgPrint("WaitRequest is null\n");
}
}  

if (NULL != pDevExt)
IoReleaseRemoveLock(&pDevExt->RemoveLock, Irp);
 
//IoFreeIrp(Irp);

return status;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值