I’m analyzing memory dump with BSOD DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce). I can’t believe what I see.
It occured during USB device surprise removal. Driver apparently received surprise remove and remove IRPs and blocked waiting until everything completes. In parallel or as a result of SR it received an IOCTL from user mode app which in turn lead to port reset which can take some times in this state. When done, IOCTL dispatch completed the IRP and decremented IO count which in turn lead to unblocked remove IRP handler finishing and removing the device. User mode app then probably closed a handle from different thread which caused driver unload. But IOCTL dispatch still had few instructions to execute and crashed because code wasn’t in the memory.
I just took Oney’s WDM book and he clearly states driver remains in the memory until it both completes IRP and returns from the dispatch routine. But it didn’t. Someting changed in the XP SP2? Or is it app responsibility to not close handles before synchronous functions called from other threads return? (seems impossible anyway)
Analysis below. I forced WinDbg to load symbols for my unloaded driver (tcusb.sys) so don’t be confused it is there. Originally there was just reference to unloaded driver. I examined handle 0x450 passed to NtDeviceIoControlFile() and it is already freed. Also my device extension indicates all handles were freed.
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
A driver unloaded without cancelling timers, DPCs, worker threads, etc.
The broken driver’s name is displayed on the screen.
Arguments:
Arg1: f7972185, memory referenced
Arg2: 00000000, value 0 = read operation, 1 = write operation
Arg3: f7972185, If non-zero, the instruction address which referenced the bad memory
address.
Arg4: 00000000, Mm internal code.
Debugging Details:
READ_ADDRESS: f7972185
FAULTING_IP:
tcusb!BulkUsb_IoDecrement+61 [e:\build\tcdrv\build-0071-main\src\tcdrv\bulkpnp.c @ 2796]
f7972185 ?? ???
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0xCE
PROCESS_NAME: sdk_test.exe
TRAP_FRAME: eea73a30 – (.trap ffffffffeea73a30)
ErrCode = 00000000
eax=80a16123 ebx=82d9c848 ecx=00000000 edx=00000000 esi=82d9c824 edi=8080cf16
eip=f7972185 esp=eea73aa4 ebp=eea73ab4 iopl=0 nv up ei pl nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010202
tcusb!BulkUsb_IoDecrement+0x61:
f7972185 ?? ???
Resetting default scope
LAST_CONTROL_TRANSFER: from 8084d6fb to 8085c9ae
FAILED_INSTRUCTION_ADDRESS:
tcusb!BulkUsb_IoDecrement+61 [e:\build\tcdrv\build-0071-main\src\tcdrv\bulkpnp.c @ 2796]
f7972185 ?? ???
STACK_TEXT:
eea739cc 8084d6fb 00000050 f7972185 00000000 nt!KeBugCheckEx+0x1b
eea73a18 8080aff1 00000000 f7972185 00000000 nt!MmAccessFault+0x6f5
eea73a18 f7972185 00000000 f7972185 00000000 nt!KiTrap0E+0xcc
eea73ab4 f7976b58 00d9c758 82de6fb8 831c5278 tcusb!BulkUsb_IoDecrement+0x61 [e:\build\tcdrv\build-0071-main\src\tcdrv\bulkpnp.c @ 2796]
eea73c34 8080cd77 82d9c6a0 8324f008 80a16070 tcusb!DispatchDevCtrl+0xed6 [e:\build\tcdrv\build-0071-main\src\tcdrv\ioctl.c @ 1297]
eea73c44 808939ab 8324f0e4 832762e0 8324f008 nt!IopfCallDriver+0x31
eea73c58 808a69f7 82d9c6a0 8324f008 832762e0 nt!IopSynchronousServiceTail+0x60
eea73d00 808a8bfa 00000450 00000464 00000000 nt!IopXxxControlFile+0x611
eea73d34 8080806b 00000450 00000464 00000000 nt!NtDeviceIoControlFile+0x2a
eea73d34 7c90eb94 00000450 00000464 00000000 nt!KiFastCallEntry+0xf8
WARNING: Frame IP not in any known module. Following frames may be wrong.
00129a34 00000000 00000000 00000000 00000000 0x7c90eb94
STACK_COMMAND: kb
FOLLOWUP_IP:
tcusb!BulkUsb_IoDecrement+61 [e:\build\tcdrv\build-0071-main\src\tcdrv\bulkpnp.c @ 2796]
f7972185 ?? ???
FAULTING_SOURCE_CODE:
2792:
2793: KeReleaseSpinLock(&DeviceExtension->IOCountLock, oldIrql);
2794:
2795: TTRACE_LEAVE((“BulkUsb_IoDecrement() -> %x”, result));
2796: return(result);
2797: }
2798:
2799: NTSTATUS
2800: CanStopDevice(
2801: IN PDEVICE_OBJECT DeviceObject,
SYMBOL_STACK_INDEX: 3
SYMBOL_NAME: tcusb!BulkUsb_IoDecrement+61
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: tcusb
IMAGE_NAME: tcusb.sys
DEBUG_FLR_IMAGE_TIMESTAMP: fffffffe
FAILURE_BUCKET_ID: 0xCE_BAD_IP_tcusb!BulkUsb_IoDecrement+61
BUCKET_ID: 0xCE_BAD_IP_tcusb!BulkUsb_IoDecrement+61
Followup: MachineOwner
Best regards,
Michal Vodicka
UPEK, Inc.
[xxxxx@upek.com, http://www.upek.com]