返回STATUS_MORE_PROCESSING_REQUIRED的2种形式

一种是自己申请IRP

第二种是自身是过滤驱动(IRP是上层组件下发的,所以IRP不能只在我们驱动的函数这里(像第一种情况那样就释放)就消失了

 

第一种:

NTSTATUS
IoCompletionRoutine(
      IN PDEVICE_OBJECT DeviceObject,
      IN PIRP Irp,
      IN PVOID Context)
{
*Irp->UserIosb = Irp->IoStatus;
if (Irp->UserEvent)
   KeSetEvent(Irp->UserEvent, IO_NO_INCREMENT, 0);
if (Irp->MdlAddress)
{
   IoFreeMdl(Irp->MdlAddress);
   Irp->MdlAddress = NULL;
}
IoFreeIrp(Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}

 xxfun()

{

allocate irp()

IoSetCompletionRoutine(Irp, IoCompletionRoutine, 0, TRUE, TRUE, TRUE);

iocalldriver()

if pending 

   waitfor pending

done!

}

===================

 

第二种

NTSTATUS
DispatchRoutine_2(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
    )
{
    KEVENT   event;
    NTSTATUS status;

    KeInitializeEvent(&event, NotificationEvent, FALSE);

    // 
    // You are setting completion routine, so you must copy
    // current stack location to the next. You cannot skip a location
    // here.
    // 
    IoCopyCurrentIrpStackLocationToNext(Irp);

    IoSetCompletionRoutine(Irp,
                           CompletionRoutine_2,
                           &event,
                           TRUE,
                           TRUE,
                           TRUE
                           );

    status = IoCallDriver(TopOfDeviceStack, Irp);

    if (status == STATUS_PENDING) {
        
       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);//注意要在这里complete
    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);

 

注意:这里也不需要调用 IoMarkIrpPending( Irp );,IoMarkIrpPending是为了把SL_PENDING_RETURNED标志一直往上传,最终的可能就是设置PendingReturned,

PendingReturned 标志就是要告诉IO在完成IRP的时候,这个IO是异步完成的,但由于我们在这里返回STATUS_MORE_PROCESSING_REQUIRED,并且DispatchRoutine_2 waitfor了,这样在DispatchRoutine_2调用IoCompleteRequest 完成IRP的时候,这个IO其实就变成同步完成了,这样当然就不要上报这个标志了
}
// This is the only status you can return. 
return STATUS_MORE_PROCESSING_REQUIRED; 
}

 

 

 

posted @ 2013-12-28 12:18  kkindof  阅读(2321)  评论(0)    收藏  举报