Marc
August 7, 2026, 6:55pm
1
Hello,
Bugcheck code 0xc4 with arg1 = 0xd7 but (as seen in dx output below)
Common::Removed is 0x0 which tells me nt!IoReleaseRemoveLockAndWaitEx has not been called
Common::IoCount is 0x0 which tells me nt!IoInitializeRemoveLockEx has not been called
Any ideas? Thanks!
1: kd> dx -r4 (*((Foo!_IO_REMOVE_LOCK *)0xffff8006b636f1e8))
(*((Foo!_IO_REMOVE_LOCK *)0xffff8006b636f1e8)) [Type: _IO_REMOVE_LOCK]
[+0x000] Common [Type: _IO_REMOVE_LOCK_COMMON_BLOCK]
[+0x000] Removed : 0x0 [Type: unsigned char]
[+0x001] Reserved [Type: unsigned char [3]]
[0] : 0x0 [Type: unsigned char]
[1] : 0x0 [Type: unsigned char]
[2] : 0x0 [Type: unsigned char]
[+0x004] IoCount : 0 [Type: long]
[+0x008] RemoveEvent [Type: _KEVENT]
[+0x000] Header [Type: _DISPATCHER_HEADER]
[+0x000] Lock : 0 [Type: long]
[+0x000] LockNV : 0 [Type: long]
[+0x000] Type : 0x0 [Type: unsigned char]
[+0x001] Signalling : 0x0 [Type: unsigned char]
[+0x002] Size : 0x0 [Type: unsigned char]
Can you post the !analyze -v output?
Marc
August 8, 2026, 3:44pm
3
Here it is. Thanks Scott!
1: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught. This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, BugChecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 00000000000000d7, Re-initializing Remove Lock.
Arg2: ffff8006b8ad06b0, Address of the chk build Remove Lock structure used internally by Verifier.
Arg3: ffff8006b636f1e8, Address of the Remove Lock structure specified by the driver.
A Remove Lock cannot be re-initialized, even after calling
IoReleaseRemoveLockAndWait, because other threads might still be
using that lock (by calling IoAcquireRemoveLock). The driver should
allocate the Remove Lock inside its device extension, and initialize
it a single time. The lock will be deleted together with the device
extension.
Arg4: 0000000000000000
Debugging Details:
------------------
KEY_VALUES_STRING: 1
Key : Analysis.CPU.mSec
Value: 1734
Key : Analysis.Elapsed.mSec
Value: 1761
Key : Analysis.IO.Other.Mb
Value: 0
Key : Analysis.IO.Read.Mb
Value: 8
Key : Analysis.IO.Write.Mb
Value: 10
Key : Analysis.Init.CPU.mSec
Value: 66593
Key : Analysis.Init.Elapsed.mSec
Value: 86324293
Key : Analysis.Memory.CommitPeak.Mb
Value: 113
Key : Analysis.Version.DbgEng
Value: 10.0.29482.1003
Key : Analysis.Version.Description
Value: 10.2509.29.03 amd64fre
Key : Analysis.Version.Ext
Value: 1.2509.29.3
Key : Bugcheck.Code.KiBugCheckData
Value: 0xc4
Key : Bugcheck.Code.LegacyAPI
Value: 0xc4
Key : Bugcheck.Code.TargetModel
Value: 0xc4
Key : Dump.Attributes.AsUlong
Value: 0x1000
Key : Dump.Attributes.DiagDataWrittenToHeader
Value: 1
Key : Dump.Attributes.ErrorCode
Value: 0x0
Key : Dump.Attributes.LastLine
Value: Dump completed successfully.
Key : Dump.Attributes.ProgressPercentage
Value: 100
Key : Failure.Bucket
Value: 0xc4_d7_VRF_FooDrv!EventCreateClose
Key : Failure.Hash
Value: {12b9c27b-0ea4-323a-fb01-a0756df7b7fa}
Key : Hypervisor.Enlightenments.Value
Value: 12576
Key : Hypervisor.Enlightenments.ValueHex
Value: 0x3120
Key : Hypervisor.Flags.AnyHypervisorPresent
Value: 1
Key : Hypervisor.Flags.ApicEnlightened
Value: 0
Key : Hypervisor.Flags.ApicVirtualizationAvailable
Value: 0
Key : Hypervisor.Flags.AsyncMemoryHint
Value: 0
Key : Hypervisor.Flags.CoreSchedulerRequested
Value: 0
Key : Hypervisor.Flags.CpuManager
Value: 0
Key : Hypervisor.Flags.DeprecateAutoEoi
Value: 1
Key : Hypervisor.Flags.DynamicCpuDisabled
Value: 0
Key : Hypervisor.Flags.Epf
Value: 0
Key : Hypervisor.Flags.ExtendedProcessorMasks
Value: 0
Key : Hypervisor.Flags.HardwareMbecAvailable
Value: 0
Key : Hypervisor.Flags.MaxBankNumber
Value: 0
Key : Hypervisor.Flags.MemoryZeroingControl
Value: 0
Key : Hypervisor.Flags.NoExtendedRangeFlush
Value: 1
Key : Hypervisor.Flags.NoNonArchCoreSharing
Value: 0
Key : Hypervisor.Flags.Phase0InitDone
Value: 1
Key : Hypervisor.Flags.PowerSchedulerQos
Value: 0
Key : Hypervisor.Flags.RootScheduler
Value: 0
Key : Hypervisor.Flags.SynicAvailable
Value: 1
Key : Hypervisor.Flags.UseQpcBias
Value: 0
Key : Hypervisor.Flags.Value
Value: 536632
Key : Hypervisor.Flags.ValueHex
Value: 0x83038
Key : Hypervisor.Flags.VpAssistPage
Value: 1
Key : Hypervisor.Flags.VsmAvailable
Value: 0
Key : Hypervisor.RootFlags.AccessStats
Value: 0
Key : Hypervisor.RootFlags.CrashdumpEnlightened
Value: 0
Key : Hypervisor.RootFlags.CreateVirtualProcessor
Value: 0
Key : Hypervisor.RootFlags.DisableHyperthreading
Value: 0
Key : Hypervisor.RootFlags.HostTimelineSync
Value: 0
Key : Hypervisor.RootFlags.HypervisorDebuggingEnabled
Value: 0
Key : Hypervisor.RootFlags.IsHyperV
Value: 0
Key : Hypervisor.RootFlags.LivedumpEnlightened
Value: 0
Key : Hypervisor.RootFlags.MapDeviceInterrupt
Value: 0
Key : Hypervisor.RootFlags.MceEnlightened
Value: 0
Key : Hypervisor.RootFlags.Nested
Value: 0
Key : Hypervisor.RootFlags.StartLogicalProcessor
Value: 0
Key : Hypervisor.RootFlags.Value
Value: 0
Key : Hypervisor.RootFlags.ValueHex
Value: 0x0
Key : SecureKernel.HalpHvciEnabled
Value: 0
Key : WER.OS.Branch
Value: ni_release
Key : WER.OS.Version
Value: 10.0.22621.1
Key : WER.System.BIOSRevision
Value: 255.255.0.0
BUGCHECK_CODE: c4
BUGCHECK_P1: d7
BUGCHECK_P2: ffff8006b8ad06b0
BUGCHECK_P3: ffff8006b636f1e8
BUGCHECK_P4: 0
FILE_IN_CAB: MEMORY.DMP
DUMP_FILE_ATTRIBUTES: 0x1000
FAULTING_THREAD: ffff8006b7252080
BLACKBOXBSD: 1 (!blackboxbsd)
BLACKBOXNTFS: 1 (!blackboxntfs)
BLACKBOXPNP: 1 (!blackboxpnp)
BLACKBOXWINLOGON: 1 (!blackboxwinlogon)
PROCESS_NAME: foo-driver-app.exe
STACK_TEXT:
ffffc409`17c53158 fffff803`63fd5cdb : 00000000`000000c4 00000000`000000d7 ffff8006`b8ad06b0 ffff8006`b636f1e8 : nt!KeBugCheckEx
ffffc409`17c53160 fffff803`63fd4917 : 00000000`00000000 fffff803`63e314b0 fffff803`63e314b0 00000000`00000000 : nt!CarInitiateBugcheck+0x47
ffffc409`17c531a0 fffff803`644d034c : 00000000`000000c4 00000000`00000000 00000000`00000020 00000000`ffffff01 : nt!CarReportRuleViolationForTriage+0x147
ffffc409`17c53220 fffff803`644d5698 : 00000000`00000001 ffffc409`17c533b0 00000000`00000020 ffff8006`b636f1e8 : nt!VerifierBugCheckIfAppropriate+0xc8
ffffc409`17c532c0 fffff805`4662809b : 00000000`00000000 ffffc409`17c533b0 ffff8006`b636f1b0 ffffc409`17c533b0 : nt!VerifierIoInitializeRemoveLockEx+0x78
ffffc409`17c53330 fffff803`63fdb33b : ffff8006`aecbab20 ffff8006`aecbab20 ffff8006`b636f060 00000000`00000040 : FooDrv!EventCreateClose+0x9b
ffffc409`17c53370 fffff803`63cb54ff : ffff8006`b72f0aa0 ffff8006`b636f060 ffff8006`b84b2750 ffffc409`17c53408 : nt!DifIRP_MJ_CREATEWrapper+0xdb
ffffc409`17c533d0 fffff803`644c422f : 00000000`00000000 00000000`00000000 00000000`00000030 00000000`00000000 : nt!IopfCallDriver+0x53
ffffc409`17c53410 fffff803`63e45f91 : ffff8006`b636f060 ffffc409`17c53760 ffff8006`b72f0bb8 00000000`00000000 : nt!IovCallDriver+0x5f
ffffc409`17c53450 fffff803`640ab28e : ffff8006`b636f060 ffffc409`17c53760 ffff8006`b72f0aa0 ffff8006`b84b2750 : nt!IofCallDriver+0x12f251
ffffc409`17c53490 fffff803`641d10a4 : fffff803`640aa9d0 fffff803`640aa9d0 ffff8006`aeced300 ffffc409`17c53880 : nt!IopParseDevice+0x8be
ffffc409`17c53660 fffff803`641cfa52 : ffff8006`b5caa701 ffffc409`17c53880 00000000`00000040 ffff8006`aee48bc0 : nt!ObpLookupObjectName+0x1104
ffffc409`17c537f0 fffff803`641c0981 : 00000800`00000000 ffff8006`b655c820 000000ee`97bcf640 ffff8006`b655c838 : nt!ObOpenObjectByNameEx+0x1f2
ffffc409`17c53920 fffff803`641c03f9 : 000000ee`97bcf5e0 00000000`00000001 000000ee`97bcf640 000000ee`97bcf5e8 : nt!IopCreateFile+0x431
ffffc409`17c539e0 fffff803`63e294e5 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!NtCreateFile+0x79
ffffc409`17c53a70 00007ff8`db48fe94 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : nt!KiSystemServiceCopyEnd+0x25
000000ee`97bcf558 00000000`00000000 : 00000000`00000000 00000000`00000000 00000000`00000000 00000000`00000000 : 0x00007ff8`db48fe94
SYMBOL_NAME: FooDrv!EventCreateClose+9b
MODULE_NAME: FooDrv
IMAGE_NAME: FooDrv.sys
STACK_COMMAND: .process /r /p 0xffff8006b7e130c0; .thread 0xffff8006b7252080 ; kb
BUCKET_ID_FUNC_OFFSET: 9b
FAILURE_BUCKET_ID: 0xc4_d7_VRF_FooDrv!EventCreateClose
OS_VERSION: 10.0.22621.1
BUILDLAB_STR: ni_release
OSPLATFORM_TYPE: x64
OSNAME: Windows 10
FAILURE_ID_HASH: {12b9c27b-0ea4-323a-fb01-a0756df7b7fa}
Followup: MachineOwner
---------
Marc
August 8, 2026, 4:22pm
4
Hi Scott, the Akismet spam filter has temporarily hidden my reply with the !analyze -v output.
Why are you reinitializing a remove lock here? As the crash code hints, the remove lock is a specific OS mechanism and should really only be used for preventing your device object from going away. So, you put it in your device extension, initialize it once, and then that's it. Initializing it again on IRP_MJ_CREATE would be the bug it's pointing to...
If you're trying to use remove locks to solve some other problem then maybe look at rundown the reference APIs:
Run-Down Protection - Windows drivers | Microsoft Learn
Same idea as a remove lock but more generic and they do allow for reinitialization.
Marc
August 8, 2026, 5:46pm
6
Thanks Scott. This is a legacy WDM driver I inherited which:
Calls IoCreateDevice() with Exclusive set to TRUE
Has an init flag that prevents subsequent IRP_MJ_CREATEs from reinitializing the remove lock.
But, the init flag isn't set to TRUE at the end of IRP_MJ_CREATE. It's set to TRUE after a few more initialization related private IOCTLs are issued. It's possible during development that a dev was debugging the user mode app and terminated it after calling CreateFile() but before calling the other initialization related private IOCTLs and then started a new instance of the user mode app. The remove lock is already in the device extension so I'll move its initialization to DriverEntry().
I'm curious though. Both Common::Removed and Common::IoCount in _IO_REMOVE_LOCK are zero. I disassembled IoReleaseRemoveLockAndWaitEx and it immediately sets Common::Removed to 1 and IoInitializeRemoveLockEx immediately sets Common::IoCount to 1. And the KEVENT doesn't appear to be initailized. Doesn't that mean that neither IoReleaseRemoveLockAndWaitEx nor IoInitializeRemoveLockEx had been called previous to the verifier bugcheck?
Thanks!
Verifier is doing more work here than just looking at the contents of the structure. If you walk through VerifierIoInitializeRemoveLockEx it's keeping all the remove lock address in a global AVL tree. I'd look for a previous stale instance of your device lingering or something.
Marc
August 11, 2026, 1:44pm
8
Thanks Scott for this information. I appreciate it!