REQUEST_ISOCH_FREE_BANDWIDTH difference between XP and Win7 1394 driver

Hi all,

I think I have uncovered an interesting difference between the WinXP and Win7 1394 drivers, a difference that crashes XP but not Win7. Moreover it seems that I can do nothing to avoid the crash on XP, so I would appreciate your suggestions.

The problem is that on XP if I call REQUEST_ISOCH_FREE_BANDWIDTH twice for the same bandwidth handle then I get a BSOD.

Here are some details from that BSOD:

BAD_POOL_CALLER (c2)
The current thread is making a bad pool request. Typically this is at a bad IRQL level or double freeing the same allocation, etc.

STACK_TEXT:
b43e4570 80821e09 00000003 b43e48cc 00000000 nt!RtlpBreakWithStatusInstruction
b43e45bc 808229f4 00000003 00000000 89cb76c8 nt!KiBugCheckDebugBreak+0x19
b43e499c 80822f43 000000c2 00000007 00000cd4 nt!KeBugCheck2+0x574
b43e49bc 80874583 000000c2 00000007 00000cd4 nt!KeBugCheckEx+0x1b
b43e4a0c 8087495f 89cb76d0 00000000 b43e4a54 nt!ExFreePoolWithTag+0x2a3
b43e4a1c b80bfcf7 89cb76d0 00000103 89cb7bf0 nt!ExFreePool+0xf
b43e4a54 b80babac 8adaa0e0 00001333 8ad2b008 ohci1394!OhciIsochFreeBandwidth+0xe9
b43e4a8c 8081819f 8adaa028 8a02b3d8 89cb76d0 ohci1394!OhciIOCtl+0x11a
b43e4a9c b80ce6ff b80d24f4 8ad2b008 89cb7bf0 nt!IopfCallDriver+0x31
b43e4aa0 b80d24f4 8ad2b008 89cb7bf0 8a02b3d8 1394BUS!Bus1394IsochChainToPort+0x1b
b43e4ae8 b80ce923 8ad2b008 89cb7bf0 8a02b3d8 1394BUS!Bus1394IsochFreeBandwidth+0xec
b43e4b08 b80c9f39 89cb7bf0 8a02b3d8 8accca40 1394BUS!Bus1394DispatchIsochRequest+0x35
b43e4b38 8081819f 8ad2b008 8a02b3d8 8a8ecd30 1394BUS!Bus1394IOCtl+0x2ad
b43e4b48 b7331821 8a02b46c 00000000 b43e4ba4 nt!IopfCallDriver+0x31
b43e4b58 b7338099 8accc988 8a02b3d8 89cb7bf0 mydriver!FreeBandwidth

FOLLOWUP_IP:
ohci1394!OhciIsochFreeBandwidth+e9
b80bfcf7 8bc7 mov eax,edi

SYMBOL_STACK_INDEX: 6
SYMBOL_NAME: ohci1394!OhciIsochFreeBandwidth+e9
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: ohci1394
IMAGE_NAME: ohci1394.sys
DEBUG_FLR_IMAGE_TIMESTAMP: 3d6ddc4f
FAILURE_BUCKET_ID: 0xc2_7_ohci_ohci1394!OhciIsochFreeBandwidth+e9
BUCKET_ID: 0xc2_7_ohci_ohci1394!OhciIsochFreeBandwidth+e9

Well, that might be fine you could say, don’t free the same bandwidth handle twice. But I don’t free it twice in my code, but only once. What actually crashes my system is that the handle is freed once by the 1394 driver and then also by my code.

This is the timing of how this happens:
When I close my application so it starts off to do its cleanup, among which it has to free the bandwidth handle.
When a bus reset happens my bus reset handler clears all records of allocated bandwidth and channels from my “books”, because it expects the 1394 driver to do all the freeing, although the documentation vaguely implies otherwise.
Now imagine that the bus reset happens while the application is doing its cleanup, just after my driver has checked its “books” and found that it must free a bandwidth handle on behalf of that application.
But the 1394 driver cleans up the bandwidth handle internally first and my bus reset handler has not run yet to cleanup the “books”, so my cleanup code makes the call to free the bandwidth and I get an identical BSOD as the one that I get when I make a double call directly through hardwired test code.

Now on Win7, the 2nd call will fail with error code 0xc000000d (STATUS_INVALID_PARAMETER), so this timing bug will not bite me on Win7. The fact that the behavior is as expected on Win7 makes me think that this is a clear bug on the WinXP driver.

What I also found interesting is how I uncovered this situation. I had tested sleep/resume so extensively, using PwrTest as well, so I thought that hibernation should be without problems, but little did I know. I can only reproduce the timing required by this when resuming from hibernation, and not all the times.

Has anyone seen this bug before? Any ideas on how I could bypass it?
I am at a loss here, because my cleanup code can have no idea that a bus reset is about to happen and that the 1394 driver is about to cleanup the same handle.

Thanks in advance!
Dimitrios Staikos