NTSTATUS
PacketCompletion(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
if(Irp->PendingReturned)
{
KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
}
return STATUS_MORE_PROCESSING_REQUIRED;
}
出现的问题是0x000000b8,或者我加了driververifier以后,是0x000000c4,para1是3b,也就是说错误是:
Bug Check 0xB8: ATTEMPTED_SWITCH_FROM_DPC
The ATTEMPTED_SWITCH_FROM_DPC bug check has a value of 0x000000B8. This indicates that an illegal operation was attempted by a delayed procedure call (DPC) routine.
或者
The driver called KeWaitXxx at an IRQL of DISPATCH_LEVEL or higher.
(This is permitted only if the driver already owns the DISPATCHER lock and it passes a timeout value of zero to the routine.)
另外:这种错误是比较随机的,可能运行半个小时都没事,突然就爆发,在虚拟机单核的时候没怎么感觉发生过,但是在真机双核或者虚拟机双核时基本上频繁访问十分钟左右就会蓝屏。请高手们分析一下,给个提示,非常感谢!
Scenario 2: Forward and wait
Use the following code if a driver wants to forward the IRP to a lower driver and wait for it to return so that it can process the IRP. This is frequently done when handling PNP IRPs. For example, when you receive a IRP_MN_START_DEVICE IRP, you must forward the IRP down to the bus driver and wait for it to complete before you can start your device. The Windows XP system has a new function named IoForwardIrpSynchronously that you can use to do this operation easily.
NTSTATUS
DispatchRoutine_2(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
{
KEVENT event;
NTSTATUS status;
//
// You are setting completion routine, so you must copy
// current stack location to the next. You cannot skip a location
// here.
//
IoCopyCurrentIrpStackLocationToNext(Irp);
KeWaitForSingleObject(&event,
Executive, // WaitReason
KernelMode, // must be Kernelmode to prevent the stack getting paged out
FALSE,
NULL // indefinite wait
);
status = Irp->IoStatus.Status;
}
// <---- Do your own work here.
//
// Because you stopped the completion of the IRP in the CompletionRoutine
// by returning STATUS_MORE_PROCESSING_REQUIRED, you must call
// IoCompleteRequest here.
//
IoCompleteRequest (Irp, IO_NO_INCREMENT);
return status;
}
NTSTATUS
CompletionRoutine_2(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
if (Irp->PendingReturned == TRUE) {
//
// You will set the event only if the lower driver has returned
// STATUS_PENDING earlier. This optimization removes the need to
// call KeSetEvent unnecessarily and improves performance because the
// system does not have to acquire an internal lock.
//
KeSetEvent ((PKEVENT) Context, IO_NO_INCREMENT, FALSE);
}
// This is the only status you can return.
return STATUS_MORE_PROCESSING_REQUIRED;
}