I have written this audio driver which is pretty stable when playing/
recording sound. However, when I try to update the driver (via Device
Manager), it generates a Fatal System Error:


*** Fatal System Error: 0x0000000a
(0x00000000,0x00000002,0x00000001,0x80525722)

with the following stack trace:


nt!RtlpBreakWithStatusInstruction
nt!KiBugCheckDebugBreak+0x19
nt!KeBugCheck2+0xa51
nt!KiTrap0E+0x233
nt!PoRegisterDeviceForIdleDetection+0x46
nt!PoRunDownDeviceObject+0x1c
nt!IoDeleteDevice+0x4d
portcls!PnpRemoveDevice+0x8f
portcls!DispatchPnp+0xce
portcls!PcDispatchIrp+0x34
adrvr!MyPnpHandler+0x236 <<<<<<< only function that is mine
nt!IopfCallDriver+0x31
nt!IopSynchronousCall+0xb7
nt!IopRemoveDevice+0x93
nt!IopRemoveLockedDeviceNode+0x160
nt!IopDeleteLockedDeviceNode+0x34
nt!IopDeleteLockedDeviceNodes+0x3f
nt!PiProcessQueryRemoveAndEject+0x76b
nt!PiProcessTargetDeviceEvent+0x2a
nt!PiWalkDeviceList+0x122
nt!ExpWorkerThread+0x100
nt!PspSystemThreadStartup+0x34
nt!KiThreadStartup+0x16


Clearly, bugcheck analysis gives me a strong clue where to look for:
MyPnpHandler().

Well, what I do in MyPnpHandler() is basically this:


NTSTATUS YzPnpHandler(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
PAGED_CODE();

ASSERT(fdo != NULL);
ASSERT(irp != NULL);

if (OurFDO(fdo) &&
pIoStackLocation->MinorFunction == IRP_MN_REMOVE_DEVICE)
{
// stop thread and wait for its exit
}

return ( PcDispatchIrp(fdo, irp) ); // pass the IRPs on to
PortCls
}


It seems that one of (or both?) paramaters to PcDispatchIrp are
invalid by the time PcDispatchIrp is called?

But how is this possible? as seen in my code, both fdo and irp are
used successfully and *never modified* until they reach
PcDispatchIrp(fdo, irp). How is this possible?

What Could Possibly Crash PnpRemoveDevice()?

Thanks,
Don

Re: What Could Possibly Crash PnpRemoveDevice()? by Don

Don
Thu Feb 07 07:50:09 CST 2008

I don't know audio drivers, but killing the thread would never work in most
drivers, there is a 12 step process that must be done for regular PnP
drivers (see IRP_MN_REMOVE documentation) and that includes deleting the
device object and calling the lower driver.


--
Don Burn (MVP, Windows DDK)
Windows 2k/XP/2k3 Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr
Remove StopSpam to reply


<0dbell@gmail.com> wrote in message
news:e4659c0f-9c78-41b8-aca1-74eb8b425797@j20g2000hsi.googlegroups.com...
>I have written this audio driver which is pretty stable when playing/
> recording sound. However, when I try to update the driver (via Device
> Manager), it generates a Fatal System Error:
>
>
> *** Fatal System Error: 0x0000000a
> (0x00000000,0x00000002,0x00000001,0x80525722)
>
> with the following stack trace:
>
>
> nt!RtlpBreakWithStatusInstruction
> nt!KiBugCheckDebugBreak+0x19
> nt!KeBugCheck2+0xa51
> nt!KiTrap0E+0x233
> nt!PoRegisterDeviceForIdleDetection+0x46
> nt!PoRunDownDeviceObject+0x1c
> nt!IoDeleteDevice+0x4d
> portcls!PnpRemoveDevice+0x8f
> portcls!DispatchPnp+0xce
> portcls!PcDispatchIrp+0x34
> adrvr!MyPnpHandler+0x236 <<<<<<< only function that is mine
> nt!IopfCallDriver+0x31
> nt!IopSynchronousCall+0xb7
> nt!IopRemoveDevice+0x93
> nt!IopRemoveLockedDeviceNode+0x160
> nt!IopDeleteLockedDeviceNode+0x34
> nt!IopDeleteLockedDeviceNodes+0x3f
> nt!PiProcessQueryRemoveAndEject+0x76b
> nt!PiProcessTargetDeviceEvent+0x2a
> nt!PiWalkDeviceList+0x122
> nt!ExpWorkerThread+0x100
> nt!PspSystemThreadStartup+0x34
> nt!KiThreadStartup+0x16
>
>
> Clearly, bugcheck analysis gives me a strong clue where to look for:
> MyPnpHandler().
>
> Well, what I do in MyPnpHandler() is basically this:
>
>
> NTSTATUS YzPnpHandler(IN PDEVICE_OBJECT fdo, IN PIRP irp)
> {
> PAGED_CODE();
>
> ASSERT(fdo != NULL);
> ASSERT(irp != NULL);
>
> if (OurFDO(fdo) &&
> pIoStackLocation->MinorFunction == IRP_MN_REMOVE_DEVICE)
> {
> // stop thread and wait for its exit
> }
>
> return ( PcDispatchIrp(fdo, irp) ); // pass the IRPs on to
> PortCls
> }
>
>
> It seems that one of (or both?) paramaters to PcDispatchIrp are
> invalid by the time PcDispatchIrp is called?
>
> But how is this possible? as seen in my code, both fdo and irp are
> used successfully and *never modified* until they reach
> PcDispatchIrp(fdo, irp). How is this possible?
>
> What Could Possibly Crash PnpRemoveDevice()?
>
> Thanks,
> Don



Re: What Could Possibly Crash PnpRemoveDevice()? by 0dbell

0dbell
Thu Feb 07 09:29:05 CST 2008

On Feb 7, 8:50=A0am, "Don Burn" <b...@stopspam.windrvr.com> wrote:
> I don't know audio drivers, but killing the thread would never work in mos=
t
> drivers, there is a 12 step process that must be done for regular PnP
> drivers (see IRP_MN_REMOVE documentation) and that includes deleting the
> device object and calling the lower driver.
>

Don, once again thanks for your wise guidance. You are right in that
audio drivers are different than other drivers since the use (and rely
on) the PortCls subsystem to do most of the work.

In fact, until I added a system thread to help with handling CSQed
IRPs, I had no PnpHandler/DispatchPnP routine of my own - all was
taken care of automagically by the PortCls system since until then I
used only resources known to (and managed by) PortCls.

Then, when I added that thread, I discovered that I needed to stop it
before uninstalling/updating the driver, otherwise chaos will ensue. I
then replaced (in DriverEntry) the default PortCls IRP_MJ_PNP handler
with mine, not forgetting to forward all IRP_MJ_PNPs going through it
to PortCls, using PcDispatchIrp().

I thought that by identifying and handling only IRP_MN_REMOVE_DEVICE I
was "acting smart" by saving duplicate work that PortCls is doing
anyway. But thanks to your concised but right-on-target reply I
understand that there is much more to handling PNP - *if and when* I
have to add customized handling (i.e. that PortCls has no chance of
knowing about).

In particular, I at least needed to stop that thread in response to
IRP_MN_QUERY_REMOVE_DEVICE and not IRP_MN_REMOVE_DEVICE, right?

This is because by the time IRP_MN_REMOVE_DEVICE is received, the
device should have already been inactive in response to a prior
IRP_MN_QUERY_REMOVE_DEVICE.

Anyway, I think the time has come to (at least attempt to) handle all
8 minor PnP IRPs.



BTW, I just noticed in this WinDbg's crash handling:

=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D START QUOTE =3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
IRQL_NOT_LESS_OR_EQUAL (a)

Arguments:
Arg1: 00000000, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000001, value 0 =3D read operation, 1 =3D write operation
Arg4: 80525722, address which referenced memory

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

*** No owner thread found for resource 80558460
*** No owner thread found for resource 80558460
*** No owner thread found for resource 80558460

WRITE_ADDRESS: 00000000

CURRENT_IRQL: 2

FAULTING_IP:
nt!PoRegisterDeviceForIdleDetection+46
80525722 8901 mov dword ptr [ecx],eax
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D END QUOTE =3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D

Which probably means that the fault occurred at
PoRegisterDeviceForIdleDetection() - way down the call stack from
PnpRemoveDevice().

The only pointer parameter that PoRegisterDeviceForIdleDetection()
receives (since the fault is a *write access violation*) is a pointer
to the FDO. And since the write address is reported by WinDbg as
00000000 this must be the deleted FDO, right?

If so, how is this possible? Yes, the eventual job of
IRP_MN_REMOVE_DEVICE is to stop the device and **delete the FDO**, but
my handler didn't delete and FDO, it merely passed it to the venerable
PcDispatchIrp().


Thanks,
Don



Re: What Could Possibly Crash PnpRemoveDevice()? by Tim

Tim
Sat Feb 09 19:27:44 CST 2008

0dbell@gmail.com wrote:
>
>In particular, I at least needed to stop that thread in response to
>IRP_MN_QUERY_REMOVE_DEVICE and not IRP_MN_REMOVE_DEVICE, right?

That's almost certainly correct.


>This is because by the time IRP_MN_REMOVE_DEVICE is received, the
>device should have already been inactive in response to a prior
>IRP_MN_QUERY_REMOVE_DEVICE.
>
>Anyway, I think the time has come to (at least attempt to) handle all
>8 minor PnP IRPs.

There are, in fact, 23 minor PnP IRP codes. However, many of them have
specific purposes and won't interest you.

>BTW, I just noticed in this WinDbg's crash handling:
>
>================ START QUOTE ===============
>IRQL_NOT_LESS_OR_EQUAL (a)
>
>Arguments:
>Arg1: 00000000, memory referenced
>Arg2: 00000002, IRQL
>Arg3: 00000001, value 0 = read operation, 1 = write operation
>Arg4: 80525722, address which referenced memory
>...
>CURRENT_IRQL: 2
>
>FAULTING_IP:
>nt!PoRegisterDeviceForIdleDetection+46
>80525722 8901 mov dword ptr [ecx],eax
>================ END QUOTE ===============
>
>Which probably means that the fault occurred at
>PoRegisterDeviceForIdleDetection() - way down the call stack from
>PnpRemoveDevice().

Right, the last routine in the stack is at the top.

>The only pointer parameter that PoRegisterDeviceForIdleDetection()
>receives (since the fault is a *write access violation*) is a pointer
>to the FDO. And since the write address is reported by WinDbg as
>00000000 this must be the deleted FDO, right?

Not necessarily. It could be that one of the fields in the FDO had been
damaged, or in one of the structures it points to.
--
Tim Roberts, timr@probo.com
Providenza & Boekelheide, Inc.