当前位置: 代码迷 >> 驱动开发 >> KeRemoveEntryDeviceQueue引发蓝屏的有关问题
  详细解决方案

KeRemoveEntryDeviceQueue引发蓝屏的有关问题

热度:31   发布时间:2016-04-28 10:54:18.0
KeRemoveEntryDeviceQueue引发蓝屏的问题?
蓝屏后用windbg打开dump 发现KeRemoveEntryDeviceQueue引发蓝屏 不知道怎么解决 大家帮忙看看 谢谢
如果在应用程序中不调用CancelIo 则不会引发蓝屏 
这个程序大致情况是这样:应用程序创建2个线程 两个线程函数是一样的 都是readFile 然后read是异步的 read以后就是 CancelIo 然后是等待
驱动程序里边 对IRP进行了队列化 

驱动代码如下:
#pragma LOCKEDCODE
VOID MyStartIo( IN PDEVICE_OBJECT DeviceObject,IN PIRP pFistIrp)
{
KdPrint(("Enter MyStartIo\n"));

KIRQL oldirql;
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
DeviceObject->DeviceExtension;

PKDEVICE_QUEUE_ENTRY device_entry;

//获取cancel自旋锁
IoAcquireCancelSpinLock(&oldirql);

if(pFirstIrp!=pDevExt->pCurrentIRP||pFirstIrp->Cancel)
{
IoReleaseCancelSpinLock(oldirql);
return;
}else
{
IoSetCancelRoutine(pFirstIrp, NULL);
IoReleaseCancelSpinLock(oldirql);
}

PIRP Irp = pFistIrp;
do
{
KEVENT event;
KeInitializeEvent(&event,NotificationEvent,FALSE);

//等3秒
LARGE_INTEGER timeout;
timeout.QuadPart = -3*1000*1000*10;

//定义一个3秒的延时,主要是为了模拟该IRP操作需要大概3秒左右时间
KeWaitForSingleObject(&event,Executive,KernelMode,FALSE,&timeout);

KdPrint(("Complete a irp:%x\n",Irp));
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0; // no bytes xfered
IoCompleteRequest(Irp,IO_NO_INCREMENT);

device_entry=KeRemoveDeviceQueue(&pDevExt->device_queue);
KdPrint(("device_entry:%x\n",device_entry));
if (device_entry==NULL)
{
break;
}

Irp = CONTAINING_RECORD(device_entry, IRP, Tail.Overlay.DeviceQueueEntry);
}while(1);

KdPrint(("Leave MyStartIo\n"));
}

VOID OnCancelIRP(IN PDEVICE_OBJECT DeviceObject,IN PIRP Irp)
{
KdPrint(("Enter CancelReadIRP\n"));
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;

if(pdx->pCurrentIRP == Irp)
{
//释放Cancel自旋锁
IoReleaseCancelSpinLock(Irp->CancelIrql);

//从IRP队列取出下一个IRP 并将它送给startIO
IoStartNextPacket(DeviceObject, TRUE);

KeLowerIrql(Irp->CancelIrql);
}else
{
//把IRP从队列中删除 但是并不影响IRP 本身
KeRemoveEntryDeviceQueue(&pdx->device_queue, &Irp->Tail.Overlay.DeviceQueueEntry);
//释放Cancel自旋锁
IoReleaseCancelSpinLock(Irp->CancelIrql);
}

//设置完成状态为STATUS_CANCELLED
  Irp->IoStatus.Status = STATUS_CANCELLED;
  Irp->IoStatus.Information = 0; // bytes xfered
  IoCompleteRequest( Irp, IO_NO_INCREMENT );

KdPrint(("Leave CancelReadIRP\n"));
}

NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) 
{
KdPrint(("Enter HelloDDKRead\n"));

PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pDevObj->DeviceExtension;

//将IRP设置为挂起
IoMarkIrpPending(pIrp);

IoSetCancelRoutine(pIrp,OnCancelIRP);

KIRQL oldirql;
//提升IRP至DISPATCH_LEVEL
KeRaiseIrql(DISPATCH_LEVEL, &oldirql);

KdPrint(("HelloDDKRead irp :%x\n",pIrp));

KdPrint(("DeviceQueueEntry:%x\n",&pIrp->Tail.Overlay.DeviceQueueEntry));
if (!KeInsertDeviceQueue(&pDevExt->device_queue, &pIrp->Tail.Overlay.DeviceQueueEntry))
MyStartIo(pDevObj,pIrp);

//将IRP降至原来IRQL
KeLowerIrql(oldirql);

KdPrint(("Leave HelloDDKRead\n"));

//返回pending状态
return STATUS_PENDING;
}

#pragma INITCODE
extern "C" NTSTATUS DriverEntry (IN PDRIVER_OBJECT pDriverObject,IN PUNICODE_STRING pRegistryPath) 
{
NTSTATUS status;
//设置卸载函数 设置派遣函数 创建驱动设备对象
return status;
}
#pragma PAGEDCODE
VOID HelloDDKUnload (IN PDRIVER_OBJECT pDriverObject) 
  相关解决方案