> 1) Is there anything special about calling IoCallDriver() from within a
IRP_MJ_CREATE handler?
- Does the driver being called via IoCallDriver() actually have to be
“open?”
Nope and nope.
The I/O manager is blowing up when it tries to set the event signalling that
the I/O is complete.
f2a315d0 805021de 0000000a 00000016 0000001c nt!KiTrap0E+0x238
f2a31680 804f9f92 00000000 00000000 85f9d930 nt!KiWaitTest+0x30
f2a31694 804f4a7e f2a31858 00000000 00000000 nt!KeSetEvent+0x5a
f2a316f0 804febb5 85f9d970 f2a3173c f2a31730 nt!IopCompleteRequest+0x232
The bugcheck indicates a NULL pointer dereference (word ptr [eax+0x16]
evaluated to 0x16) at IRQL 0x1C, which is the IRQL for the dispatcher
database lock.
So, I’d say that your KEVENT is hosed. Did you ever actually call
KeInitializeEvent on it?
Regards,
-scott
–
Scott Noone
Software Engineer
OSR Open Systems Resources, Inc.
http://www.osronline.com
“Guy Townsend” wrote in message
news:xxxxx@ntdev…
> “Roddy, Mark” wrote in message
> news:xxxxx@ntdev…
> A remove lock is not a blocking lock unless called using
> IoReleaseRemoveLockAndWait. Maxim’s admonition applies to locks that
> actually block other threads. In its normal usage mode
> (IoAcquireRemoveLock/ IoReleaseRemoveLock) just increment/decrement
> counters.
>
> ---------------------------------
>
> Hmmm… In this particular case, it was IoReleaseRemoveLock() which was
> being called. Commenting out the IoAcquireRemoveLock/ IoReleaseRemoveLock
> pair certainly stopped the crash. Perhaps I should post the full scenario
> here, as it seems that this “shouldn’t happen.”
>
> But first, let me ask the dumb questions, just save time for anyone trying
> to help…
>
> 1) Is there anything special about calling IoCallDriver() from within a
> IRP_MJ_CREATE handler?
>
> 2) Does the driver being called via IoCallDriver() actually have to be
> “open?” The IRP_MJ_CREATE handler in the called driver does nothing
> anyway, and in the OSR articles about inter-driver communication it seemed
> to say that this was okay, unless I misread something… Does the I/O
> manager expect/require an IRP_MJ_CREATE call before any IRPs can be sent
> to a driver? Doesn’t seem right to me, as that would exclude PnP calls,
> the original AddDevice calls, etc… But I’m willing to be corrected…
>
> If those questions did not solve this, then here is the rest of the
> story…
>
> In a nutshell, Driver #1, in its IRP_MJ_CREATE handler, ends up calling
> IoCallDriver() with an IRP built with IoBuildDeviceIoControlRequest().
> ( I’m careful NOT to do this while there is a lock held; at least one I
> know about…)
>
> This IoCallDriver() calls Driver #2 through the via IRP_MJ_DEVICE_CONTROL
> handler. Even if I comment out the calls to the functional code, so it
> just basically completes the IRP, it still crashes when it calls
> IoReleaseRemoveLock(). This is an edited version of that code:
>
> PIO_STACK_LOCATION pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
> Status = IoAcquireRemoveLock(&pExtension->RemoveLock,NULL);
>
> // Make sure device is started…(this code removed…)
>
> // Call the appropriate routine to match the code sent
> // (removed, since crash happens the same with it commented out)
>
> pIrp->IoStatus.Status = Status;
> pIrp->IoStatus.Information =
> pIrpSp->Parameters.DeviceIoControl.InputBufferLength;
>
> IoCompleteRequest( pIrp, IO_NO_INCREMENT );
>
> IoReleaseRemoveLock( &pExtension->RemoveLock, NULL ); << Line 295
>
>
> Here is the stack trace:
>
> 0: kd> !analyze -v
>*******************************************************
> *
> *
> * Bugcheck Analysis
> *
> *
> *
> ***************************************************
>
> IRQL_NOT_LESS_OR_EQUAL (a)
> An attempt was made to access a pageable (or completely invalid) address
> at
> an
> interrupt request level (IRQL) that is too high. This is usually
> caused by drivers using improper addresses.
> If a kernel debugger is available get the stack backtrace.
> Arguments:
> Arg1: 00000016, memory referenced
> Arg2: 0000001c, IRQL
> Arg3: 00000000, value 0 = read operation, 1 = write operation
> Arg4: 805021de, address which referenced memory
>
> Debugging Details:
> ------------------
>
>
> READ_ADDRESS: 00000016
>
> CURRENT_IRQL: 1c
>
> FAULTING_IP:
> nt!KiWaitTest+30
> 805021de 6683781601 cmp word ptr [eax+0x16],0x1
>
> DEFAULT_BUCKET_ID: DRIVER_FAULT
>
> BUGCHECK_STR: 0xA
>
> LAST_CONTROL_TRANSFER: from 804f8afd to 8052a5d8
>
> IRP_ADDRESS: 85f9d930
>
> DEVICE_OBJECT: 86518a28
>
> DRIVER_OBJECT: 8658e500
>
> IMAGE_NAME: rfsbdev.sys
>
> DEBUG_FLR_IMAGE_TIMESTAMP: 445740c8
>
> MODULE_NAME: rfsbdev
>
> FAULTING_MODULE: f791b000 rfsbdev
>
> STACK_TEXT:
> f2a311a4 804f8afd 00000003 f2a31500 00000000
> nt!RtlpBreakWithStatusInstruction
> f2a311f0 804f96e8 00000003 00000016 805021de nt!KiBugCheckDebugBreak+0x19
> f2a315d0 805436d0 0000000a 00000016 0000001c nt!KeBugCheck2+0x574
> f2a315d0 805021de 0000000a 00000016 0000001c nt!KiTrap0E+0x238
> f2a31680 804f9f92 00000000 00000000 85f9d930 nt!KiWaitTest+0x30
> f2a31694 804f4a7e f2a31858 00000000 00000000 nt!KeSetEvent+0x5a
> f2a316f0 804febb5 85f9d970 f2a3173c f2a31730 nt!IopCompleteRequest+0x232
> f2a31740 806e4ef2 00000000 00000000 f2a31758 nt!KiDeliverApc+0xb3
> f2a31740 806e4ae4 00000000 00000000 f2a31758 hal!HalpApcInterrupt+0xc6
> f2a317c8 804fc1eb 85f9d970 85f9d930 00000000
> hal!KeReleaseQueuedSpinLock+0x3c
> f2a317e8 804f1518 85f9d970 00000000 00000000 nt!KeInsertQueueApc+0x6d
> f2a3181c f791e710 e1b44422 8658e500 865bf928 nt!IopfCompleteRequest+0x1d8
> f2a31834 804eeeb1 86518a28 00000000 00000000 rfsbdev!Rf_DispatchIoctl+0x8e
> [c:\mainpine\dev\rfsbdev\rf_disp.c @ 295] Last code in my
> driver. *****
> f2a31844 f43bd07d 85fa0520 865bf928 00000000 nt!IopfCallDriver+0x31
> f2a318b0 f43b6a61 865bf928 00000001 86616df0 rfserial!RFSerialReset+0x16b
> [c:\mainpine\dev\rfserial\openclos.c @ 1352]
> f2a318d4 804eeeb1 865bf870 00000000 00000000
> rfserial!SerialCreateOpen+0x31f
> [c:\mainpine\dev\rfserial\openclos.c @ 403]
> f2a318e4 f792490c 8661e770 00000000 8604e700 nt!IopfCallDriver+0x31
> f2a31904 f7925c51 865bf870 85fa0520 00000001
> Modem!WaitForLowerDriverToCompleteIrp+0x58
> f2a31a40 f7925dd4 8661e770 85fa0520 85fa0530 Modem!UniOpenStarter+0x48b
> f2a31a5c 804eeeb1 8661e6b8 85fa0520 85fa0520 Modem!UniOpen+0x50
> f2a31a6c 80581eba 865bf858 860e6fd4 f2a31c04 nt!IopfCallDriver+0x31
> f2a31b4c 805bdd08 865bf870 00000000 860e6f30 nt!IopParseDevice+0xa58
> f2a31bc4 805ba390 00000000 f2a31c04 00000040 nt!ObpLookupObjectName+0x53c
> f2a31c18 80574e37 00000000 00000000 00000001 nt!ObOpenObjectByName+0xea
> f2a31c94 805757ae 0006f74c c0100080 0006f6ec nt!IopCreateFile+0x407
> f2a31cf0 80577e78 0006f74c c0100080 0006f6ec nt!IoCreateFile+0x8e
> f2a31d30 8054060c 0006f74c c0100080 0006f6ec nt!NtCreateFile+0x30
>
> Now that I look at it again, I realize that it is actually the call to
> IoCompleteRequest which seems to be crashing. Yet removing the call to
> IoAcquireRemoveLock() certainly keeps this from happening. At one time it
> only happened in the free build, but not in checked build of this driver.
> But after some small code changes it started happening in both builds.
> Which of course is always scary…
>
> The stuff that happens toward the top of this stack list seems odd to me,
> especially that it crashes at IRQL 0x1C…
>
> I have had one thing I wondered about, though it seemed ok… I am passing
> the address of a struct allocated on the stack for the input buffer,
> though this is buffered I/O and I use sizeof() to set the size. The event
> and status block are also on the stack, and that seems quite common, so
> maybe it doesn’t matter. But I just keep trying to find something to
> explain what is happening… Below is the essentials of the code around
> the IoCallDriver() call which ends up “passing” the IRP to the driver
> where the fault occurs:
>
> irp = IoBuildDeviceIoControlRequest(
> IOCTL_RFDATA,
> targetObject,
> &ioData, / local var of type:
> struct RF_DATA /
> sizeof( RF_DATA ),
> NULL,
> 0,
> FALSE, / NOT InternalDeviceIoControl
> /
> &event, / local var /
> &ioStatus / local var */
> );
>
> if (irp == NULL)
> {
> return STATUS_INSUFFICIENT_RESOURCES;
> }
> else
> {
> status = IoCallDriver( targetObject, irp );
> if (status == STATUS_PENDING)
> {
> KeWaitForSingleObject( &event, Executive,
> KernelMode, FALSE,
> NULL );
> status = ioStatus.Status;
> }
> }
>
>
> Any insight is much appreciated. I’m starting to wonder if commenting out
> the RemoveLock stuff simply moved the problem around again… But
> something is happening…
>
> BTW, I have run this under Driver Verifier, with probably too many options
> turned on, as it took forever to do anything… and it did NOT crash.
> Neither were there any warnings at all from either driver…
>
> Thanks,
>
> Guy
>
>
>
> “Roddy, Mark” wrote in message
> news:xxxxx@ntdev…
> A remove lock is not a blocking lock unless called using
> IoReleaseRemoveLockAndWait. Maxim’s admonition applies to locks that
> actually block other threads. In its normal usage mode
> (IoAcquireRemoveLock/ IoReleaseRemoveLock) just increment/decrement
> counters.
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Guy Townsend
> Sent: Tuesday, May 02, 2006 10:02 AM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] Calling IoCompleteRequest() and IoCallDriver() with
> Remove Locks
>
> I’d like to get some advice the proper use of Remove Locks… I’ve just
> spent way too many hours debugging a problem with what was working code,
> and
> my small change caused a nasty and repeatable crash. After searching the
>
> archives here, I came across a statement which guided me to the
> solution:
>
> “Never ever call IoCallDriver or IoCompleteRequest while holding any
> kind of
> a
> lock (the only exception is filesystem’s ERESOURCE locks which guard the
>
> file
> size). This is a gross mis-design.”
>
> Maxim Shatskih, Windows DDK MVP
>
> Thanks Maxim! (and the others in that thread a couple of years back…)
>
> However, the cause of my particular problem was a RemoveLock, and
> according
> to the DDK docs, the existing use looked perfectly reasonable. (this was
> an
> existing driver I inherited, to add features to). The short description
> is
> that this was in the IOCTL handler, and it called IoCompleteRequest()
> while
> the RemoveLock was held. This seemed to work fine called from UserLand,
> but
> when I called it from another driver via IoCallDriver() it crashed when
> the
> lock was released.
>
> I notice that all the I/O routines in this driver have the RemoveLock
> protection, as the DDK advises. And that IoCompleteRequest() and
> IoCallDriver() are called in many places with the Remove Locks held. And
> it
> has been working that way for a couple of years…
>
> Can someone fill in the gaps on Maxim’s statement for me? Are there
> exceptions to that rule? Is there something special about calling from
> another driver such that the RemoveLock cannot be used (which certainly
> seems to be the case from what I have just seen…) In that case, what
> should I do about a Remove Lock in this IOCTL handler? I have not tried
> all
> the variations, and so far have only commented out the aquisition and
> release of the lock and confirmed that everything works as it is
> supposed
> to…
>
> One of these drivers is a modified version of the DDK serial.sys driver,
> and
> I notice it does not use the RemoveLock mechanism… The problem driver
> is
> for a PCI device, so I wonder if it really needs it either. Will the
> system
> actually try to remove the device with outstanding IRPs anyway?
>
> Thanks,
>
> Guy
>
>
>
>
>
>
> —
> Questions? First check the Kernel Driver FAQ at
> http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>
>
>