Tech Support > Microsoft Windows > Drivers > Question about filter sample from Mr. Oney's book
Question about filter sample from Mr. Oney's book
Posted by Benoît Bousquet on August 30th, 2004


Chapter 16, "filter" sample, DispatchAny function (master IRP handler):

---cut here---
(...)
// Pass request down without additional processing
NTSTATUS status;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return status;
} // DispatchAny
---cut here---

Assuming I want to make changes to the IRP_MJ_READ buffer after the lower
driver fills it, would I need to add a completion routine to the read
request? I tried adding a call to IoSetCompletionRoutine right before the
IoCallDriver line (and moving the IoReleaseRemoveLock into the dispatch
routine, obviously) but everything stops working (I get hangs and systematic
failures) when I do that:

---cut here---
(...)
// Pass request down without additional processing
NTSTATUS status;
status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);
if (!NT_SUCCESS(status))
return CompleteRequest(Irp, status, 0);
IoSkipCurrentIrpStackLocation(Irp);
IoSetCompletionRoutine(Irp,
(PIO_COMPLETION_ROUTINE)PassThroughCompletionRouti ne, pdx, TRUE, TRUE,
TRUE);
status = IoCallDriver(pdx->LowerDeviceObject, Irp);
return status;
} // DispatchAny

NTSTATUS PassThroughCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PVOID Context)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)Context;
IoReleaseRemoveLock(&((PDEVICE_EXTENSION)Context)->RemoveLock, Irp);
return STATUS_MORE_PROCESSING_REQUIRED;
}
---cut here---

The documentation confuses me (then again, I'm easily confused, I guess).
Should the completion routine be returning STATUS_SUCCESS in this case? And
assuming I'm somewhat doing things right, how would I obtain the values that
were in the IO_STACK_LOCATION from inside the completion routine (or would
it be better to send those through the Context parameter...)?

--
-----
Benoît Bousquet
(e-mail address is invalid)


Posted by Walter Oney on August 30th, 2004


"Benoît Bousquet" wrote:
Yes, the completion routine should return STATUS_SUCCESS. In addition,
you should almost certainly be calling
IoCopyCurrentIrpStackLocationToNext instead of
IoSkipCurrenIrpStackLocation in the dispatch routine. This is scenario
number 1 in my cookbook of IRP handling scenarios, described on pp.
294-95 of the book.

Bear in mind that the lower driver will put the data in a place that
matches the DO_DIRECT_IO or DO_BUFFERED_IO flag in the device object. A
filter driver should be prepared to handle either (or neither) case.

--
Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Check out our schedule at http://www.oneysoft.com

Posted by Calvin Guan on August 30th, 2004


Also note that if the OP wants to change the status of the IRP in the
completion he must not return IoCallDriver in the dispatch routine. I don't
remember off hand if this scenario was mentioned in the book.

-
Calvin Guan Software Engineer
ATI Technologies Inc. www.ati.com

"Walter Oney" <waltoney@oneysoft.com> wrote in message
news:413369B2.89DBC016@oneysoft.com...


Posted by Benoît Bousquet on August 30th, 2004


Thank you. It's always nice to get a reply from the book's author.

I'm curious regarding a specific issue though: The sample completion routine
on page 295 checks the PendingReturned flag and calls IoMarkIrpPending if
it's set. Does that imply the IRP is still pending as far as the lower
driver is concerned (i.e. is it done with the read buffer)? My completion
routine is currently as follows:

---cut here---
NTSTATUS PassThroughCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp,
PVOID Context)
{
PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION)Context;
PIO_STACK_LOCATION pOldStack = NULL;
UCHAR type = 0;
if(Irp->PendingReturned)
{
IoMarkIrpPending(Irp);
}
pOldStack = IoGetCurrentIrpStackLocation(Irp);
type = pOldStack->MajorFunction;
if(type == IRP_MJ_READ)
{
// modify the read buffer if needed, and update the buffer length
// ...
}
IoReleaseRemoveLock(&pdx->RemoveLock, Irp);
return STATUS_SUCCESS;
}
---cut here---

pOldStack and its contents are usually valid, but I've been running across a
few cases where it's not, and subsequently page faults. I believe my piece
of code is flawed.


--
-----
Benoît Bousquet
(e-mail address is invalid)


"Walter Oney" <waltoney@oneysoft.com> wrote in message
news:413369B2.89DBC016@oneysoft.com...


Posted by Peter Wieland [MSFT] on August 30th, 2004


The lower driver is done with the buffer when it completes the request. It
must be (if it's not then there's a bug).

-p

--
This posting is provided "AS IS" with no warranties, and confers no rights.
"Benoît Bousquet" <benoit.bousquet@nospam.zzz> wrote in message
news:elepJwsjEHA.3612@TK2MSFTNGP12.phx.gbl...