Re: Propagating the Pending Bit

Tech-Archive recommends: Fix windows errors by optimizing your registry



Calvin,

It's ok not to mark pending while
returning !STATUS_MORE_PROCESSING_REQUIRED.

Here is the quotation from IoMarkIrpPending documentation in WDK

[begin quote]

If a driver sets an IoCompletion routine for an IRP and then passes the IRP
down to a lower driver, the IoCompletion routine should check the
IRP->PendingReturned flag. If the flag is set, the IoCompletion routine must
call IoMarkIrpPending with the IRP.

[end quote]

As you can see, according to MSDN, unless you abort the call chain of
completion routines by returning STATUS_MORE_PROCESSING_REQUIRED,
IoMarkIrpPending() is an absolute must here. It seems to be a pointless call,
but it is not - you will see it shortly

NTSTATUS CompRoutine(irp)
{
//do whatever with the IRP
return STATUS_CONTINUE_COMPLETION;
}

As you will see below, the above code has quite insidious bug in it....


it doesn't make sense while setting a bit that nobody cares.

Well, this is quite bold statement. The problem is that, although the OS,
apparently, does not really care about it, some third-party drivers may do.
Consider the following scenario:


Someone decides to "optimize a performance" and avoid unnecessary calls to
KeSetEvent() in the completion routine. Therefore, his actions depend on
whether IRP has been completed synchronously or asynchronously. If IRP has
been completed asynchronously, he calls KeSetEvent() in the completion
routine, because he knows that his Dispatch routine waits on it . Otherwise,
he does not do anything - he knows that his Dispatch routine would not wait
on event if IRP has been completed synchronously, so that he deems a call to
KeSetEvent() unnecessary.....



What happens if you write your completion routine the way you have described,
and this "optimized" driver happens to be above you on the stack? The answer
is obvios - if you don't propagate PendingReturned flag, this driver will
always believe that IRP has been completed synchronously, and, hence, will
never call
KeSetEvent(). Therefore, if IoCallDriver() call that he makes from his
Dispatch routine returns STATUS_PENDING, his Dispatch routine is going to
deadlock......

This is just a classical example of how one may get into a conflict with the
third-party software because of avoiding some seemingly pointless call that,
according to MSDN, he should make....


Anton Bassov

"Calvin Guan" wrote:

Interesting. Haven't seen discussion on classic topic like this for a long
time.

However, if the driver sets an IoCompletion routine, and the
next-lower driver returns STATUS_PENDING, the current driver must mark
its
own I/O stack location as pending.

I don't know where the OP get this from. I don't know the context of this
statement but if there is no higher driver, doing so is most likely
committing suicide unless the caller has allocated extra stack. but still it
doesn't make sense while setting a bit that nobody cares.

Not necessarily - it is required to do so only if its completion routine
does not return STATUS_MORE_PROCESSING_REQUIRED.

"Only" is a bit too strong here. It's ok not to mark pending while
returning !STATUS_MORE_PROCESSING_REQUIRED.

NTSTATUS CompRoutine(irp)
{
//do whatever with the IRP
return STATUS_CONTINUE_COMPLETION;
}

NTSTATUS
Xyz_call_drv_and_potentially_alter_the_return_status (
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context
)
{
IoMarkIrpPending(Irp);
IoSetCompletionRoutine(Irp,CompRoutine,....);
IoCallDriver(DeviceObject,Irp);
return STATUS_PENDING;
}

There are just too many calling and completion combinations. I think the
best way for people outside of MSFT to understand how things work is disasm
the IoSyncxxxServiceTail and IofCompleteRequest. It hasn't changed a lot
since NT3.x. In the end, why would people have to care about IRP nowadays? I
thought MSFT wants us use WDF which would solve all of the mess.

--
Calvin Guan (expiring DDK MVP)
Sr. Staff Engineer
NetXtreme NTX Miniport
Broadcom Corporation
Connecting Everything(r)



.



Relevant Pages

  • IoReleaseRemoveLock race
    ... operations that set an IoCompletion routine include a race condition. ... They could allow a driver to release the last known reference to its ... if the lower driver happens to call ...
    (microsoft.public.development.device.drivers)
  • Help in NDIS Driver
    ... I am writing virtual network i/f driver for a PCI card. ... This driver also requires a IOCTL dispatch routine for few device ... The IOCTL routines used to read / write data from / to the PCI card ... and set a completion routine for the IRP. ...
    (microsoft.public.development.device.drivers)
  • serial read problem
    ... I'm writing an upper filter driver on USBSER.sys from microsoft, ... One of the feature I need, in the Dispatch_IO routine of my filter, is ... IoCallDriver (deviceExtension->NextLowerDriver, Irp); ...
    (microsoft.public.development.device.drivers)
  • Re: serial read problem
    ... mscomm.ocx cannot handle pended async reads. ... I'm writing an upper filter driver on USBSER.sys from microsoft, ... One of the feature I need, in the Dispatch_IO routine of my filter, is ... IoCallDriver (deviceExtension->NextLowerDriver, Irp); ...
    (microsoft.public.development.device.drivers)
  • Re: Irp handling scenario
    ... IoMarkPending, ... "Any driver that sets an IoCompletion routine in an IRP and then passes ...
    (microsoft.public.development.device.drivers)