IoCompleteRequest(Irp=IoAllocateIrp()) BSOD

Hi, all

We have a volume driver who create a VolDeviceObj and a fsd who create a FsdDevObj on IRP_MN_MOUNT_VOLUME, and during the mount operation VolDeviceObj->Vpb->DeviceObject is set to FsdDevObj.

Our purpose is to dismount a drive(ex: Z:) by a FSCTL_DISMOUNT_VOLUME send
by an user process(named: APP).
The way of sending a FSCTL_DISMOUNT_VOLUME directly to fsd by APP is ok,
and works well.

But now it has been decided to do it in another way:
1). APP send an IOCTL to volume driver;
2). On receiving the IOCTL from APP, the volume driver send an FSCTL_DISMOUNT_VOLUME to fsd.
After fsd have “successfully” processed the FSCTL_DISMOUNT_VOLUME in FsdFileSystemControl,it call IoCompleteRequest(), then BSOD occured.

In this process,the volume driver build a new stack,and it’s on the top of stack,
and fsd is just under it, right(— Q1)?
Is it a normal way and is suggested to do so?

Thanks in advance!

And following is the details of buiuding my own IRP in volume driver and send it to fsd.

// Open the drive and the FileObject we need
ZwCreateFile(L"\Z:\");
ObReferenceObjectByHandle(FileObject);

Irp = NULL;
// Or should be IoAllocateIrp(DeviceObject->StackSize +1 ) ? (— Q2)
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

IrpSp = IoGetNextIrpStackLocation(Irp);
//Setup Irpsp and Irp

Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘EloV’);

KeInitializeEvent(Event, NotificationEvent, FALSE);
IoSetCompletionRoutine(
Irp,
DismountIoctlComplete,
Event,
TRUE,
TRUE,
TRUE
);

Status = IoCallDriver(DeviceObject, Irp);
KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
ExFreePoolWithTag(Event, ‘EloV’);
Event = NULL;
IoFreeIrp(Irp);

completion routine:
DismountIoctlComplete()
{
KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
// Or should return STATUS_SUCCESS, or both of them are ok here? (— Q3)
return STATUS_MORE_PROCESSING_REQUIRED;
}

Update:

I moved IoFreeIrp(Irp) into the completion routine and problem got solved.

completion routine:
DismountIoctlComplete()
{
IoFreeIrp(Irp);
KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
// Or should return STATUS_SUCCESS, or both of them are ok? (Q3)
return STATUS_MORE_PROCESSING_REQUIRED;
}

But why should IoFreeIrp() only be called in completion routine?

And my upper 3 questions(Q1~Q3)?

Thanks!

Q1. No it’s not. But it can receive this request later if this is
VolumeObject.
Q2. no it should not
Q3. To answer for this question it’s necessary you post BSOD. But likely
you get BSOD because the DeviceObject which get IOCTL from APP is
VolumeObject which receive rest usual requests for this type of device. Am
i right?

2013/5/30

> Update:
>
> I moved IoFreeIrp(Irp) into the completion routine and problem got
> solved.
>
> completion routine:
> DismountIoctlComplete()
> {
> IoFreeIrp(Irp);
> KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
> // Or should return STATUS_SUCCESS, or both of them are ok? (Q3)
> return STATUS_MORE_PROCESSING_REQUIRED;
> }
>
>
> But why should IoFreeIrp() only be called in completion routine?
>
> And my upper 3 questions(Q1~Q3)?
>
> Thanks!
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Hi anatoly,

Thanks for your quick reply.

Q1. No it’s not. But it can receive this request later if this is
VolumeObject.
Lower volumeObject send a IRP to upper fsdDeviceObject, the IRP crossed stack, right?
Because I think the normal way is upper fsdDeviceObject to lower volumeObject, at least the data read/write process are processed in this way.

Q3. To answer for this question it’s necessary you post BSOD. But likely
you get BSOD because the DeviceObject which get IOCTL from APP is
VolumeObject which receive rest usual requests for this type of device. Am
i right?
Sorry, but I didn’t get you clearly.

Sorry for my English. I’ll try to explain.

I meant i want to see BSOD you get. And i meant what you probably get this
BSOD because of lower device object sends request to upper device object.
For this reason i need to see the BSOD at least to answer for your
question. If you do everything correctly, no matter when you call IoFreeIrp.

Because I think the normal way is upper fsdDeviceObject to lower
volumeObject, at least the data read/write process are processed in this
way.
Yes it is. But when APP sends request to FSD, the fsdDeviceObject get this
request first.

2013/5/30

> Hi anatoly,
>
> Thanks for your quick reply.
>
> >Q1. No it’s not. But it can receive this request later if this is
> VolumeObject.
> Lower volumeObject send a IRP to upper fsdDeviceObject, the IRP crossed
> stack, right?
> Because I think the normal way is upper fsdDeviceObject to lower
> volumeObject, at least the data read/write process are processed in this
> way.
>
> >Q3. To answer for this question it’s necessary you post BSOD. But likely
> you get BSOD because the DeviceObject which get IOCTL from APP is
> VolumeObject which receive rest usual requests for this type of device. Am
> i right?
> Sorry, but I didn’t get you clearly.
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

In my practice(moving IoFreeIrp to completion routine), it seems that lower device object sends request to upper device object is ok, and it work well.
So I’m look for the theory to support this kind of method. It’d better from Microsoft.

For causes of the BSOD, I have different opinion, and I think that where to put the “IoFreeIrp” does matter.

Following is the original DUMP analysis:
Myfsd and My_volume is the fsd and volume driver I mentioned above.

The OsrOnline web is not so kind for X64 system dump to display, for the 64 bits pointer alway get displayed in 2 lines.

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: 0000000000000088, memory referenced
Arg2: 0000000000000002, IRQL
Arg3: 0000000000000001, bitfield :
bit 0 : value 0 = read operation, 1 = write operation
bit 3 : value 0 = not an execute operation, 1 = execute operation (only on chips which support this level of status)
Arg4: fffff80003a5312e, address which referenced memory

Debugging Details:

MODULE_NAME: MyFsd

FAULTING_MODULE: fffff80003a04000 nt

DEBUG_FLR_IMAGE_TIMESTAMP: 51a6cb63

WRITE_ADDRESS: unable to get nt!MmSpecialPoolStart
unable to get nt!MmSpecialPoolEnd
unable to get nt!MmPoolCodeStart
unable to get nt!MmPoolCodeEnd
0000000000000088

CURRENT_IRQL: 0

FAULTING_IP:
nt!KeInsertQueueApc+42
fffff800`03a5312e f0480fbaab8800000000 lock bts qword ptr [rbx+88h],0

DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT

BUGCHECK_STR: 0xA

LAST_CONTROL_TRANSFER: from fffff80003b6a672 to fffff80003a6b8e1

STACK_TEXT:
fffff880061f37a8 fffff80003b6a672 : 0000000000000088 fffffa8006576760 0000000000000065 fffff80003ab1910 : nt!DbgBreakPointWithStatus+0x1
fffff880061f37b0 fffff80003b6b45e : 0000000000000003 0000000000000000 fffff80003aae4d0 000000000000000a : nt!HeadlessDispatch+0x192
fffff880061f3810 fffff80003a73984 : 0000000000000000 fffff88000000000 0000000000000000 fffff80003af1b52 : nt!KeEnterKernelDebugger+0x76e
fffff880061f3ee0 fffff80003a72de9 : 000000000000000a 0000000000000088 0000000000000002 0000000000000001 : nt!KeBugCheckEx+0x104
fffff880061f3f20 fffff80003a71a60 : 0000000000000000 0000000000000000 0000000000000000 0000000000000001 : nt!KeSynchronizeExecution+0x3d59
fffff880061f4060 fffff80003a5312e : 0000000000000000 0000000000000000 fffffa80043aff2b fffff88002e896dd : nt!KeSynchronizeExecution+0x29d0
fffff880061f41f0 fffff80003a76709 : 0000000000000000 00000000a000000c 0000000000000000 0000000000000000 : nt!KeInsertQueueApc+0x42
fffff880061f4250 fffff88001d97bba : fffffa80051c7870 fffff88001d97a01 0000000000000010 0000000000000000 : nt!memset+0xc79
fffff880061f4340 fffff88001d94652 : 0000000000000000 fffffa80043afe10 fffffa8000000000 fffff880061f43c0 : MyFsd!MyCompleteRequest_Real+0xea
fffff880061f4380 fffff88001d93468 : fffffa80051c7870 fffffa80043afe10 0000000000000000 0000000000000000 : MyFsd!MyLockVolume+0x572
fffff880061f4410 fffff88001d8f7e4 : fffffa80051c7870 fffffa80043afe10 fffffa80043afe10 fffff80003c02888 : MyFsd!MyUserFsCtrl+0x288
fffff880061f4480 fffff88001d8f435 : fffffa80051c7870 fffffa80043afe10 fffffa80043afe10 fffffa8000000001 : MyFsd!MyCommonFileSystemControl+0x2b4
fffff880061f44f0 fffff88002e89a32 : fffffa8006eef040 fffffa80043afe10 fffffa80043480d0 0000000000000701 : MyFsd!MyFsdFileSystemControl+0x1b5
fffff880061f4550 fffff88002e8abea : fffffa8006dbd1a0 fffffa8006eef040 0000000000060006 fffff8a004362240 : My_volume!DismountVolume+0x342
fffff880061f4680 fffff88002e82beb : fffffa8005eeb060 fffffa80065b3260 fffff8a00003dea0 fffff8a00a1d7d24 : My_volume!Volmgr_DeviceControl+0xd6a
fffff880061f4890 fffff80003cdb068 : fffffa8005eeb060 fffffa80065b3260 0000000000000001 0000000020206f49 : My_volume!LDiskDeviceControl+0x7b
fffff880061f48d0 fffff80003cd9c81 : 0000000000000000 fffff880061f4c60 fffffa80065b3260 fffff88001446a01 : nt!IoBuildSynchronousFsdRequest+0x168
fffff880061f4910 fffff880014226af : fffffa8006ee2c90 fffffa8006ede070 fffffa80065b3260 0000000000000000 : nt!PsRevertToSelf+0x6b1
fffff880061f4970 fffff80003d8a8f7 : fffffa8006ede070 fffff880061f4c60 fffffa80065b3408 fffffa80065b3260 : fltmgr+0x16af
fffff880061f49d0 fffff80003d8b156 : 0000000000000401 0000000000000000 0000000000000001 0000000000000000 : nt!NtMapViewOfSection+0x25a7
fffff880061f4b00 fffff80003a72ad3 : 0000000000000401 fffff960001029aa 0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56
fffff880061f4b70 0000000072db2dd9 : 0000000072db2932 0000000074e672af 0000000072e20023 0000000000000401 : nt!KeSynchronizeExecution+0x3a43
000000000008ebf8 0000000072db2932 : 0000000074e672af 0000000072e20023 0000000000000401 00000000001880f8 : wow64cpu!TurboDispatchJumpAddressEnd+0x690
000000000008ec00 0000000074e672af : 0000000072e20023 0000000000000401 00000000001880f8 000000000008ec50 : wow64cpu!TurboDispatchJumpAddressEnd+0x1e9
000000000008ec08 0000000072e20023 : 0000000000000401 00000000001880f8 000000000008ec50 0000000000073018 : KERNELBASE!IsNLSDefinedString+0x7db
000000000008ec10 0000000000000401 : 00000000001880f8 000000000008ec50 0000000000073018 0000000002266f48 : wow64+0x23
000000000008ec18 00000000001880f8 : 000000000008ec50 0000000000073018 0000000002266f48 00000000000000a0 : 0x401
000000000008ec20 000000000008ec50 : 0000000000073018 0000000002266f48 00000000000000a0 0000000000000000 : 0x1880f8
000000000008ec28 0000000000073018 : 0000000002266f48 00000000000000a0 0000000000000000 0000000000000000 : 0x8ec50
000000000008ec30 0000000002266f48 : 00000000000000a0 0000000000000000 0000000000000000 000000000018888c : 0x73018
000000000008ec38 00000000000000a0 : 0000000000000000 0000000000000000 000000000018888c 0000000000a4f928 : 0x2266f48
000000000008ec40 0000000000000000 : 0000000000000000 000000000018888c 0000000000a4f928 000000000018888c : 0xa0

STACK_COMMAND: kb

FOLLOWUP_IP:
MyFsd!MyCompleteRequest_Real+ea [\My_fsd\Mydata.c @ 709]
fffff880`01d97bba 4883c438 add rsp,38h

FAULTING_SOURCE_CODE:
705: IoCompleteRequest( Irp, IO_DISK_INCREMENT );
706: }
707:
708: return;

709: }
710:
711: BOOLEAN
712: MyIsIrpTopLevel (
713: IN PIRP Irp
714: )

SYMBOL_STACK_INDEX: 8

SYMBOL_NAME: MyFsd!MyCompleteRequest_Real+ea

FOLLOWUP_NAME: MachineOwner

IMAGE_NAME: MyFsd.sys

BUCKET_ID: WRONG_SYMBOLS

Followup: MachineOwner

> In my practice(moving IoFreeIrp to completion routine), it seems that
lower device object sends request to upper device object is ok, and it work
well.
it’s ok while you send requests which you’ll just pass through without
processing which results in sending new request.

What you return from DismountIoctlComplete when you get BSOD? STATUS_SUCCEE
or STATUS_MORE_PROCESSING_
REQUIRED?

What you send dismount request from IOCTL request for? To guarantee
fsdVolumeObject get this request first?

2013/5/30

> In my practice(moving IoFreeIrp to completion routine), it seems that
> lower device object sends request to upper device object is ok, and it work
> well.
> So I’m look for the theory to support this kind of method. It’d better
> from Microsoft.
>
> For causes of the BSOD, I have different opinion, and I think that where
> to put the “IoFreeIrp” does matter.
>
>
>
>
> Following is the original DUMP analysis:
> Myfsd and My_volume is the fsd and volume driver I mentioned above.
>
> The OsrOnline web is not so kind for X64 system dump to display, for the
> 64 bits pointer alway get displayed in 2 lines.
>
> 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: 0000000000000088, memory referenced
> Arg2: 0000000000000002, IRQL
> Arg3: 0000000000000001, bitfield :
> bit 0 : value 0 = read operation, 1 = write operation
> bit 3 : value 0 = not an execute operation, 1 = execute operation
> (only on chips which support this level of status)
> Arg4: fffff80003a5312e, address which referenced memory
>
> Debugging Details:
> ------------------
>
>
> MODULE_NAME: MyFsd
>
> FAULTING_MODULE: fffff80003a04000 nt
>
> DEBUG_FLR_IMAGE_TIMESTAMP: 51a6cb63
>
> WRITE_ADDRESS: unable to get nt!MmSpecialPoolStart
> unable to get nt!MmSpecialPoolEnd
> unable to get nt!MmPoolCodeStart
> unable to get nt!MmPoolCodeEnd
> 0000000000000088
>
> CURRENT_IRQL: 0
>
> FAULTING_IP:
> nt!KeInsertQueueApc+42
> fffff80003a5312e f0480fbaab8800000000 lock bts qword ptr [rbx+88h],0<br>&gt;<br>&gt; DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT<br>&gt;<br>&gt; BUGCHECK_STR: 0xA<br>&gt;<br>&gt; LAST_CONTROL_TRANSFER: from fffff80003b6a672 to fffff80003a6b8e1<br>&gt;<br>&gt; STACK_TEXT:<br>&gt; fffff880061f37a8 fffff80003b6a672 : 0000000000000088 fffffa8006576760<br>&gt; 0000000000000065 fffff80003ab1910 : nt!DbgBreakPointWithStatus+0x1<br>&gt; fffff880061f37b0 fffff80003b6b45e : 0000000000000003 0000000000000000<br>&gt; fffff80003aae4d0 000000000000000a : nt!HeadlessDispatch+0x192<br>&gt; fffff880061f3810 fffff80003a73984 : 0000000000000000 fffff88000000000<br>&gt; 0000000000000000 fffff80003af1b52 : nt!KeEnterKernelDebugger+0x76e<br>&gt; fffff880061f3ee0 fffff80003a72de9 : 000000000000000a 0000000000000088<br>&gt; 0000000000000002 0000000000000001 : nt!KeBugCheckEx+0x104<br>&gt; fffff880061f3f20 fffff80003a71a60 : 0000000000000000 0000000000000000<br>&gt; 0000000000000000 0000000000000001 : nt!KeSynchronizeExecution+0x3d59<br>&gt; fffff880061f4060 fffff80003a5312e : 0000000000000000 0000000000000000<br>&gt; fffffa80043aff2b fffff88002e896dd : nt!KeSynchronizeExecution+0x29d0<br>&gt; fffff880061f41f0 fffff80003a76709 : 0000000000000000 00000000a000000c<br>&gt; 0000000000000000 0000000000000000 : nt!KeInsertQueueApc+0x42<br>&gt; fffff880061f4250 fffff88001d97bba : fffffa80051c7870 fffff88001d97a01<br>&gt; 0000000000000010 0000000000000000 : nt!memset+0xc79<br>&gt; fffff880061f4340 fffff88001d94652 : 0000000000000000 fffffa80043afe10<br>&gt; fffffa8000000000 fffff880061f43c0 : MyFsd!MyCompleteRequest_Real+0xea<br>&gt; fffff880061f4380 fffff88001d93468 : fffffa80051c7870 fffffa80043afe10<br>&gt; 0000000000000000 0000000000000000 : MyFsd!MyLockVolume+0x572<br>&gt; fffff880061f4410 fffff88001d8f7e4 : fffffa80051c7870 fffffa80043afe10<br>&gt; fffffa80043afe10 fffff80003c02888 : MyFsd!MyUserFsCtrl+0x288<br>&gt; fffff880061f4480 fffff88001d8f435 : fffffa80051c7870 fffffa80043afe10<br>&gt; fffffa80043afe10 fffffa8000000001 : MyFsd!MyCommonFileSystemControl+0x2b4<br>&gt; fffff880061f44f0 fffff88002e89a32 : fffffa8006eef040 fffffa80043afe10<br>&gt; fffffa80043480d0 0000000000000701 : MyFsd!MyFsdFileSystemControl+0x1b5<br>&gt; fffff880061f4550 fffff88002e8abea : fffffa8006dbd1a0 fffffa8006eef040<br>&gt; 0000000000060006 fffff8a004362240 : My_volume!DismountVolume+0x342<br>&gt; fffff880061f4680 fffff88002e82beb : fffffa8005eeb060 fffffa80065b3260<br>&gt; fffff8a00003dea0 fffff8a00a1d7d24 : My_volume!Volmgr_DeviceControl+0xd6a<br>&gt; fffff880061f4890 fffff80003cdb068 : fffffa8005eeb060 fffffa80065b3260<br>&gt; 0000000000000001 0000000020206f49 : My_volume!LDiskDeviceControl+0x7b<br>&gt; fffff880061f48d0 fffff80003cd9c81 : 0000000000000000 fffff880061f4c60<br>&gt; fffffa80065b3260 fffff88001446a01 : nt!IoBuildSynchronousFsdRequest+0x168<br>&gt; fffff880061f4910 fffff880014226af : fffffa8006ee2c90 fffffa8006ede070<br>&gt; fffffa80065b3260 0000000000000000 : nt!PsRevertToSelf+0x6b1<br>&gt; fffff880061f4970 fffff80003d8a8f7 : fffffa8006ede070 fffff880061f4c60<br>&gt; fffffa80065b3408 fffffa80065b3260 : fltmgr+0x16af<br>&gt; fffff880061f49d0 fffff80003d8b156 : 0000000000000401 0000000000000000<br>&gt; 0000000000000001 0000000000000000 : nt!NtMapViewOfSection+0x25a7<br>&gt; fffff880061f4b00 fffff80003a72ad3 : 0000000000000401 fffff960001029aa<br>&gt; 0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56<br>&gt; fffff880061f4b70 0000000072db2dd9 : 0000000072db2932 0000000074e672af<br>&gt; 0000000072e20023 0000000000000401 : nt!KeSynchronizeExecution+0x3a43<br>&gt; 000000000008ebf8 0000000072db2932 : 0000000074e672af 0000000072e20023<br>&gt; 0000000000000401 00000000001880f8 :<br>&gt; wow64cpu!TurboDispatchJumpAddressEnd+0x690<br>&gt; 000000000008ec00 0000000074e672af : 0000000072e20023 0000000000000401<br>&gt; 00000000001880f8 000000000008ec50 :<br>&gt; wow64cpu!TurboDispatchJumpAddressEnd+0x1e9<br>&gt; 000000000008ec08 0000000072e20023 : 0000000000000401 00000000001880f8<br>&gt; 000000000008ec50 0000000000073018 : KERNELBASE!IsNLSDefinedString+0x7db<br>&gt; 000000000008ec10 0000000000000401 : 00000000001880f8 000000000008ec50<br>&gt; 0000000000073018 0000000002266f48 : wow64+0x23<br>&gt; 000000000008ec18 00000000001880f8 : 000000000008ec50 0000000000073018<br>&gt; 0000000002266f48 00000000000000a0 : 0x401<br>&gt; 000000000008ec20 000000000008ec50 : 0000000000073018 0000000002266f48<br>&gt; 00000000000000a0 0000000000000000 : 0x1880f8<br>&gt; 000000000008ec28 0000000000073018 : 0000000002266f48 00000000000000a0<br>&gt; 0000000000000000 0000000000000000 : 0x8ec50<br>&gt; 000000000008ec30 0000000002266f48 : 00000000000000a0 0000000000000000<br>&gt; 0000000000000000 000000000018888c : 0x73018<br>&gt; 000000000008ec38 00000000000000a0 : 0000000000000000 0000000000000000<br>&gt; 000000000018888c 0000000000a4f928 : 0x2266f48<br>&gt; 000000000008ec40 0000000000000000 : 0000000000000000 000000000018888c<br>&gt; 0000000000a4f928 000000000018888c : 0xa0<br>&gt;<br>&gt;<br>&gt; STACK_COMMAND: kb<br>&gt;<br>&gt; FOLLOWUP_IP:<br>&gt; MyFsd!MyCompleteRequest_Real+ea [\My_fsd\Mydata.c @ 709]<br>&gt; fffff88001d97bba 4883c438 add rsp,38h
>
> FAULTING_SOURCE_CODE:
> 705: IoCompleteRequest( Irp, IO_DISK_INCREMENT );
> 706: }
> 707:
> 708: return;
> > 709: }
> 710:
> 711: BOOLEAN
> 712: MyIsIrpTopLevel (
> 713: IN PIRP Irp
> 714: )
>
>
> SYMBOL_STACK_INDEX: 8
>
> SYMBOL_NAME: MyFsd!MyCompleteRequest_Real+ea
>
> FOLLOWUP_NAME: MachineOwner
>
> IMAGE_NAME: MyFsd.sys
>
> BUCKET_ID: WRONG_SYMBOLS
>
> Followup: MachineOwner
> ---------
>
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

Minor point: you do not need to allocate the KEVENT on the heap. You can
just declare it as a local variable! While passing addreses of locals
across thread boundaries is generally a Really Bad Thing To Do, in this
case you are guaranteed the stack will remain in place because of the
WaitFor.

Major Point: What if IoCallDriver returns any code other than
STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
can never arise.

The code, more correctly, should be
status = IoCallDriver(…);
if(status==STATUS_PENDING)
{
WaitFor(…);
status = Irp->IoStatus.Status;
delete the IRP
}
else
{
delete the IRP
}
return status.

Note this can’t work if you delete the IRP in the completion routine, so
you should figure out why the BSOD.

Note that the ONLY valid return code from your completion routine is
STATUS_MORE_PROCESSING_REQUIRED. If you return ANY other value, you are
guaranteed a BSOD. You did not post the !analyze -v output. If you return
any value other than SMPR then the completion walker will try to find the
next-higher completion routine, which does not exist. BSOD.
joe

Hi, all

We have a volume driver who create a VolDeviceObj and a fsd who create a
FsdDevObj on IRP_MN_MOUNT_VOLUME, and during the mount operation
VolDeviceObj->Vpb->DeviceObject is set to FsdDevObj.

Our purpose is to dismount a drive(ex: Z:) by a FSCTL_DISMOUNT_VOLUME send
by an user process(named: APP).
The way of sending a FSCTL_DISMOUNT_VOLUME directly to fsd by APP is ok,
and works well.

But now it has been decided to do it in another way:
1). APP send an IOCTL to volume driver;
2). On receiving the IOCTL from APP, the volume driver send an
FSCTL_DISMOUNT_VOLUME to fsd.
After fsd have “successfully” processed the FSCTL_DISMOUNT_VOLUME in
FsdFileSystemControl,it call IoCompleteRequest(), then BSOD occured.

In this process,the volume driver build a new stack,and it’s on the top of
stack,
and fsd is just under it, right(— Q1)?
Is it a normal way and is suggested to do so?

Thanks in advance!

And following is the details of buiuding my own IRP in volume driver and
send it to fsd.

// Open the drive and the FileObject we need
ZwCreateFile(L"\Z:\");
ObReferenceObjectByHandle(FileObject);

Irp = NULL;
// Or should be IoAllocateIrp(DeviceObject->StackSize +1 ) ? (— Q2)
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);

IrpSp = IoGetNextIrpStackLocation(Irp);
//Setup Irpsp and Irp

Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘EloV’);

KeInitializeEvent(Event, NotificationEvent, FALSE);
IoSetCompletionRoutine(
Irp,
DismountIoctlComplete,
Event,
TRUE,
TRUE,
TRUE
);

Status = IoCallDriver(DeviceObject, Irp);
KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
ExFreePoolWithTag(Event, ‘EloV’);
Event = NULL;
IoFreeIrp(Irp);

completion routine:
DismountIoctlComplete()
{
KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
// Or should return STATUS_SUCCESS, or both of them are ok here? (—
Q3)
return STATUS_MORE_PROCESSING_REQUIRED;
}


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I’m playing “catch-up” after a week that sucked up most of my free time.
So I see you DID post the !analyze -v output. Unfortunately, you dd not
post the code of the function that faulted; the last three lines are
particularly useless. At first glance, I’d say that you are probably
writing too much data into a local array, which will cause the reurn
instruction to fail.

Note also that a cndition that references the ‘return’ line may indicate
That it is the /previous/ statement that failed. In this case, rbx is 0,
which means you passed in a NULL pointer somewhere.

We don’t see what led to this point, so it is hard to guess what has gone
wrong.

Also, I don’t see tbe registers displayed in this dump. Is this some new
misfeature?
joe

> In my practice(moving IoFreeIrp to completion routine), it seems that
lower device object sends request to upper device object is ok, and it
work
well.
it’s ok while you send requests which you’ll just pass through without
processing which results in sending new request.

What you return from DismountIoctlComplete when you get BSOD?
STATUS_SUCCEE
or STATUS_MORE_PROCESSING_
REQUIRED?

What you send dismount request from IOCTL request for? To guarantee
fsdVolumeObject get this request first?

2013/5/30
>
>> In my practice(moving IoFreeIrp to completion routine), it seems that
>> lower device object sends request to upper device object is ok, and it
>> work
>> well.
>> So I’m look for the theory to support this kind of method. It’d better
>> from Microsoft.
>>
>> For causes of the BSOD, I have different opinion, and I think that where
>> to put the “IoFreeIrp” does matter.
>>
>>
>>
>>
>> Following is the original DUMP analysis:
>> Myfsd and My_volume is the fsd and volume driver I mentioned above.
>>
>> The OsrOnline web is not so kind for X64 system dump to display, for the
>> 64 bits pointer alway get displayed in 2 lines.
>>
>> 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: 0000000000000088, memory referenced
>> Arg2: 0000000000000002, IRQL
>> Arg3: 0000000000000001, bitfield :
>> bit 0 : value 0 = read operation, 1 = write operation
>> bit 3 : value 0 = not an execute operation, 1 = execute
>> operation
>> (only on chips which support this level of status)
>> Arg4: fffff80003a5312e, address which referenced memory
>>
>> Debugging Details:
>> ------------------
>>
>>
>> MODULE_NAME: MyFsd
>>
>> FAULTING_MODULE: fffff80003a04000 nt
>>
>> DEBUG_FLR_IMAGE_TIMESTAMP: 51a6cb63
>>
>> WRITE_ADDRESS: unable to get nt!MmSpecialPoolStart
>> unable to get nt!MmSpecialPoolEnd
>> unable to get nt!MmPoolCodeStart
>> unable to get nt!MmPoolCodeEnd
>> 0000000000000088
>>
>> CURRENT_IRQL: 0
>>
>> FAULTING_IP:
>> nt!KeInsertQueueApc+42
>> fffff80003a5312e f0480fbaab8800000000 lock bts qword ptr [rbx+88h],0<br>&gt;&gt;<br>&gt;&gt; DEFAULT_BUCKET_ID: VISTA_DRIVER_FAULT<br>&gt;&gt;<br>&gt;&gt; BUGCHECK_STR: 0xA<br>&gt;&gt;<br>&gt;&gt; LAST_CONTROL_TRANSFER: from fffff80003b6a672 to fffff80003a6b8e1<br>&gt;&gt;<br>&gt;&gt; STACK_TEXT:<br>&gt;&gt; fffff880061f37a8 fffff80003b6a672 : 0000000000000088
>> fffffa8006576760<br>&gt;&gt; 0000000000000065 fffff80003ab1910 : nt!DbgBreakPointWithStatus+0x1<br>&gt;&gt; fffff880061f37b0 fffff80003b6b45e : 0000000000000003
>> 0000000000000000<br>&gt;&gt; fffff80003aae4d0 000000000000000a : nt!HeadlessDispatch+0x192<br>&gt;&gt; fffff880061f3810 fffff80003a73984 : 0000000000000000
>> fffff88000000000<br>&gt;&gt; 0000000000000000 fffff80003af1b52 : nt!KeEnterKernelDebugger+0x76e<br>&gt;&gt; fffff880061f3ee0 fffff80003a72de9 : 000000000000000a
>> 0000000000000088<br>&gt;&gt; 0000000000000002 0000000000000001 : nt!KeBugCheckEx+0x104<br>&gt;&gt; fffff880061f3f20 fffff80003a71a60 : 0000000000000000
>> 0000000000000000<br>&gt;&gt; 0000000000000000 0000000000000001 : nt!KeSynchronizeExecution+0x3d59<br>&gt;&gt; fffff880061f4060 fffff80003a5312e : 0000000000000000
>> 0000000000000000<br>&gt;&gt; fffffa80043aff2b fffff88002e896dd : nt!KeSynchronizeExecution+0x29d0<br>&gt;&gt; fffff880061f41f0 fffff80003a76709 : 0000000000000000
>> 00000000a000000c<br>&gt;&gt; 0000000000000000 0000000000000000 : nt!KeInsertQueueApc+0x42<br>&gt;&gt; fffff880061f4250 fffff88001d97bba : fffffa80051c7870
>> fffff88001d97a01<br>&gt;&gt; 0000000000000010 0000000000000000 : nt!memset+0xc79<br>&gt;&gt; fffff880061f4340 fffff88001d94652 : 0000000000000000
>> fffffa80043afe10<br>&gt;&gt; fffffa8000000000 fffff880061f43c0 : MyFsd!MyCompleteRequest_Real+0xea<br>&gt;&gt; fffff880061f4380 fffff88001d93468 : fffffa80051c7870
>> fffffa80043afe10<br>&gt;&gt; 0000000000000000 0000000000000000 : MyFsd!MyLockVolume+0x572<br>&gt;&gt; fffff880061f4410 fffff88001d8f7e4 : fffffa80051c7870
>> fffffa80043afe10<br>&gt;&gt; fffffa80043afe10 fffff80003c02888 : MyFsd!MyUserFsCtrl+0x288<br>&gt;&gt; fffff880061f4480 fffff88001d8f435 : fffffa80051c7870
>> fffffa80043afe10<br>&gt;&gt; fffffa80043afe10 fffffa8000000001 :<br>&gt;&gt; MyFsd!MyCommonFileSystemControl+0x2b4<br>&gt;&gt; fffff880061f44f0 fffff88002e89a32 : fffffa8006eef040
>> fffffa80043afe10<br>&gt;&gt; fffffa80043480d0 0000000000000701 : MyFsd!MyFsdFileSystemControl+0x1b5<br>&gt;&gt; fffff880061f4550 fffff88002e8abea : fffffa8006dbd1a0
>> fffffa8006eef040<br>&gt;&gt; 0000000000060006 fffff8a004362240 : My_volume!DismountVolume+0x342<br>&gt;&gt; fffff880061f4680 fffff88002e82beb : fffffa8005eeb060
>> fffffa80065b3260<br>&gt;&gt; fffff8a00003dea0 fffff8a00a1d7d24 :<br>&gt;&gt; My_volume!Volmgr_DeviceControl+0xd6a<br>&gt;&gt; fffff880061f4890 fffff80003cdb068 : fffffa8005eeb060
>> fffffa80065b3260<br>&gt;&gt; 0000000000000001 0000000020206f49 : My_volume!LDiskDeviceControl+0x7b<br>&gt;&gt; fffff880061f48d0 fffff80003cd9c81 : 0000000000000000
>> fffff880061f4c60<br>&gt;&gt; fffffa80065b3260 fffff88001446a01 :<br>&gt;&gt; nt!IoBuildSynchronousFsdRequest+0x168<br>&gt;&gt; fffff880061f4910 fffff880014226af : fffffa8006ee2c90
>> fffffa8006ede070<br>&gt;&gt; fffffa80065b3260 0000000000000000 : nt!PsRevertToSelf+0x6b1<br>&gt;&gt; fffff880061f4970 fffff80003d8a8f7 : fffffa8006ede070
>> fffff880061f4c60<br>&gt;&gt; fffffa80065b3408 fffffa80065b3260 : fltmgr+0x16af<br>&gt;&gt; fffff880061f49d0 fffff80003d8b156 : 0000000000000401
>> 0000000000000000<br>&gt;&gt; 0000000000000001 0000000000000000 : nt!NtMapViewOfSection+0x25a7<br>&gt;&gt; fffff880061f4b00 fffff80003a72ad3 : 0000000000000401
>> fffff960001029aa<br>&gt;&gt; 0000000000000000 0000000000000000 : nt!NtDeviceIoControlFile+0x56<br>&gt;&gt; fffff880061f4b70 0000000072db2dd9 : 0000000072db2932
>> 0000000074e672af<br>&gt;&gt; 0000000072e20023 0000000000000401 : nt!KeSynchronizeExecution+0x3a43<br>&gt;&gt; 000000000008ebf8 0000000072db2932 : 0000000074e672af
>> 0000000072e20023<br>&gt;&gt; 0000000000000401 00000000001880f8 :<br>&gt;&gt; wow64cpu!TurboDispatchJumpAddressEnd+0x690<br>&gt;&gt; 000000000008ec00 0000000074e672af : 0000000072e20023
>> 0000000000000401<br>&gt;&gt; 00000000001880f8 000000000008ec50 :<br>&gt;&gt; wow64cpu!TurboDispatchJumpAddressEnd+0x1e9<br>&gt;&gt; 000000000008ec08 0000000072e20023 : 0000000000000401
>> 00000000001880f8<br>&gt;&gt; 000000000008ec50 0000000000073018 :<br>&gt;&gt; KERNELBASE!IsNLSDefinedString+0x7db<br>&gt;&gt; 000000000008ec10 0000000000000401 : 00000000001880f8
>> 000000000008ec50<br>&gt;&gt; 0000000000073018 0000000002266f48 : wow64+0x23<br>&gt;&gt; 000000000008ec18 00000000001880f8 : 000000000008ec50
>> 0000000000073018<br>&gt;&gt; 0000000002266f48 00000000000000a0 : 0x401<br>&gt;&gt; 000000000008ec20 000000000008ec50 : 0000000000073018
>> 0000000002266f48<br>&gt;&gt; 00000000000000a0 0000000000000000 : 0x1880f8<br>&gt;&gt; 000000000008ec28 0000000000073018 : 0000000002266f48
>> 00000000000000a0<br>&gt;&gt; 0000000000000000 0000000000000000 : 0x8ec50<br>&gt;&gt; 000000000008ec30 0000000002266f48 : 00000000000000a0
>> 0000000000000000<br>&gt;&gt; 0000000000000000 000000000018888c : 0x73018<br>&gt;&gt; 000000000008ec38 00000000000000a0 : 0000000000000000
>> 0000000000000000<br>&gt;&gt; 000000000018888c 0000000000a4f928 : 0x2266f48<br>&gt;&gt; 000000000008ec40 0000000000000000 : 0000000000000000
>> 000000000018888c<br>&gt;&gt; 0000000000a4f928 000000000018888c : 0xa0<br>&gt;&gt;<br>&gt;&gt;<br>&gt;&gt; STACK_COMMAND: kb<br>&gt;&gt;<br>&gt;&gt; FOLLOWUP_IP:<br>&gt;&gt; MyFsd!MyCompleteRequest_Real+ea [\My_fsd\Mydata.c @ 709]<br>&gt;&gt; fffff88001d97bba 4883c438 add rsp,38h
>>
>> FAULTING_SOURCE_CODE:
>> 705: IoCompleteRequest( Irp, IO_DISK_INCREMENT );
>> 706: }
>> 707:
>> 708: return;
>> > 709: }
>> 710:
>> 711: BOOLEAN
>> 712: MyIsIrpTopLevel (
>> 713: IN PIRP Irp
>> 714: )
>>
>>
>> SYMBOL_STACK_INDEX: 8
>>
>> SYMBOL_NAME: MyFsd!MyCompleteRequest_Real+ea
>>
>> FOLLOWUP_NAME: MachineOwner
>>
>> IMAGE_NAME: MyFsd.sys
>>
>> BUCKET_ID: WRONG_SYMBOLS
>>
>> Followup: MachineOwner
>> ---------
>>
>>
>> —
>> NTFSD is sponsored by OSR
>>
>> OSR is hiring!! Info at http://www.osr.com/careers
>>
>> For our schedule of debugging and file system seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer

Just one minor point of clarification, the KeWait…() can use a stack
allocated event as long as the wait type is KernelMode, which you do
specify. If you were to specify UserMode then it is possible the stack
could be swapped out resulting in a crash when the event is later signaled.

Thus the stack is guaranteed to not be swapped out not because of the
call to KeWait…() but because the call specifies a KernelMode wait type.

Pete

On 6/1/2013 3:08 PM, xxxxx@flounder.com wrote:

Minor point: you do not need to allocate the KEVENT on the heap. You can
just declare it as a local variable! While passing addreses of locals
across thread boundaries is generally a Really Bad Thing To Do, in this
case you are guaranteed the stack will remain in place because of the
WaitFor.

Major Point: What if IoCallDriver returns any code other than
STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
can never arise.

The code, more correctly, should be
status = IoCallDriver(…);
if(status==STATUS_PENDING)
{
WaitFor(…);
status = Irp->IoStatus.Status;
delete the IRP
}
else
{
delete the IRP
}
return status.

Note this can’t work if you delete the IRP in the completion routine, so
you should figure out why the BSOD.

Note that the ONLY valid return code from your completion routine is
STATUS_MORE_PROCESSING_REQUIRED. If you return ANY other value, you are
guaranteed a BSOD. You did not post the !analyze -v output. If you return
any value other than SMPR then the completion walker will try to find the
next-higher completion routine, which does not exist. BSOD.
joe

> Hi, all
>
> We have a volume driver who create a VolDeviceObj and a fsd who create a
> FsdDevObj on IRP_MN_MOUNT_VOLUME, and during the mount operation
> VolDeviceObj->Vpb->DeviceObject is set to FsdDevObj.
>
> Our purpose is to dismount a drive(ex: Z:) by a FSCTL_DISMOUNT_VOLUME send
> by an user process(named: APP).
> The way of sending a FSCTL_DISMOUNT_VOLUME directly to fsd by APP is ok,
> and works well.
>
> But now it has been decided to do it in another way:
> 1). APP send an IOCTL to volume driver;
> 2). On receiving the IOCTL from APP, the volume driver send an
> FSCTL_DISMOUNT_VOLUME to fsd.
> After fsd have “successfully” processed the FSCTL_DISMOUNT_VOLUME in
> FsdFileSystemControl,it call IoCompleteRequest(), then BSOD occured.
>
> In this process,the volume driver build a new stack,and it’s on the top of
> stack,
> and fsd is just under it, right(— Q1)?
> Is it a normal way and is suggested to do so?
>
> Thanks in advance!
>
>
>
> And following is the details of buiuding my own IRP in volume driver and
> send it to fsd.
>
> // Open the drive and the FileObject we need
> ZwCreateFile(L"\Z:\");
> ObReferenceObjectByHandle(FileObject);
>
> Irp = NULL;
> // Or should be IoAllocateIrp(DeviceObject->StackSize +1 ) ? (— Q2)
> Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
> …
>
> IrpSp = IoGetNextIrpStackLocation(Irp);
> //Setup Irpsp and Irp
> …
> Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘EloV’);
> …
> KeInitializeEvent(Event, NotificationEvent, FALSE);
> IoSetCompletionRoutine(
> Irp,
> DismountIoctlComplete,
> Event,
> TRUE,
> TRUE,
> TRUE
> );
>
> Status = IoCallDriver(DeviceObject, Irp);
> KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
> ExFreePoolWithTag(Event, ‘EloV’);
> Event = NULL;
> IoFreeIrp(Irp);
>
> completion routine:
> DismountIoctlComplete()
> {
> KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
> // Or should return STATUS_SUCCESS, or both of them are ok here? (—
> Q3)
> return STATUS_MORE_PROCESSING_REQUIRED;
> }
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295

Yes, thank you for pointing that out; I’ve only seen this trick using
kernel mode waits, and I had forgotten entirely about the user-mode
version.
joe

Just one minor point of clarification, the KeWait…() can use a stack
allocated event as long as the wait type is KernelMode, which you do
specify. If you were to specify UserMode then it is possible the stack
could be swapped out resulting in a crash when the event is later
signaled.

Thus the stack is guaranteed to not be swapped out not because of the
call to KeWait…() but because the call specifies a KernelMode wait type.

Pete

On 6/1/2013 3:08 PM, xxxxx@flounder.com wrote:
> Minor point: you do not need to allocate the KEVENT on the heap. You
> can
> just declare it as a local variable! While passing addreses of locals
> across thread boundaries is generally a Really Bad Thing To Do, in this
> case you are guaranteed the stack will remain in place because of the
> WaitFor.
>
> Major Point: What if IoCallDriver returns any code other than
> STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
> can never arise.
>
> The code, more correctly, should be
> status = IoCallDriver(…);
> if(status==STATUS_PENDING)
> {
> WaitFor(…);
> status = Irp->IoStatus.Status;
> delete the IRP
> }
> else
> {
> delete the IRP
> }
> return status.
>
> Note this can’t work if you delete the IRP in the completion routine, so
> you should figure out why the BSOD.
>
> Note that the ONLY valid return code from your completion routine is
> STATUS_MORE_PROCESSING_REQUIRED. If you return ANY other value, you are
> guaranteed a BSOD. You did not post the !analyze -v output. If you
> return
> any value other than SMPR then the completion walker will try to find
> the
> next-higher completion routine, which does not exist. BSOD.
> joe
>
>
>> Hi, all
>>
>> We have a volume driver who create a VolDeviceObj and a fsd who create
>> a
>> FsdDevObj on IRP_MN_MOUNT_VOLUME, and during the mount operation
>> VolDeviceObj->Vpb->DeviceObject is set to FsdDevObj.
>>
>> Our purpose is to dismount a drive(ex: Z:) by a FSCTL_DISMOUNT_VOLUME
>> send
>> by an user process(named: APP).
>> The way of sending a FSCTL_DISMOUNT_VOLUME directly to fsd by APP is
>> ok,
>> and works well.
>>
>> But now it has been decided to do it in another way:
>> 1). APP send an IOCTL to volume driver;
>> 2). On receiving the IOCTL from APP, the volume driver send an
>> FSCTL_DISMOUNT_VOLUME to fsd.
>> After fsd have “successfully” processed the FSCTL_DISMOUNT_VOLUME in
>> FsdFileSystemControl,it call IoCompleteRequest(), then BSOD occured.
>>
>> In this process,the volume driver build a new stack,and it’s on the top
>> of
>> stack,
>> and fsd is just under it, right(— Q1)?
>> Is it a normal way and is suggested to do so?
>>
>> Thanks in advance!
>>
>>
>>
>> And following is the details of buiuding my own IRP in volume driver
>> and
>> send it to fsd.
>>
>> // Open the drive and the FileObject we need
>> ZwCreateFile(L"\Z:\");
>> ObReferenceObjectByHandle(FileObject);
>>
>> Irp = NULL;
>> // Or should be IoAllocateIrp(DeviceObject->StackSize +1 ) ? (— Q2)
>> Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
>> …
>>
>> IrpSp = IoGetNextIrpStackLocation(Irp);
>> //Setup Irpsp and Irp
>> …
>> Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), ‘EloV’);
>> …
>> KeInitializeEvent(Event, NotificationEvent, FALSE);
>> IoSetCompletionRoutine(
>> Irp,
>> DismountIoctlComplete,
>> Event,
>> TRUE,
>> TRUE,
>> TRUE
>> );
>>
>> Status = IoCallDriver(DeviceObject, Irp);
>> KeWaitForSingleObject(Event, Executive, KernelMode, FALSE, NULL);
>> ExFreePoolWithTag(Event, ‘EloV’);
>> Event = NULL;
>> IoFreeIrp(Irp);
>>
>> completion routine:
>> DismountIoctlComplete()
>> {
>> KeSetEvent(pEvent, IO_NO_INCREMENT, FALSE);
>> // Or should return STATUS_SUCCESS, or both of them are ok here?
>> (—
>> Q3)
>> return STATUS_MORE_PROCESSING_REQUIRED;
>> }
>>
>> —
>> NTFSD is sponsored by OSR
>>
>> OSR is hiring!! Info at http://www.osr.com/careers
>>
>> For our schedule of debugging and file system seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
>
>
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


Kernel Drivers
Windows File System and Device Driver Consulting
www.KernelDrivers.com
866.263.9295


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Hi, all

Many thanks.

What if IoCallDriver returns any code other than
STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
can never arise.
I will change the code after the IoCallDriver().
But I want to get more details about this.
Is the lower driver is desired to return STATUS_PENDING? If the Status returned from IoCallDriver is not STATUS_PENDING, then it’s guaranteed that the completion routine will not be called and no one will touch the Irp any more, right?

Based on all your replys, it seems that there is no requirement that a IoAllocateIrp-allocated IRP can only be freeed in the completion routine, right? Then it’s strange that after I moved IoFreeIrp to completion routine, my BSOD dirappered.

I will reproduce the BSOD and paste the full dump analyse as soon as possilbe.

That is not correct, your completion routine is called in both cases.
However, it is a common optimization to skip the call to
KeWaitForSingleObject when the return value is *not* STATUS_PENDING. In this
case, you know the IRP has been completed synchronously (the status is not
_PENDING), your completion routine has already run, and the event is
definitely set.

Correct. There’s something else going on here.

-scott
OSR

wrote in message news:xxxxx@ntfsd…

Hi, all

Many thanks.

What if IoCallDriver returns any code other than
STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
can never arise.
I will change the code after the IoCallDriver().
But I want to get more details about this.
Is the lower driver is desired to return STATUS_PENDING? If the Status
returned from IoCallDriver is not STATUS_PENDING, then it’s guaranteed that
the completion routine will not be called and no one will touch the Irp any
more, right?

Based on all your replys, it seems that there is no requirement that a
IoAllocateIrp-allocated IRP can only be freeed in the completion routine,
right? Then it’s strange that after I moved IoFreeIrp to completion
routine, my BSOD dirappered.

I will reproduce the BSOD and paste the full dump analyse as soon as
possilbe.

> [quote]

If the Status returned from IoCallDriver is not STATUS_PENDING, then it’s
guaranteed that the completion routine will not be called and no one will
touch the Irp any more, right?
[/quote]

That is not correct, your completion routine is called in both cases.
However, it is a common optimization to skip the call to
KeWaitForSingleObject when the return value is *not* STATUS_PENDING. In
this
case, you know the IRP has been completed synchronously (the status is not
_PENDING), your completion routine has already run, and the event is
definitely set.

The question would be, does a lower-level driver, in rejecting an IRP it
just received, complete the IRP or just return an error code?

If the latter, then yes.

The pattern I was basing this on is the old WDM IRP_MJ_PNP model, which,
at least in the WDM prototype code, not block if the IoCallDriver returns
an error code; this seems to assume that the lower-level driver will not
complete the request. What is the “contract” between two drivers when
IoCallDriver is what calls the lower one? And it this desired behavior
documented, so that the driver writer can make sure the driver s/he is
writing conforms to the contract with the driver above it?
thanks
joe

Correct. There’s something else going on here.

-scott
OSR

wrote in message news:xxxxx@ntfsd…

Hi, all

Many thanks.

>What if IoCallDriver returns any code other than
STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
can never arise.
I will change the code after the IoCallDriver().
But I want to get more details about this.
Is the lower driver is desired to return STATUS_PENDING? If the Status
returned from IoCallDriver is not STATUS_PENDING, then it’s guaranteed
that
the completion routine will not be called and no one will touch the Irp
any
more, right?

Based on all your replys, it seems that there is no requirement that a
IoAllocateIrp-allocated IRP can only be freeed in the completion routine,
right? Then it’s strange that after I moved IoFreeIrp to completion
routine, my BSOD dirappered.

I will reproduce the BSOD and paste the full dump analyse as soon as
possilbe.


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

You *must* complete the IRP with IoCompleteRequest and return the same error
status. Driver Verifier will fail you if you don’t.

The pattern is to not block if the status is anything other than
STATUS_PENDING, successful or not. The idea is that if the status is
anything other than STATUS_PENDING, the IRP must have been completed
synchronously. If it was completed synchronously, then the lower driver has
already called IoCompleteRequest and your completion routine has already
executed and signaled the event (in fact, a further optimization was to
detect this case and not even signal the event,). Thus, if you, “know” that
the event is already signaled there is no point in waiting on it.

This was potentially a win when there was a global dispatcher database lock,
though I suspect that these days it’s a micro-optimization that exists just
to confuse people.

-scott
OSR

wrote in message news:xxxxx@ntfsd…

That is not correct, your completion routine is called in both cases.
However, it is a common optimization to skip the call to
KeWaitForSingleObject when the return value is *not* STATUS_PENDING. In
this
case, you know the IRP has been completed synchronously (the status is not
_PENDING), your completion routine has already run, and the event is
definitely set.

The question would be, does a lower-level driver, in rejecting an IRP it
just received, complete the IRP or just return an error code?

If the latter, then yes.

The pattern I was basing this on is the old WDM IRP_MJ_PNP model, which,
at least in the WDM prototype code, not block if the IoCallDriver returns
an error code; this seems to assume that the lower-level driver will not
complete the request. What is the “contract” between two drivers when
IoCallDriver is what calls the lower one? And it this desired behavior
documented, so that the driver writer can make sure the driver s/he is
writing conforms to the contract with the driver above it?
thanks
joe

Correct. There’s something else going on here.

-scott
OSR

wrote in message news:xxxxx@ntfsd…

Hi, all

Many thanks.

>What if IoCallDriver returns any code other than
STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
can never arise.
I will change the code after the IoCallDriver().
But I want to get more details about this.
Is the lower driver is desired to return STATUS_PENDING? If the Status
returned from IoCallDriver is not STATUS_PENDING, then it’s guaranteed
that
the completion routine will not be called and no one will touch the Irp
any
more, right?

Based on all your replys, it seems that there is no requirement that a
IoAllocateIrp-allocated IRP can only be freeed in the completion routine,
right? Then it’s strange that after I moved IoFreeIrp to completion
routine, my BSOD dirappered.

I will reproduce the BSOD and paste the full dump analyse as soon as
possilbe.


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Thank you for the clarification. There are far too many of tese legacy
“optimizations” floating around, and it is hard to separate fact from
cuteness in the code. Trying to reverse-engineer the code in a WDM driver
to sort out the wheat from the chaff is a lengthy and difficult exercise.

Sadly, when we submitted a chapter of our book to a Microsoft driver
expert (more than a decade ago) it came back with certain sections
highlighted with comments like “this is wrong”. But no indication of what
was wrong, or why, or what the correct code would have been; when we read
the documentation, we saw that the code (it was from a Microsoft example)
conformed to the documentation. So a lot of tbe reverse-engineering is
by-guess-and-by-golly, and trying to attach a rationale to what we see.

I appreciate the explanation.
joe

You *must* complete the IRP with IoCompleteRequest and return the same
error
status. Driver Verifier will fail you if you don’t.

The pattern is to not block if the status is anything other than
STATUS_PENDING, successful or not. The idea is that if the status is
anything other than STATUS_PENDING, the IRP must have been completed
synchronously. If it was completed synchronously, then the lower driver
has
already called IoCompleteRequest and your completion routine has already
executed and signaled the event (in fact, a further optimization was to
detect this case and not even signal the event,). Thus, if you, “know”
that
the event is already signaled there is no point in waiting on it.

This was potentially a win when there was a global dispatcher database
lock,
though I suspect that these days it’s a micro-optimization that exists
just
to confuse people.

-scott
OSR

wrote in message news:xxxxx@ntfsd…

> [quote]
> If the Status returned from IoCallDriver is not STATUS_PENDING, then
> it’s
> guaranteed that the completion routine will not be called and no one
> will
> touch the Irp any more, right?
> [/quote]
>
> That is not correct, your completion routine is called in both cases.
> However, it is a common optimization to skip the call to
> KeWaitForSingleObject when the return value is *not* STATUS_PENDING. In
> this
> case, you know the IRP has been completed synchronously (the status is
> not
> _PENDING), your completion routine has already run, and the event is
> definitely set.

The question would be, does a lower-level driver, in rejecting an IRP it
just received, complete the IRP or just return an error code?

If the latter, then yes.

The pattern I was basing this on is the old WDM IRP_MJ_PNP model, which,
at least in the WDM prototype code, not block if the IoCallDriver returns
an error code; this seems to assume that the lower-level driver will not
complete the request. What is the “contract” between two drivers when
IoCallDriver is what calls the lower one? And it this desired behavior
documented, so that the driver writer can make sure the driver s/he is
writing conforms to the contract with the driver above it?
thanks
joe
>
> [quote]
> Based on all your replys, it seems that there is no requirement that a
> IoAllocateIrp-allocated IRP can only be freeed in the completion
> routine,
> right? Then it’s strange that after I moved IoFreeIrp to completion
> routine, my BSOD dirappered.
> [/quote]
>
> Correct. There’s something else going on here.
>
> -scott
> OSR
>
> wrote in message news:xxxxx@ntfsd…
>
> Hi, all
>
> Many thanks.
>
>>What if IoCallDriver returns any code other than
> STATUS_PENDING? Your WaiFor will hang forever wating for a notice that
> can never arise.
> I will change the code after the IoCallDriver().
> But I want to get more details about this.
> Is the lower driver is desired to return STATUS_PENDING? If the Status
> returned from IoCallDriver is not STATUS_PENDING, then it’s guaranteed
> that
> the completion routine will not be called and no one will touch the Irp
> any
> more, right?
>
> Based on all your replys, it seems that there is no requirement that a
> IoAllocateIrp-allocated IRP can only be freeed in the completion
> routine,
> right? Then it’s strange that after I moved IoFreeIrp to completion
> routine, my BSOD dirappered.
>
> I will reproduce the BSOD and paste the full dump analyse as soon as
> possilbe.
>
>
> —
> NTFSD is sponsored by OSR
>
> OSR is hiring!! Info at http://www.osr.com/careers
>
> For our schedule of debugging and file system seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>


NTFSD is sponsored by OSR

OSR is hiring!! Info at http://www.osr.com/careers

For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer