BAD_POOL_CALLER bugcheck on IoSkipCurrentIrpStackLocation

Hey, I try to redirect an IRP using the following code…
But when I pass the IRP down, i get a blue screen of death which basically is a BAD_POOL_CALLER, the error (at least windbg says it) occurs right in the IoSkipCurrentIrpStackLocation line.

I appreciate any help or hint. And here it goes:

/* JUST AN EXCERPT */

SfRedirectIRP(irpSp,Irp,&myRandomName);
// Free myRandomName to avoid Stack Flooding
if(myRandomName.Buffer)
ExFreePool(myRandomName.Buffer);
IoSkipCurrentIrpStackLocation( Irp );

return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION) DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
Irp );

/* EXCERPT END */

VOID SfRedirectIRP(PIO_STACK_LOCATION FltObjects, PIRP Data, PUNICODE_STRING TargetName)
{
PUNICODE_STRING filename = &((PFILE_OBJECT)FltObjects->FileObject)->FileName;

/* HERE WE ARE SETTING THE NEW FILENAME INSIDE THE BUFFER */
if(TargetName->MaximumLength < filename->MaximumLength)
{
// Create a new buffer and free existing one.
// Note that allocated buffer will be freed automatically by the system.
PWSTR pBuffer = (PWSTR) ExAllocatePool(NonPagedPool,TargetName->MaximumLength * sizeof(WCHAR)); //new (NonPagedPool)char[TargetName->MaximumLength];
if(pBuffer == NULL)
return;

if(filename->Buffer)
ExFreePool(filename->Buffer);

RtlCopyMemory(pBuffer, TargetName->Buffer, TargetName->Length);
filename->Length = TargetName->Length;
filename->MaximumLength = TargetName->MaximumLength;
filename->Buffer = pBuffer;
}
else
{
// Reuse the existing buffer
RtlCopyMemory(filename->Buffer, TargetName->Buffer, TargetName->Length);
filename->Length = TargetName->Length;
}

Data=Data;
// SET IRP STATUS TO REPARSE
Data->IoStatus.Status = STATUS_REPARSE;
Data->IoStatus.Information = IO_REPARSE;

// REDIRECTION OF THE IRP FINISHED!

}

> the error (at least windbg says it) occurs right in the

IoSkipCurrentIrpStackLocation line.

Look at declaration:

#define IoSkipCurrentIrpStackLocation( Irp ) { \
(Irp)->CurrentLocation++; \
(Irp)->Tail.Overlay.CurrentStackLocation++; }

It is obvious from the above declaration that, as long as IRP in itself is valid, you just cannot bluescreen in IoSkipCurrentIrpStackLocation. Therefore, you should investigate your problem more thoroughly…

Anton Bassov

Well I do nothing more than changing the filename in the Irp and then just hand the IRP down to lower device.

This is a more detailed error report, maybe that helps a bit:

Connected to:
Name : RESEARCH
Processor : IA32(x86)-Pentium 4M (Mobile)
Stepping : 8
Processor Count: 1
Operating Sys. : Windows XP Ver. 5.1 Build 2600 Service Pack 2 (FRE)
Target Service : Connected (Active)
BUGCHECK: c2 BAD_POOL_CALLER
Attempt to free pool which was already freed.

Parameter 4 : 0x86073570 Address of Pool Header

Probably caused by : SystemCallStub+4 (Ring3/Ring0 Trans.)
TrapFrame Address : 0xee225d64
More information : lastfault -a

Where are you returning with

return Status_Reparse;

?

On 9/30/07, xxxxx@web.de wrote:
>
> Hey, I try to redirect an IRP using the following code…
> But when I pass the IRP down, i get a blue screen of death which basically
> is a BAD_POOL_CALLER, the error (at least windbg says it) occurs right in
> the IoSkipCurrentIrpStackLocation line.
>
> I appreciate any help or hint. And here it goes:
>
>
> /* JUST AN EXCERPT /
>
> SfRedirectIRP(irpSp,Irp,&myRandomName);
> // Free myRandomName to avoid Stack Flooding
> if(myRandomName.Buffer)
> ExFreePool(myRandomName.Buffer);
> IoSkipCurrentIrpStackLocation( Irp );
>
> return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)
> DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
> Irp );
>
>
>
> /
EXCERPT END /
>
> VOID SfRedirectIRP(PIO_STACK_LOCATION FltObjects, PIRP Data,
> PUNICODE_STRING TargetName)
> {
> PUNICODE_STRING filename =
> &((PFILE_OBJECT)FltObjects->FileObject)->FileName;
>
>
> /
HERE WE ARE SETTING THE NEW FILENAME INSIDE THE BUFFER */
> if(TargetName->MaximumLength < filename->MaximumLength)
> {
> // Create a new buffer and free existing one.
> // Note that allocated buffer will be freed automatically by the
> system.
> PWSTR pBuffer = (PWSTR)
> ExAllocatePool(NonPagedPool,TargetName->MaximumLength * sizeof(WCHAR));
> //new (NonPagedPool)char[TargetName->MaximumLength];
> if(pBuffer == NULL)
> return;
>
> if(filename->Buffer)
> ExFreePool(filename->Buffer);
>
> RtlCopyMemory(pBuffer, TargetName->Buffer, TargetName->Length);
> filename->Length = TargetName->Length;
> filename->MaximumLength = TargetName->MaximumLength;
> filename->Buffer = pBuffer;
> }
> else
> {
> // Reuse the existing buffer
> RtlCopyMemory(filename->Buffer, TargetName->Buffer,
> TargetName->Length);
> filename->Length = TargetName->Length;
> }
>
> Data=Data;
> // SET IRP STATUS TO REPARSE
> Data->IoStatus.Status = STATUS_REPARSE;
> Data->IoStatus.Information = IO_REPARSE;
>
> // REDIRECTION OF THE IRP FINISHED!
>
> }
>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> You are currently subscribed to ntfsd as: xxxxx@gmail.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

http://support.microsoft.com/kb/319447

On 9/30/07, OSR LIST wrote:
>
> Where are you returning with
>
> return Status_Reparse;
>
> ?
>
> On 9/30/07, xxxxx@web.de < xxxxx@web.de> wrote:
> >
> > Hey, I try to redirect an IRP using the following code…
> > But when I pass the IRP down, i get a blue screen of death which
> > basically is a BAD_POOL_CALLER, the error (at least windbg says it) occurs
> > right in the IoSkipCurrentIrpStackLocation line.
> >
> > I appreciate any help or hint. And here it goes:
> >
> >
> > /* JUST AN EXCERPT /
> >
> > SfRedirectIRP(irpSp,Irp,&myRandomName);
> > // Free myRandomName to avoid Stack Flooding
> > if(myRandomName.Buffer)
> > ExFreePool(myRandomName.Buffer );
> > IoSkipCurrentIrpStackLocation( Irp );
> >
> > return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)
> > DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
> > Irp );
> >
> >
> >
> > /
EXCERPT END /
> >
> > VOID SfRedirectIRP(PIO_STACK_LOCATION FltObjects, PIRP Data,
> > PUNICODE_STRING TargetName)
> > {
> > PUNICODE_STRING filename =
> > &((PFILE_OBJECT)FltObjects->FileObject)->FileName;
> >
> >
> > /
HERE WE ARE SETTING THE NEW FILENAME INSIDE THE BUFFER */
> > if(TargetName->MaximumLength < filename->MaximumLength)
> > {
> > // Create a new buffer and free existing one.
> > // Note that allocated buffer will be freed automatically by the
> > system.
> > PWSTR pBuffer = (PWSTR)
> > ExAllocatePool(NonPagedPool,TargetName->MaximumLength * sizeof(WCHAR));
> > //new (NonPagedPool)char[TargetName->MaximumLength];
> > if(pBuffer == NULL)
> > return;
> >
> > if(filename->Buffer)
> > ExFreePool(filename->Buffer);
> >
> > RtlCopyMemory(pBuffer, TargetName->Buffer, TargetName->Length);
> > filename->Length = TargetName->Length;
> > filename->MaximumLength = TargetName->MaximumLength;
> > filename->Buffer = pBuffer;
> > }
> > else
> > {
> > // Reuse the existing buffer
> > RtlCopyMemory(filename->Buffer, TargetName->Buffer,
> > TargetName->Length);
> > filename->Length = TargetName->Length;
> > }
> >
> > Data=Data;
> > // SET IRP STATUS TO REPARSE
> > Data->IoStatus.Status = STATUS_REPARSE;
> > Data->IoStatus.Information = IO_REPARSE;
> >
> > // REDIRECTION OF THE IRP FINISHED!
> >
> > }
> >
> >
> > —
> > NTFSD is sponsored by OSR
> >
> > For our schedule debugging and file system seminars
> > (including our new fs mini-filter seminar) visit:
> > http://www.osr.com/seminars
> >
> > You are currently subscribed to ntfsd as: xxxxx@gmail.com
> > To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
>
>

> Well I do nothing more than changing the filename in the Irp and then just hand

the IRP down to lower device.

Duh…

I looked at your code - now I see what you are doing and where you are crashing
(it happens not in IoSkipCurrentIrpStackLocation but after you have passed IRP to the lower driver).

If you want to redirect IRP_MJ_CREATE to another file, you have to replace filename with the full name of the destination file, set IoStatus block to STATUS_REPARSE, call IoCompleteRequest(), and return STATUS_REPARSE. If you do it this way, IO Manager will send another IRP, this time taking into consideration the name that you have supplied.

However, you pass IRP down to FSD after having modified the file name. What do you think is supposed to happen under these circumstances???

Anton Bassov

Just small correction: replacing file name in FO and then passing IRP down is
not necessarily wrong. It is a correct way of redirecting within volume
boundaries. However setting IoStatus.Status to STATUS_REPARSE does not make
much sense in this case.
Anyway, changing file name should not cause BSOD - I guess root cause is in
the code which OP did not provide.

Alexei.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of
xxxxx@hotmail.com
Sent: Sunday, September 30, 2007 8:56 AM
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] BAD_POOL_CALLER bugcheck on
IoSkipCurrentIrpStackLocation

Well I do nothing more than changing the filename in the Irp and then just
hand
the IRP down to lower device.

Duh…

I looked at your code - now I see what you are doing and where you are
crashing
(it happens not in IoSkipCurrentIrpStackLocation but after you have passed
IRP to the lower driver).

If you want to redirect IRP_MJ_CREATE to another file, you have to replace
filename with the full name of the destination file, set IoStatus block to
STATUS_REPARSE, call IoCompleteRequest(), and return STATUS_REPARSE. If you
do it this way, IO Manager will send another IRP, this time taking into
consideration the name that you have supplied.

However, you pass IRP down to FSD after having modified the file name. What
do you think is supposed to happen under these circumstances???

Anton Bassov


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@vmware.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> Just small correction: replacing file name in FO and then passing IRP down is

not necessarily wrong. It is a correct way of redirecting within volume boundaries.

AFAIK, returning STATUS_REPARSE is the only *approved* way of doing it. At the same time, I don’t immediately see any reason why replacing file name and passing IRP down the stack should fail if you redirect to the same volume…

Anyway, changing file name should not cause BSOD

Normally I would agree with you, but, before passing IRP down the stack, the OP sets IRP
status and information to respectively STATUS_REPARSE and IO_REPARSE. Therefore, I don’t exclude the possibility that underlying FSD or IO Manager just get “surprized” when they see completion information and status in IRP that has not yet been completed, and bugcheck “just in case”…

Anton Bassov

Hi,
At least there is one error in the logic - you skip the case when the
RelatedFileObject is not NULL.


Slava Imameyev, xxxxx@hotmail.com

wrote in message news:xxxxx@ntfsd…
> Hey, I try to redirect an IRP using the following code…
> But when I pass the IRP down, i get a blue screen of death which basically
> is a BAD_POOL_CALLER, the error (at least windbg says it) occurs right in
> the IoSkipCurrentIrpStackLocation line.
>
> I appreciate any help or hint. And here it goes:
>
>
> /* JUST AN EXCERPT /
>
> SfRedirectIRP(irpSp,Irp,&myRandomName);
> // Free myRandomName to avoid Stack Flooding
> if(myRandomName.Buffer)
> ExFreePool(myRandomName.Buffer);
> IoSkipCurrentIrpStackLocation( Irp );
>
> return IoCallDriver( ((PSFILTER_DEVICE_EXTENSION)
> DeviceObject->DeviceExtension)->NLExtHeader.AttachedToDeviceObject,
> Irp );
>
>
>
> /
EXCERPT END /
>
> VOID SfRedirectIRP(PIO_STACK_LOCATION FltObjects, PIRP Data,
> PUNICODE_STRING TargetName)
> {
> PUNICODE_STRING filename =
> &((PFILE_OBJECT)FltObjects->FileObject)->FileName;
>
>
> /
HERE WE ARE SETTING THE NEW FILENAME INSIDE THE BUFFER */
> if(TargetName->MaximumLength < filename->MaximumLength)
> {
> // Create a new buffer and free existing one.
> // Note that allocated buffer will be freed automatically by the
> system.
> PWSTR pBuffer = (PWSTR)
> ExAllocatePool(NonPagedPool,TargetName->MaximumLength * sizeof(WCHAR));
> //new (NonPagedPool)char[TargetName->MaximumLength];
> if(pBuffer == NULL)
> return;
>
> if(filename->Buffer)
> ExFreePool(filename->Buffer);
>
> RtlCopyMemory(pBuffer, TargetName->Buffer, TargetName->Length);
> filename->Length = TargetName->Length;
> filename->MaximumLength = TargetName->MaximumLength;
> filename->Buffer = pBuffer;
> }
> else
> {
> // Reuse the existing buffer
> RtlCopyMemory(filename->Buffer, TargetName->Buffer,
> TargetName->Length);
> filename->Length = TargetName->Length;
> }
>
> Data=Data;
> // SET IRP STATUS TO REPARSE
> Data->IoStatus.Status = STATUS_REPARSE;
> Data->IoStatus.Information = IO_REPARSE;
>
> // REDIRECTION OF THE IRP FINISHED!
>
> }
>
>