Windbg: Irp is completed

I am using IoAllocateIrp to set up a RYO irp_mj_read in a create completion
routine of my legacy FSFD. When I display the Irp in WinDbg with !IRP, it
shows status “Irp is complete” even though I have not called IoCallDriver
yet. What does it look for in the Irp to display that status?

Thanks.

So soon after you call IoAllocateIrp; windbg reports it to be completed??

How about setting something in the next stack location; this will set the current stack location pointer.(Which I guess is what it might be checking). Set it and check again.

> routine of my legacy FSFD. When I display the Irp in WinDbg with !IRP, it

shows status “Irp is complete” even though I have not called IoCallDriver

I suspect that !irp considers the IRP as complete if it has no current stack location at all, only the next one. This is really the picture with just-allocated IRP.

Pass it down, and look again.

Also, you can allocate the IRP with +1 more stack locations, and immediately call IoSetNextIrpStackLocation on it. This switches the pointer+index in the IRP so that the ex-next SP becomes current SP, and the next IRP slot becomes next SP.

This a) allows the DeviceObject parameter in the completion routine b) is mandatory for some things like TDI (IRPs returned from callbacks like ClientEventConnect and ClientEventReceive).

I suspect WinDbg will work fine on this.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

> How about setting something in the next stack location; this will set the current stack location pointer.

No, it will not. IoCallDriver or IoSetNextIrpStackLocation will.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>>No, it will not. IoCallDriver or IoSetNextIrpStackLocation will.

Sorry for not being clear; I did not meant to set the next stack location manually when I said to do so.

wrote in message news:xxxxx@ntfsd…
> So soon after you call IoAllocateIrp; windbg reports it to be completed??

Good question. I stopped it immediately after IoAllocateIrp and it is being
shown as “completed”.

Maxim,

This is the stripped down code I am using - I removed the fluff and error paths for clarity.

WinDbg is showing pIrp as “completed” all the way through to IoCallDriver. Am I setting up something incorrectly?

Thanks.

pIrp = IoAllocateIrp(deviceExtension->FileSystemDeviceObject->StackSize, FALSE);
KeInitializeEvent(&myEvent, NotificationEvent, FALSE);
nextSp = IoGetNextIrpStackLocation(pIrp);
pIrp->Tail.Overlay.Thread = PsGetCurrentThread();
pIrp->UserBuffer = myBuffer; // non paged buffer
nextSp->DeviceObject = deviceExtension->FileSystemDeviceObject;
nextSp->Parameters.Read.Length = myLen;
nextSp->Parameters.Read.ByteOffset.QuadPart = 0;
nextSp->MajorFunction = IRP_MJ_READ;
pIrp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION | IRP_NOCACHE;
IoSetCompletionRoutine(pIrp, myComplete, &myEvent, TRUE, TRUE, TRUE);
pIrp->Tail.Overlay.OriginalFileObject = pFileObject;
pIrp->RequestorMode = KernelMode;
nextSp->FileObject = pFileObject;
ntStatus = IoCallDriver(deviceExtension->FileSystemDeviceObject, pIrp);

“Maxim S. Shatskih” wrote in message news:xxxxx@ntfsd…
> routine of my legacy FSFD. When I display the Irp in WinDbg with !IRP, it
> shows status “Irp is complete” even though I have not called IoCallDriver

I suspect that !irp considers the IRP as complete if it has no current stack location at all, only the next one. This is really the picture with just-allocated IRP.

Pass it down, and look again.

Also, you can allocate the IRP with +1 more stack locations, and immediately call IoSetNextIrpStackLocation on it. This switches the pointer+index in the IRP so that the ex-next SP becomes current SP, and the next IRP slot becomes next SP.

This a) allows the DeviceObject parameter in the completion routine b) is mandatory for some things like TDI (IRPs returned from callbacks like ClientEventConnect and ClientEventReceive).

I suspect WinDbg will work fine on this.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

“Neil Weicher” wrote in message news:xxxxx@ntfsd…
>This is the stripped down code I am using - I removed the fluff and error
>paths for clarity.
>
>WinDbg is showing pIrp as “completed” all the way through to IoCallDriver.
>Am I setting up something incorrectly?

It’s really just a limitation of the !irp command.

!irp considers an IRP to be complete if there’s no current stack location,
which is the case at two points in an IRP’s life:

1) When the IRP is actually complete, because the I/O manager unwinds I/O
stack locations until there aren’t any left

2) When the IRP is first allocated, because the person allocating the IRP
never gets their own stack location thus there is no, “current” stack
location.

Internally and strictly as an implementation detail, “an IRP with no current
stack location” is denoted by the CurrentLocation field in the IRP being
higher than the StackCount field. So, for a random example taken from my
current target:

3: kd> g
Breakpoint 2 hit
nt!IoAllocateIrp:
828774c8 8bff mov edi,edi
3: kd> gu
nt!IopAllocateIrpMustSucceed+0x20:
8287baf6 85c0 test eax,eax
3: kd> ??((nt!_IRP*)@eax)->StackCount
char 0n13 ‘’
3: kd> ??((nt!_IRP*)@eax)->CurrentLocation
char 0n14 ‘’
3: kd> !irp @eax
Irp is active with 13 stacks 14 is current (= 0x9727affc)
No Mdl: No System Buffer: Thread 00000000: Irp is completed.

Once we’re in this case, there are two things that are going to cause the
IRP to have a current stack location:

1) Calling IoSetNextIrpStackLocation (which is rare)

2) Calling IoCallDriver, which will make the next stack location the current
stack location and then call the target driver

Note that you can’t just step over IoCallDriver in the debugger because the
target driver may complete the IRP between the time you step over the call
and the debugger comes back, in which case the IRP really is complete. You’d
want to step into IoCallDriver until the point where the CurrentLocation
field of the IRP is decremented, at which point you’ll no longer see the IRP
as being completed in the !irp output.

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com

>nextSp->DeviceObject = deviceExtension->FileSystemDeviceObject;

No need, IoCallDriver will set it.

pIrp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION | IRP_NOCACHE;

No need ever. Do not touch this field.

pIrp->Tail.Overlay.OriginalFileObject = pFileObject;

No need ever. Do not touch this field.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

“Maxim S. Shatskih” wrote in message news:xxxxx@ntfsd…

>pIrp->Flags |= IRP_READ_OPERATION | IRP_DEFER_IO_COMPLETION |
>IRP_NOCACHE;
No need ever. Do not touch this field.

While I agree setting IRP_READ_OPERATION and IRP_DEFER_IO_COMPLETION aren’t
necessary, I don’t agree that you should never touch this field. How else
would you signify that you want non-cached I/O (or paging, though that’s
probably used less often)?

-scott


Scott Noone
Consulting Associate and Chief System Problem Analyst
OSR Open Systems Resources, Inc.
http://www.osronline.com