Canceling Irps in Win2k with Surprise removal

Hi there,
I have run across a problem that has me scratching my head. I have
developed a driver using the 2k DDK, but did all my dev/testing on an XP
box. When I physically remove my device from the system on XP, the IO
manger is canceling my queued IRP’s for me (a good thing). However, on
win 2k it is not. This only happens when the device is physically
removed. If I remove it under software control I dont have that problem.
Any ideas?

-Justin

I need to ammend my last message, the IO manager is not canceling IRP’s
for me at all in Win2K. Is this normal? My driver was written to expect
queued IRPs to be canceled by the IO manger just before I receive the
surprise removal IRP (this works on XP). I have not successfully been
able cancel IRP’s myself using IoCancelIrp().

-Justin

Justin Frodsham wrote:

I need to ammend my last message, the IO manager is not canceling IRP’s
for me at all in Win2K. Is this normal? My driver was written to expect
queued IRPs to be canceled by the IO manger just before I receive the
surprise removal IRP (this works on XP). I have not successfully been
able cancel IRP’s myself using IoCancelIrp().

The I/O Manager will not automatically cancel IRPs on any platform
simply because your device is surprise removed. You may be getting
confused by something else. For example, the USB bus driver will fail
any outstanding IRPs for a removed device. If you’re disabling
registered interfaces when you handle IRP_MN_SURPRISE_REMOVAL (as you
should), correctly coded applications will close their handles and exit.
Closing a handle will give you IRP_MJ_CLEANUP and IRP_MJ_CLOSE. An
application exiting will cause the I/O Manager to cancel IRPs
outstanding for the terminating threads.

In the scheme I show in my WDM driver book, I use a custom IRP queue (a
DEVQUEUE) that’s closely tied to the PnP and power dispatch functions. A
surprise remove triggers a call to an AbortRequests function that
cancels any queued IRPs.


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

Detach the IRPs from the queue and complete them with
STATUS_CANCELLED.

Max

----- Original Message -----
From: “Justin Frodsham”
To: “NT Developers Interest List”
Sent: Thursday, October 03, 2002 8:10 AM
Subject: [ntdev] Re: Canceling Irps in Win2k with Surprise removal

> I need to ammend my last message, the IO manager is not canceling
IRP’s
> for me at all in Win2K. Is this normal? My driver was written to
expect
> queued IRPs to be canceled by the IO manger just before I receive
the
> surprise removal IRP (this works on XP). I have not successfully
been
> able cancel IRP’s myself using IoCancelIrp().
>
> -Justin
>
> —
> You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> To unsubscribe send a blank email to %%email.unsub%%
>

I can’t do that to the Irp I already sent to a lower driver. It is sitting
in the lower driver in a cancelable state, but the lower driver doesn’t
know the above drivers are terminating (xp there is no trouble, 2k the top
level driver is not canceling).

-Justin

At 04:01 AM 10/3/2002, you wrote:

Detach the IRPs from the queue and complete them with
STATUS_CANCELLED.

Max

----- Original Message -----
From: “Justin Frodsham”
>To: “NT Developers Interest List”
>Sent: Thursday, October 03, 2002 8:10 AM
>Subject: [ntdev] Re: Canceling Irps in Win2k with Surprise removal
>
>
> > I need to ammend my last message, the IO manager is not canceling
>IRP’s
> > for me at all in Win2K. Is this normal? My driver was written to
>expect
> > queued IRPs to be canceled by the IO manger just before I receive
>the
> > surprise removal IRP (this works on XP). I have not successfully
>been
> > able cancel IRP’s myself using IoCancelIrp().
> >
> > -Justin
> >
> > —
> > You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> > To unsubscribe send a blank email to %%email.unsub%%
> >
>
>
>
>—
>You are currently subscribed to ntdev as: zeppelin@io.com
>To unsubscribe send a blank email to %%email.unsub%%

I’m just theorizing here that it might just be a BUG in the w2k USB
stack that is FIXED in the XP stack.

I realize that doesn’t help you much. Perhaps microsoft ought to
consider back-porting the much improved XP usb stack to a w2k service
pack?

You are correct in that as you are in the middle of this mess, there is
very little you can do to clean up irps that are neither on your own
queue nor originated by you.

===========================
Mark Roddy
Consultant, Microsoft DDK MVP
Hollis Technology Solutions
xxxxx@hollistech.com
www.hollistech.com
603-321-1032

-----Original Message-----
From: Justin Frodsham
To: “NT Developers Interest List”
Date: Thu, 03 Oct 2002 05:11:06 -1000
Subject: [ntdev] Re: Canceling Irps in Win2k with Surprise removal

> I can’t do that to the Irp I already sent to a lower driver. It is
> sitting
> in the lower driver in a cancelable state, but the lower driver doesn’t
> know the above drivers are terminating (xp there is no trouble, 2k the
> top
> level driver is not canceling).
>
> -Justin
>
> At 04:01 AM 10/3/2002, you wrote:
> >Detach the IRPs from the queue and complete them with
> >STATUS_CANCELLED.
> >
> > Max
> >
> >----- Original Message -----
> >From: “Justin Frodsham”
> >To: “NT Developers Interest List”
> >Sent: Thursday, October 03, 2002 8:10 AM
> >Subject: [ntdev] Re: Canceling Irps in Win2k with Surprise removal
> >
> >
> > > I need to ammend my last message, the IO manager is not canceling
> >IRP’s
> > > for me at all in Win2K. Is this normal? My driver was written to
> >expect
> > > queued IRPs to be canceled by the IO manger just before I receive
> >the
> > > surprise removal IRP (this works on XP). I have not successfully
> >been
> > > able cancel IRP’s myself using IoCancelIrp().
> > >
> > > -Justin
> > >
> > > —
> > > You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> > > To unsubscribe send a blank email to %%email.unsub%%
> > >
> >
> >
> >
> >—
> >You are currently subscribed to ntdev as: zeppelin@io.com
> >To unsubscribe send a blank email to %%email.unsub%%
>
>
>
>
> —
> You are currently subscribed to ntdev as: xxxxx@hollistech.com
> To unsubscribe send a blank email to %%email.unsub%%

I am communicating with Microsoft on the issue, and this seems to be the
case. However my last response from them said for me to complete the Irps
myself with an error code, but what If I have already passed one or all to
to then next driver!! In theory I cant do anything with the Irp at that
point. Any ideas?

-Justin

At 06:55 AM 10/4/2002, you wrote:

I’m just theorizing here that it might just be a BUG in the w2k USB
stack that is FIXED in the XP stack.

I realize that doesn’t help you much. Perhaps microsoft ought to
consider back-porting the much improved XP usb stack to a w2k service
pack?

You are correct in that as you are in the middle of this mess, there is
very little you can do to clean up irps that are neither on your own
queue nor originated by you.

===========================
Mark Roddy
Consultant, Microsoft DDK MVP
Hollis Technology Solutions
xxxxx@hollistech.com
www.hollistech.com
603-321-1032

-----Original Message-----
From: Justin Frodsham
>To: “NT Developers Interest List”
>Date: Thu, 03 Oct 2002 05:11:06 -1000
>Subject: [ntdev] Re: Canceling Irps in Win2k with Surprise removal
>
> > I can’t do that to the Irp I already sent to a lower driver. It is
> > sitting
> > in the lower driver in a cancelable state, but the lower driver doesn’t
> > know the above drivers are terminating (xp there is no trouble, 2k the
> > top
> > level driver is not canceling).
> >
> > -Justin
> >
> > At 04:01 AM 10/3/2002, you wrote:
> > >Detach the IRPs from the queue and complete them with
> > >STATUS_CANCELLED.
> > >
> > > Max
> > >
> > >----- Original Message -----
> > >From: “Justin Frodsham”
> > >To: “NT Developers Interest List”
> > >Sent: Thursday, October 03, 2002 8:10 AM
> > >Subject: [ntdev] Re: Canceling Irps in Win2k with Surprise removal
> > >
> > >
> > > > I need to ammend my last message, the IO manager is not canceling
> > >IRP’s
> > > > for me at all in Win2K. Is this normal? My driver was written to
> > >expect
> > > > queued IRPs to be canceled by the IO manger just before I receive
> > >the
> > > > surprise removal IRP (this works on XP). I have not successfully
> > >been
> > > > able cancel IRP’s myself using IoCancelIrp().
> > > >
> > > > -Justin
> > > >
> > > > —
> > > > You are currently subscribed to ntdev as: xxxxx@storagecraft.com
> > > > To unsubscribe send a blank email to %%email.unsub%%
> > > >
> > >
> > >
> > >
> > >—
> > >You are currently subscribed to ntdev as: zeppelin@io.com
> > >To unsubscribe send a blank email to %%email.unsub%%
> >
> >
> >
> >
> > —
> > You are currently subscribed to ntdev as: xxxxx@hollistech.com
> > To unsubscribe send a blank email to %%email.unsub%%
>
>
>
>—
>You are currently subscribed to ntdev as: zeppelin@io.com
>To unsubscribe send a blank email to %%email.unsub%%

Justin Frodsham wrote:

I am communicating with Microsoft on the issue, and this seems to be the
case. However my last response from them said for me to complete the Irps
myself with an error code, but what If I have already passed one or all to
to then next driver!! In theory I cant do anything with the Irp at that
point. Any ideas?

I think you’re going too far down a rathole here. If you were to simply
pass the ping-pong IRPs (as HIDCLASS calls them) down to the USB bus
driver, you’d be doing exactly what HIDUSB does. HIDCLASS cancels those
IRPs automatically. If HIDCLASS or the USB bus driver has a bug (which I
don’t actually think is the case), the bug is also showing up with
regular USB HID devices, and everybody is already living with it.

You said in earlier posts that you were queuing these IRPs and then
sending them down the stack. Perhaps there’s a flaw in your queue
routines. But why do you need to queue them at all if you’re going to
pass them down, given that the USB bus driver already has its own queue?


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

As a matter of fact, there is an issue with Hidclass not cleaning up
ping pong Irp’s in surprise removal under win2k. The MS engineer inspected
the source code and verified. Correct me if I am wrong, but I think that
is an error. Does the WDM architecture not require this? It doesn’t
usually matter, because when you pull the plug on a USB device any Irp’s
forwarded there get completed with an error code. That is not my
situation. My hid mini is virtual and the end user chooses whether or not
to expose the Hid interface to our device. The work around would seem to
be creating my own irp relaying the hid irp. I can then manually cancel it
from my surprise removal which is what the Hidclass failed to do. I have
also already mentioned that none of this is needed on XP as the code was
updated to fix this. Hidclass cleans up in surprise remove and all is
good. Unfortunately, I am having to add additional complexity to my driver
to compensate for the oversight and allow 2k compatibility. I am not
holding my breath that MS is going to supply us a hotfix or otherwise.

-Justin Frodsham

At 10:31 PM 10/4/2002, you wrote:

Justin Frodsham wrote:
> I am communicating with Microsoft on the issue, and this seems to be the
> case. However my last response from them said for me to complete the Irps
> myself with an error code, but what If I have already passed one or all to
> to then next driver!! In theory I cant do anything with the Irp at that
> point. Any ideas?

I think you’re going too far down a rathole here. If you were to simply
pass the ping-pong IRPs (as HIDCLASS calls them) down to the USB bus
driver, you’d be doing exactly what HIDUSB does. HIDCLASS cancels those
IRPs automatically. If HIDCLASS or the USB bus driver has a bug (which I
don’t actually think is the case), the bug is also showing up with
regular USB HID devices, and everybody is already living with it.

You said in earlier posts that you were queuing these IRPs and then
sending them down the stack. Perhaps there’s a flaw in your queue
routines. But why do you need to queue them at all if you’re going to
pass them down, given that the USB bus driver already has its own queue?


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com


You are currently subscribed to ntdev as: zeppelin@io.com
To unsubscribe send a blank email to %%email.unsub%%

Well,
My idea crashes and burns on XP, because the XP HidClass will not
pass down the surprise removal UNTIL the ping pong irps are canceled, so I
never get the chance to cancel my own relay Irp. I could add even more
code keep current hid Irp cancelable even after I de-queue it, but the
extra complication is starting to get out of hand. One option I have found
is to delay cleanup until I get the remove IRP, and only disable new io
with surprise remove. XP doesn’t seem to mind this and I am assuming the
2K Hidclass will cleanup/cancel the ping pong irps when it receives a
remove Irp. It will bother me to know I had to kludge it though.

-Justin

At 02:17 AM 10/5/2002, you wrote:

As a matter of fact, there is an issue with Hidclass not cleaning up
ping pong Irp’s in surprise removal under win2k. The MS engineer
inspected the source code and verified. Correct me if I am wrong, but I
think that is an error. Does the WDM architecture not require this? It
doesn’t usually matter, because when you pull the plug on a USB device
any Irp’s forwarded there get completed with an error code. That is not
my situation. My hid mini is virtual and the end user chooses whether or
not to expose the Hid interface to our device. The work around would
seem to be creating my own irp relaying the hid irp. I can then manually
cancel it from my surprise removal which is what the Hidclass failed to
do. I have also already mentioned that none of this is needed on XP as
the code was updated to fix this. Hidclass cleans up in surprise remove
and all is good. Unfortunately, I am having to add additional complexity
to my driver to compensate for the oversight and allow 2k
compatibility. I am not holding my breath that MS is going to supply us
a hotfix or otherwise.

-Justin Frodsham

At 10:31 PM 10/4/2002, you wrote:
>Justin Frodsham wrote:
> > I am communicating with Microsoft on the issue, and this seems to be the
> > case. However my last response from them said for me to complete the
> Irps
> > myself with an error code, but what If I have already passed one or all to
> > to then next driver!! In theory I cant do anything with the Irp at that
> > point. Any ideas?
>
>I think you’re going too far down a rathole here. If you were to simply
>pass the ping-pong IRPs (as HIDCLASS calls them) down to the USB bus
>driver, you’d be doing exactly what HIDUSB does. HIDCLASS cancels those
>IRPs automatically. If HIDCLASS or the USB bus driver has a bug (which I
>don’t actually think is the case), the bug is also showing up with
>regular USB HID devices, and everybody is already living with it.
>
>You said in earlier posts that you were queuing these IRPs and then
>sending them down the stack. Perhaps there’s a flaw in your queue
>routines. But why do you need to queue them at all if you’re going to
>pass them down, given that the USB bus driver already has its own queue?
>
>–
>Walter Oney, Consulting and Training
>Basic and Advanced Driver Programming Seminars
>Now teaming with John Hyde for USB Device Engineering Seminars
>Check out our schedule at http://www.oneysoft.com
>
>—
>You are currently subscribed to ntdev as: zeppelin@io.com
>To unsubscribe send a blank email to %%email.unsub%%


You are currently subscribed to ntdev as: zeppelin@io.com
To unsubscribe send a blank email to %%email.unsub%%

Justin Frodsham wrote:

As a matter of fact, there is an issue with Hidclass not cleaning up
ping pong Irp’s in surprise removal under win2k. The MS engineer inspected
the source code and verified. Correct me if I am wrong, but I think that
is an error. Does the WDM architecture not require this? It doesn’t
usually matter, because when you pull the plug on a USB device any Irp’s
forwarded there get completed with an error code. That is not my
situation. My hid mini is virtual and the end user chooses whether or not
to expose the Hid interface to our device. The work around would seem to
be creating my own irp relaying the hid irp. I can then manually cancel it
from my surprise removal which is what the Hidclass failed to do. I have
also already mentioned that none of this is needed on XP as the code was
updated to fix this. Hidclass cleans up in surprise remove and all is
good. Unfortunately, I am having to add additional complexity to my driver
to compensate for the oversight and allow 2k compatibility. I am not
holding my breath that MS is going to supply us a hotfix or otherwise.

Okay, then. You *can* cancel an IRP that someone else created, which I
think was the fundamental stumbling block. Here’s an excerpt from that
soon-to-be-a-best-seller, “Programming the Microsoft Windows Driver
Model, Second Edition”:


Canceling Someone Else’s IRP on Which You’re Not Waiting
Suppose you’ve forwarded somebody else’s IRP to another driver, but you
weren’t planning to wait for it to complete. For whatever reason, you
decide later on that you’d like to cancel that IRP.
typedef struct _DEVICE_EXTENSION {
PIRP TheIrp;
ULONG CancelFlag;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)
{
PDEVICE_EXTENSION pdx =
(PDEVICE_EXTENSION) fdo->DeviceExtension;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnComplete,
(PVOID) pdx,
TRUE, TRUE, TRUE);
pdx->CancelFlag = 0;
pdx->TheIrp = Irp;
IoMarkIrpPending(Irp);
IoCallDriver(pdx->LowerDeviceObject, Irp);
return STATUS_PENDING;
}

VOID CancelTheIrp(PDEVICE_EXTENSION pdx)
{
PIRP Irp = (PIRP) InterlockedExchangePointer(
(PVOID*) &pdx->TheIrp, NULL);
if (Irp)
{
IoCancelIrp(Irp);
if (InterlockedExchange(&pdx->CancelFlag, 1))
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}

NTSTATUS OnComplete(PDEVICE_OBJECT fdo, PIRP Irp,
PDEVICE_EXTENSION pdx)
{
if (InterlockedExchangePointer((PVOID*) &pdx->TheIrp, NULL)
|| InterlockedExchange(&pdx->CancelFlag, 1))
return STATUS_SUCCESS;
return STATUS_MORE_PROCESSING_REQUIRED;
}
This code is similar to the code I showed earlier for cancelling your
own asynchronous IRP. Here, however, allowing IoCompleteRequest to
finish completing the IRP takes the place of the call to IoFreeIrp we
made when we were dealing with our own IRP. If the completion routine is
last on the scene, it returns STATUS_SUCCESS to allow IoCompleteRequest
to finish completing the IRP. If CancelTheIrp is last on the scene, it
calls IoCompleteRequest to resume the completion processing that the
completion routine short-circuited by returning
STATUS_MORE_PROCESSING_REQUIRED.
One extremely subtle point about this example is the call to
IoMarkIrpPending in the dispatch routine. Ordinarily, it would be safe
to just do this step conditionally in the completion routine, but not
this time. If we should happen to call CancelTheIrp in the context of
some thread other than the one in which the dispatch routine runs, the
pending flag is needed so that IoCompleteRequest will schedule an APC to
cleanup the IRP in the proper thread. The easiest way to make that true
is to simply always mark the IRP pending.



Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

That is interesting, I am curios to try out the technique you show. It
makes sense, but I have had mixed results trying to do similar things (In
my testing I did not use all the safety mechanisms). So let me get this
straight then… “It is not against the rules to try and cancel an Irp
that someone else created?” I read this in the DDK:

“An intermediate driver should not arbitrarily call IoCancelIrp unless that
driver created the IRP passed in the call. Otherwise, the intermediate
driver might cancel an IRP that some higher-level driver is tracking for
purposes of its own.”

I am pretty sure I understand why the problem exists in the
Hidclass… Hidclass was essentially new, and so was surprise removal. I
came up with another method as well… conditional cleanup depending on
the WDM version. In W2k wait until remove and in XP and later do it in
surprise remove.

Thanks for the input,
Justin

Okay, then. You *can* cancel an IRP that someone else created, which I
think was the fundamental stumbling block. Here’s an excerpt from that
soon-to-be-a-best-seller, “Programming the Microsoft Windows Driver
Model, Second Edition”:


Canceling Someone Else’s IRP on Which You’re Not Waiting
Suppose you’ve forwarded somebody else’s IRP to another driver, but you
weren’t planning to wait for it to complete. For whatever reason, you
decide later on that you’d like to cancel that IRP.
typedef struct _DEVICE_EXTENSION {
PIRP TheIrp;
ULONG CancelFlag;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)
{
PDEVICE_EXTENSION pdx =
(PDEVICE_EXTENSION) fdo->DeviceExtension;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnComplete,
(PVOID) pdx,
TRUE, TRUE, TRUE);
pdx->CancelFlag = 0;
pdx->TheIrp = Irp;
IoMarkIrpPending(Irp);
IoCallDriver(pdx->LowerDeviceObject, Irp);
return STATUS_PENDING;
}

VOID CancelTheIrp(PDEVICE_EXTENSION pdx)
{
PIRP Irp = (PIRP) InterlockedExchangePointer(
(PVOID*) &pdx->TheIrp, NULL);
if (Irp)
{
IoCancelIrp(Irp);
if (InterlockedExchange(&pdx->CancelFlag, 1))
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}

NTSTATUS OnComplete(PDEVICE_OBJECT fdo, PIRP Irp,
PDEVICE_EXTENSION pdx)
{
if (InterlockedExchangePointer((PVOID*) &pdx->TheIrp, NULL)
|| InterlockedExchange(&pdx->CancelFlag, 1))
return STATUS_SUCCESS;
return STATUS_MORE_PROCESSING_REQUIRED;
}
This code is similar to the code I showed earlier for cancelling your
own asynchronous IRP. Here, however, allowing IoCompleteRequest to
finish completing the IRP takes the place of the call to IoFreeIrp we
made when we were dealing with our own IRP. If the completion routine is
last on the scene, it returns STATUS_SUCCESS to allow IoCompleteRequest
to finish completing the IRP. If CancelTheIrp is last on the scene, it
calls IoCompleteRequest to resume the completion processing that the
completion routine short-circuited by returning
STATUS_MORE_PROCESSING_REQUIRED.
One extremely subtle point about this example is the call to
IoMarkIrpPending in the dispatch routine. Ordinarily, it would be safe
to just do this step conditionally in the completion routine, but not
this time. If we should happen to call CancelTheIrp in the context of
some thread other than the one in which the dispatch routine runs, the
pending flag is needed so that IoCompleteRequest will schedule an APC to
cleanup the IRP in the proper thread. The easiest way to make that true
is to simply always mark the IRP pending.



Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com


You are currently subscribed to ntdev as: zeppelin@io.com
To unsubscribe send a blank email to %%email.unsub%%

I got the final word back from MS, and it was decided that it can be
considered a bug and will not charge me. They did confirm that the DDK
discourages canceling Irps you don’t own, because under certain situations
there are complex race conditions to deal with etc… The correct thing is
that the top driver in the stack clean up its own Irps in surprise remove
and each driver in turn does same. However, in this circumstance it is a
known scenario with synchronous behavior and if the Irps are not canceled
when I get to my surprise removal, I can go ahead and do so. Unfortunately
I now have to keep track of them, but fortunately there are only two
outstanding irps at any given time. My other solution is simpler (defer
cleanup to the REMOVE Irp in 2k), but I have to do WDM version checking and
then my driver breaks the rules to compensate for the upper one. Thank you
to everyone who responded.

-Justin Frodsham

That is interesting, I am curios to try out the technique you show. It
makes sense, but I have had mixed results trying to do similar things (In
my testing I did not use all the safety mechanisms). So let me get this
straight then… “It is not against the rules to try and cancel an Irp
that someone else created?” I read this in the DDK:

“An intermediate driver should not arbitrarily call IoCancelIrp unless
that driver created the IRP passed in the call. Otherwise, the
intermediate driver might cancel an IRP that some higher-level driver is
tracking for purposes of its own.”

I am pretty sure I understand why the problem exists in the
Hidclass… Hidclass was essentially new, and so was surprise
removal. I came up with another method as well… conditional cleanup
depending on the WDM version. In W2k wait until remove and in XP and
later do it in surprise remove.

Thanks for the input,
Justin

Okay, then. You *can* cancel an IRP that someone else created, which I
think was the fundamental stumbling block. Here’s an excerpt from that
soon-to-be-a-best-seller, “Programming the Microsoft Windows Driver
Model, Second Edition”:


Canceling Someone Else’s IRP on Which You’re Not Waiting
Suppose you’ve forwarded somebody else’s IRP to another driver, but you
weren’t planning to wait for it to complete. For whatever reason, you
decide later on that you’d like to cancel that IRP.
typedef struct _DEVICE_EXTENSION {
PIRP TheIrp;
ULONG CancelFlag;
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

NTSTATUS DispatchSomething(PDEVICE_OBJECT fdo, PIRP Irp)
{
PDEVICE_EXTENSION pdx =
(PDEVICE_EXTENSION) fdo->DeviceExtension;
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, (PIO_COMPLETION_ROUTINE) OnComplete,
(PVOID) pdx,
TRUE, TRUE, TRUE);
pdx->CancelFlag = 0;
pdx->TheIrp = Irp;
IoMarkIrpPending(Irp);
IoCallDriver(pdx->LowerDeviceObject, Irp);
return STATUS_PENDING;
}

VOID CancelTheIrp(PDEVICE_EXTENSION pdx)
{
PIRP Irp = (PIRP) InterlockedExchangePointer(
(PVOID*) &pdx->TheIrp, NULL);
if (Irp)
{
IoCancelIrp(Irp);
if (InterlockedExchange(&pdx->CancelFlag, 1))
IoCompleteRequest(Irp, IO_NO_INCREMENT);
}
}

NTSTATUS OnComplete(PDEVICE_OBJECT fdo, PIRP Irp,
PDEVICE_EXTENSION pdx)
{
if (InterlockedExchangePointer((PVOID*) &pdx->TheIrp, NULL)
|| InterlockedExchange(&pdx->CancelFlag, 1))
return STATUS_SUCCESS;
return STATUS_MORE_PROCESSING_REQUIRED;
}
This code is similar to the code I showed earlier for cancelling your
own asynchronous IRP. Here, however, allowing IoCompleteRequest to
finish completing the IRP takes the place of the call to IoFreeIrp we
made when we were dealing with our own IRP. If the completion routine is
last on the scene, it returns STATUS_SUCCESS to allow IoCompleteRequest
to finish completing the IRP. If CancelTheIrp is last on the scene, it
calls IoCompleteRequest to resume the completion processing that the
completion routine short-circuited by returning
STATUS_MORE_PROCESSING_REQUIRED.
One extremely subtle point about this example is the call to
IoMarkIrpPending in the dispatch routine. Ordinarily, it would be safe
to just do this step conditionally in the completion routine, but not
this time. If we should happen to call CancelTheIrp in the context of
some thread other than the one in which the dispatch routine runs, the
pending flag is needed so that IoCompleteRequest will schedule an APC to
cleanup the IRP in the proper thread. The easiest way to make that true
is to simply always mark the IRP pending.



Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com


You are currently subscribed to ntdev as: zeppelin@io.com
To unsubscribe send a blank email to %%email.unsub%%

Justin Frodsham wrote:

They did confirm that the DDK
discourages canceling Irps you don’t own, because under certain situations
there are complex race conditions to deal with etc…

Yes, but members of the base team reviewed the code I posted and found
it adequate. I will happy to hear about any hole in it, of course, but
it seems to me that that code solves the race conditions.


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com

Please don’t misunderstand, I wasn’t questioning your code, just getting
mixed signals. I just feel better now that Microsoft has confirmed what
you said. Also, that I didn’t misinterpret the DDK (which discourages the
concept). I definitely now understand how, why and when Irps get canceled
(and what to do when the driver above you does something
wrong). :slight_smile: Also, the fact that MS didn’t charge me tells me I am not
totally out to lunch. :slight_smile:

Thanks again,
Justin

At 09:41 PM 10/7/2002, you wrote:

Justin Frodsham wrote:
> They did confirm that the DDK
> discourages canceling Irps you don’t own, because under certain situations
> there are complex race conditions to deal with etc…

Yes, but members of the base team reviewed the code I posted and found
it adequate. I will happy to hear about any hole in it, of course, but
it seems to me that that code solves the race conditions.


Walter Oney, Consulting and Training
Basic and Advanced Driver Programming Seminars
Now teaming with John Hyde for USB Device Engineering Seminars
Check out our schedule at http://www.oneysoft.com


You are currently subscribed to ntdev as: zeppelin@io.com
To unsubscribe send a blank email to %%email.unsub%%