From: Jeff Rhyason Jeff on
Hi everyone,

I am implementing FSCTL_INVALIDATE_VOLUMES for my on-disk filesystem
and have managed to handle every case I can think of except the trivial
one. I mean, I can handle forced dismounts from surprise disk removals
(from e.g. unplugging USB disks) when there ARE open handles, but I've
got a problem when there are NO open files on it. (I'd have thought
would be simpler, but I've definitely messed something up.)

If during INVALIDATE_VOLUMES handling I swap the RealDevice VPB and free
the old one (a la FASTFAT AFAICT), I get a crash like this:

*******************************************************************************
*
*
* Bugcheck Analysis
*
*
*
*******************************************************************************

DRIVER_VERIFIER_IOMANAGER_VIOLATION (c9)
The IO manager has caught a misbehaving driver.
Arguments:
Arg1: 0000000000000004, Invalid Device object passed to IoCallDriver
Arg2: fffffa8000d42d68, the Device object
Arg3: 0000000000000000
Arg4: 0000000000000000

Debugging Details:
------------------


BUGCHECK_STR: 0xc9_4

DRIVER_VERIFIER_IO_VIOLATION_TYPE: 4

DEVICE_OBJECT: fffffa8000d42d68

DRIVER_OBJECT: fffff8000179e928

IMAGE_NAME: hy

DEBUG_FLR_IMAGE_TIMESTAMP: 0

MODULE_NAME: hy

FAULTING_MODULE: 0000000000000000

DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT

PROCESS_NAME: System

CURRENT_IRQL: 2

LAST_CONTROL_TRANSFER: from fffff80001711502 to fffff800016616f0

STACK_TEXT:
fffffa60`01784d68 fffff800`01711502 : fffffa80`00d44040 00000000`00000065
00000000`00000004 fffff800`016a4210 : nt!RtlpBreakWithStatusInstruction
fffffa60`01784d70 fffff800`017122bb : 00000000`00000003 00000000`00000000
fffff800`016a1aa0 00000000`000000c9 : nt!KiBugCheckDebugBreak+0x12
fffffa60`01784dd0 fffff800`01667554 : 00000000`00000001 00000000`00000000
fffff800`01a78440 fffff800`016929fe : nt!KeBugCheck2+0x6eb
fffffa60`01785440 fffff800`016d0580 : 00000000`000000c9 00000000`00000004
fffffa80`00d42d68 00000000`00000000 : nt!KeBugCheckEx+0x104
fffffa60`01785480 fffff800`01a72476 : fffff980`08966f30 fffff800`0168c1c1
00000000`00000000 fffffa80`026dce20 : nt!VfBugCheckNoStackUsage+0x30
fffffa60`017854c0 fffff800`018d4084 : fffffa80`026dce20 fffff980`08966f30
fffff980`0897eca0 fffffa80`021a29f0 : nt!IovCallDriver+0x236
fffffa60`01785500 fffff800`018c96a0 : 00000000`00000000 fffffa80`026dce20
fffff880`05a4cfd0 fffffa80`00d4b000 : nt!IopCloseFile+0x184
fffffa60`01785590 fffff800`018d1287 : fffff880`05a4cfd0 fffffa80`00000001
fffffa80`00cef110 00000000`00000000 : nt!ObpDecrementHandleCount+0xc0
fffffa60`01785620 fffff800`018d1554 : fffff880`000000d0 fffff880`00000000
00000000`00000000 00000000`000007f4 : nt!ObpCloseHandleTableEntry+0xb7
fffffa60`017856c0 fffff800`01666ef3 : fffffa80`00d44040 fffffa60`01785790
00000000`00000000 00000000`00000000 : nt!ObpCloseHandle+0x94
fffffa60`01785710 fffff800`01667400 : fffff800`01a3b8c8 00000000`00000000
00000000`00000000 fffffa60`01785988 : nt!KiSystemServiceCopyEnd+0x13
fffffa60`017858a8 fffff800`01a3b8c8 : 00000000`00000000 00000000`00000000
fffffa60`01785988 fffffa80`021a29f0 : nt!KiServiceLinkage
fffffa60`017858b0 fffff800`01a40e5b : fffffa80`026e7bd0 ffffffff`800007f4
fffffa80`026e7bd0 00000000`00000017 : nt!IopInvalidateVolumesForDevice+0x278
fffffa60`01785980 fffff800`01a3d743 : fffffa80`026e7950 fffffa80`026e7950
00000000`0000030a 00000000`00000308 : nt!IopRemoveDevice+0x15b
fffffa60`01785a40 fffff800`01a40937 : fffffa80`026e7950 00000000`00000000
00000000`00000003 00000000`72637050 :
nt!PnpSurpriseRemoveLockedDeviceNode+0xe3
fffffa60`01785a80 fffff800`01a40a60 : 00000000`00000000 fffffa80`026e7900
fffff880`060d6cd0 fffffa60`01785bc8 : nt!PnpDeleteLockedDeviceNode+0x37
fffffa60`01785ab0 fffff800`01a44c08 : 00000000`00000002 00000000`00000000
00000000`00000003 00000000`00000000 : nt!PnpDeleteLockedDeviceNodes+0xa0
fffffa60`01785b20 fffff800`01a4574c : fffffa60`01785cf8 00000000`00000000
fffff880`0656a200 fffffa80`00000000 : nt!PnpProcessQueryRemoveAndEject+0x6d8
fffffa60`01785c70 fffff800`019447aa : 00000000`00000001 fffffa80`022930e0
fffff880`06157950 00000000`4b706e50 : nt!PnpProcessTargetDeviceEvent+0x4c
fffffa60`01785ca0 fffff800`0166e8c3 : fffff800`018647d8 fffff880`06157950
fffff800`0179e8f8 fffffa80`00d44040 : nt! ?? ::NNGAKEGL::`string'+0x4ffc7
fffffa60`01785cf0 fffff800`01871ec7 : fffffa80`022930e0 00000000`00000000
fffffa80`00d44040 00000000`00000080 : nt!ExpWorkerThread+0xfb
fffffa60`01785d50 fffff800`016a4616 : fffff800`01780680 fffffa80`00d44040
fffffa80`00d43720 fffffa80`00d43818 : nt!PspSystemThreadStartup+0x57
fffffa60`01785d80 00000000`00000000 : 00000000`00000000 00000000`00000000
00000000`00000000 00000000`00000000 : nt!KiStartSystemThread+0x16


STACK_COMMAND: kb

FOLLOWUP_NAME: MachineOwner

FAILURE_BUCKET_ID: X64_0xc9_4_VRF_IMAGE_hy

BUCKET_ID: X64_0xc9_4_VRF_IMAGE_hy

Followup: MachineOwner
---------

If I leak the VPB then everything works fine.

AFAICT I should be able to free the original VPB, as at the time:
- the Vpb->RealDevice no longer refers back to this VPB
- the Vpb->ReferenceCount is 0
- the filesystem has no open handles
- the current INVALIDATE_VOLUMES is the only IRP being processed by
the driver

I'd be very grateful for any ideas! In particular can anyone suggest
how to get more information about the handle argument to ObpCloseHandle()
and figure out how it leads to my VPB?

Thanks,

Jeff