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

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

“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

> 1) Is there anything special about calling IoCallDriver() from within a

IRP_MJ_CREATE handler?

  1. 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
>
>
>

There may be a timing issue. If the completion APC doesn’t run
immediately (and I think it’s possible that it might not) then returning
immediately might allow you to get back into your wait in time.

I presume you’re initializing the event that you’re passing into
IoBuildADR()? In the attempt to set the event, eax (which would
probably be the address of the Event) is NULL.

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Guy Townsend
Sent: Tuesday, May 02, 2006 9:04 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] Calling IoCompleteRequest() and IoCallDriver() with
Remove Locks

“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


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

Well, this is humbling… I copied that code directly from the Microsoft KB
example, and somehow did not get the line initializing the event, and with
all the other code constructing the device name and getting the device
object, that ball did get dropped…

Thank you! And thanks to Peter Wieland as well, who noted the same thing
just 3 minutes later. Now that it’s pointed out, the stack trace makes a
whole lot more sense to me…

Guy

“Scott Noone” wrote in message news:xxxxx@ntdev…
>
>> 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?”
>
> 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
>>
>>
>>
>
>
>

> However, the cause of my particular problem was a RemoveLock, and

I don’t know why RemoveLock is needed at all. Walter Oney had a long discussion
in his book, and the conclusion was - under 2000/XP/2003 they are not needed
anyway, they are needed in Win9x only, and - voila! - in Win9x they are no-ops
:slight_smile:

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

They are needed on NT. You can get a power irp after a pnp remove and a
remlock prevents the processing of that irp properly.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S.
Shatskih
Sent: Tuesday, May 02, 2006 10:48 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Calling IoCompleteRequest() and IoCallDriver() with
Remove Locks

However, the cause of my particular problem was a RemoveLock, and

I don’t know why RemoveLock is needed at all. Walter Oney had a long
discussion
in his book, and the conclusion was - under 2000/XP/2003 they are not
needed
anyway, they are needed in Win9x only, and - voila! - in Win9x they are
no-ops
:slight_smile:

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com


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

Sometimes remove lock could be used by me for another reason:
I used it to assure the out of my code operation has been end up to
reference any resources I could release in my IRP_MN_REMOVE_DEVICE
handler, etc. the timer’s DPC opertion has begun before I call
KeCancelTimer(). This can’t prevent the DPC routine from running on
another CPU when our driver was unloaded(Is this right?)! However, it
can reduce the race condition window!


Best Regards,
hanzhu

Doron Holan дµÀ:

They are needed on NT. You can get a power irp after a pnp remove and a
remlock prevents the processing of that irp properly.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Maxim S.
Shatskih
Sent: Tuesday, May 02, 2006 10:48 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] Calling IoCompleteRequest() and IoCallDriver() with
Remove Locks

> However, the cause of my particular problem was a RemoveLock, and

I don’t know why RemoveLock is needed at all. Walter Oney had a long
discussion
in his book, and the conclusion was - under 2000/XP/2003 they are not
needed
anyway, they are needed in Win9x only, and - voila! - in Win9x they are
no-ops
:slight_smile:

Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com


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


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