Buffer Filter for IRP_MN_QUERYDIRECTORY

Hello everyone,

I want to filter buffer returned by IRP_MN_QUERYDIRECTORY to hide some file. But when the buffer contain only one file which I should hide it, whatever I do, It can be shown. code like below:

curEntry = (PFILE_BOTH_DIR_INFORMATION)Irp->UserBuffer;
do
{
nextEntryOffset = curEntry->NextEntryOffset;
nextEntry = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)curEntry + nextEntryOffset);

//
// Get the full path for the file by adding fullPathName
//
RtlCopyUnicodeString( &fullPath, &uniPath );
fileName.Buffer = curEntry->FileName;
fileName.Length = (USHORT)curEntry->FileNameLength;
fileName.MaximumLength = (USHORT)curEntry->FileNameLength;

RtlAppendUnicodeStringToString( &fullPath, &fileName );
if( SNSfpdProtectFileW( fullPath.Buffer, fullPath.Length ) )
{
//
// Delete the entry from buffer
//
if( curEntry != nextEntry ) // not last one
{
memcpy( curEntry, nextEntry, Irp->IoStatus.Information-( (ULONG)nextEntry - (ULONG)Irp->UserBuffer ) );
Irp->IoStatus.Information -= nextEntryOffset;
}
else // last one
{
Irp->IoStatus.Information -= Irp->IoStatus.Information - ((ULONG)curEntry - (ULONG)Irp->UserBuffer);//nextEntryOffset;
if( prevEntry ) prevEntry->NextEntryOffset = 0;
if( curEntry == Irp->UserBuffer )
{
PIRP newIrp = NULL;
PIO_STACK_LOCATION newSp = NULL;
//
// query to lower driver again
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
IrpSp->Parameters.Others.Argument2 = NULL;

if( Irp->CurrentLocation > 1 )
{
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp, DirectoryDone, NULL, TRUE, TRUE, TRUE );
status = IoCallDriver( hookExt->FileSystem, Irp );
}
else
{
newIrp = IoAllocateIrp( (CCHAR)( DeviceObject->StackSize + 2 ), FALSE );
if( newIrp )
{
newIrp->MdlAddress = Irp->MdlAddress;
newIrp->Flags = Irp->Flags & (~IRP_ASSOCIATED_IRP);
newIrp->AssociatedIrp.SystemBuffer = Irp->AssociatedIrp.SystemBuffer;
newIrp->RequestorMode = Irp->RequestorMode;
newIrp->UserBuffer = Irp->UserBuffer;
newIrp->IoStatus.Information = 0;
newIrp->IoStatus.Status = STATUS_SUCCESS;

IoSetNextIrpStackLocation( newIrp );
newSp = IoGetCurrentIrpStackLocation( newIrp );
newSp[0] = IrpSp[0];
IoCopyCurrentIrpStackLocationToNext( newIrp );
IoSetCompletionRoutine( newIrp, DirectoryDone, NULL, TRUE, TRUE, TRUE );
status = IoCallDriver( hookExt->FileSystem, newIrp );
}

}
if( newIrp )
{
Irp->IoStatus.Status = newIrp->IoStatus.Status;
IoFreeIrp( newIrp );
}
}
break;
}

//
// No more entries
//
if( curEntry == nextEntry ) break;
}
else
{
//
// No more entries
//
if( curEntry == nextEntry ) break;

prevEntry = curEntry;
curEntry = nextEntry;
}

} while( curEntry );

In the case where the file you’re skipping is the only file being
returned, and you don’t want it to show, all you need to do is just
return STATUS_NO_MORE_FILES (if AT LEAST one previous file was returned
for this directory query) or STATUS_NO_SUCH_FILE (if NO previous files
have been returned for this directory query). There’s no reason you
would have to query the lower driver again.

  • Nicholas Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Ken Li
Sent: Saturday, January 18, 2003 10:31 PM
To: File Systems Developers
Subject: [ntfsd] Buffer Filter for IRP_MN_QUERYDIRECTORY

Hello everyone,

I want to filter buffer returned by IRP_MN_QUERYDIRECTORY to hide some
file. But when the buffer contain only one file which I should hide it,
whatever I do, It can be shown. code like below:

curEntry = (PFILE_BOTH_DIR_INFORMATION)Irp->UserBuffer;
do
{
nextEntryOffset = curEntry->NextEntryOffset;
nextEntry = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)curEntry +
nextEntryOffset);

//
// Get the full path for the file by adding fullPathName
//
RtlCopyUnicodeString( &fullPath, &uniPath );
fileName.Buffer = curEntry->FileName;
fileName.Length = (USHORT)curEntry->FileNameLength;
fileName.MaximumLength = (USHORT)curEntry->FileNameLength;

RtlAppendUnicodeStringToString( &fullPath, &fileName );
if( SNSfpdProtectFileW( fullPath.Buffer, fullPath.Length ) )
{
//
// Delete the entry from buffer
//
if( curEntry != nextEntry ) // not last one
{
memcpy( curEntry, nextEntry, Irp->IoStatus.Information-(
(ULONG)nextEntry - (ULONG)Irp->UserBuffer ) );
Irp->IoStatus.Information -= nextEntryOffset;
}
else // last one
{
Irp->IoStatus.Information -= Irp->IoStatus.Information -
((ULONG)curEntry - (ULONG)Irp->UserBuffer);//nextEntryOffset;
if( prevEntry ) prevEntry->NextEntryOffset = 0;
if( curEntry == Irp->UserBuffer )
{
PIRP newIrp = NULL;
PIO_STACK_LOCATION newSp = NULL;
//
// query to lower driver again
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
IrpSp->Parameters.Others.Argument2 = NULL;

if( Irp->CurrentLocation > 1 )
{
IoCopyCurrentIrpStackLocationToNext( Irp );
IoSetCompletionRoutine( Irp, DirectoryDone, NULL, TRUE, TRUE,
TRUE );
status = IoCallDriver( hookExt->FileSystem, Irp );
}
else
{
newIrp = IoAllocateIrp( (CCHAR)( DeviceObject->StackSize + 2 ),
FALSE );
if( newIrp )
{
newIrp->MdlAddress = Irp->MdlAddress;
newIrp->Flags = Irp->Flags & (~IRP_ASSOCIATED_IRP);
newIrp->AssociatedIrp.SystemBuffer =
Irp->AssociatedIrp.SystemBuffer;
newIrp->RequestorMode = Irp->RequestorMode;
newIrp->UserBuffer = Irp->UserBuffer;
newIrp->IoStatus.Information = 0;
newIrp->IoStatus.Status = STATUS_SUCCESS;

IoSetNextIrpStackLocation( newIrp );
newSp = IoGetCurrentIrpStackLocation( newIrp );
newSp[0] = IrpSp[0];
IoCopyCurrentIrpStackLocationToNext( newIrp );
IoSetCompletionRoutine( newIrp, DirectoryDone, NULL, TRUE, TRUE,
TRUE );
status = IoCallDriver( hookExt->FileSystem, newIrp );
}

}
if( newIrp )
{
Irp->IoStatus.Status = newIrp->IoStatus.Status;
IoFreeIrp( newIrp );
}
}
break;
}

//
// No more entries
//
if( curEntry == nextEntry ) break;
}
else
{
//
// No more entries
//
if( curEntry == nextEntry ) break;

prevEntry = curEntry;
curEntry = nextEntry;
}

} while( curEntry );


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

Hi Nicholas,

If I return STATUS_NO_MORE_FILES or STATUS_NO_SUCH_FILE, system still show
the file. And furthermore, I set Irp->IoStatus.Information to 0, result is
the same.

----- Original Message -----
From: “Nicholas Ryan”
To: “File Systems Developers”
Sent: Monday, January 20, 2003 10:31 AM
Subject: [ntfsd] RE: Buffer Filter for IRP_MN_QUERYDIRECTORY

> In the case where the file you’re skipping is the only file being
> returned, and you don’t want it to show, all you need to do is just
> return STATUS_NO_MORE_FILES (if AT LEAST one previous file was returned
> for this directory query) or STATUS_NO_SUCH_FILE (if NO previous files
> have been returned for this directory query). There’s no reason you
> would have to query the lower driver again.
>
> - Nicholas Ryan
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Ken Li
> Sent: Saturday, January 18, 2003 10:31 PM
> To: File Systems Developers
> Subject: [ntfsd] Buffer Filter for IRP_MN_QUERYDIRECTORY
>
>
> Hello everyone,
>
> I want to filter buffer returned by IRP_MN_QUERYDIRECTORY to hide some
> file. But when the buffer contain only one file which I should hide it,
> whatever I do, It can be shown. code like below:
>
> curEntry = (PFILE_BOTH_DIR_INFORMATION)Irp->UserBuffer;
> do
> {
> nextEntryOffset = curEntry->NextEntryOffset;
> nextEntry = (PFILE_BOTH_DIR_INFORMATION)((PCHAR)curEntry +
> nextEntryOffset);
>
> //
> // Get the full path for the file by adding fullPathName
> //
> RtlCopyUnicodeString( &fullPath, &uniPath );
> fileName.Buffer = curEntry->FileName;
> fileName.Length = (USHORT)curEntry->FileNameLength;
> fileName.MaximumLength = (USHORT)curEntry->FileNameLength;
>
> RtlAppendUnicodeStringToString( &fullPath, &fileName );
> if( SNSfpdProtectFileW( fullPath.Buffer, fullPath.Length ) )
> {
> //
> // Delete the entry from buffer
> //
> if( curEntry != nextEntry ) // not last one
> {
> memcpy( curEntry, nextEntry, Irp->IoStatus.Information-(
> (ULONG)nextEntry - (ULONG)Irp->UserBuffer ) );
> Irp->IoStatus.Information -= nextEntryOffset;
> }
> else // last one
> {
> Irp->IoStatus.Information -= Irp->IoStatus.Information -
> ((ULONG)curEntry - (ULONG)Irp->UserBuffer);//nextEntryOffset;
> if( prevEntry ) prevEntry->NextEntryOffset = 0;
> if( curEntry == Irp->UserBuffer )
> {
> PIRP newIrp = NULL;
> PIO_STACK_LOCATION newSp = NULL;
> //
> // query to lower driver again
> //
> IrpSp = IoGetCurrentIrpStackLocation( Irp );
> IrpSp->Parameters.Others.Argument2 = NULL;
>
> if( Irp->CurrentLocation > 1 )
> {
> IoCopyCurrentIrpStackLocationToNext( Irp );
> IoSetCompletionRoutine( Irp, DirectoryDone, NULL, TRUE, TRUE,
> TRUE );
> status = IoCallDriver( hookExt->FileSystem, Irp );
> }
> else
> {
> newIrp = IoAllocateIrp( (CCHAR)( DeviceObject->StackSize + 2 ),
> FALSE );
> if( newIrp )
> {
> newIrp->MdlAddress = Irp->MdlAddress;
> newIrp->Flags = Irp->Flags & (~IRP_ASSOCIATED_IRP);
> newIrp->AssociatedIrp.SystemBuffer =
> Irp->AssociatedIrp.SystemBuffer;
> newIrp->RequestorMode = Irp->RequestorMode;
> newIrp->UserBuffer = Irp->UserBuffer;
> newIrp->IoStatus.Information = 0;
> newIrp->IoStatus.Status = STATUS_SUCCESS;
>
> IoSetNextIrpStackLocation( newIrp );
> newSp = IoGetCurrentIrpStackLocation( newIrp );
> newSp[0] = IrpSp[0];
> IoCopyCurrentIrpStackLocationToNext( newIrp );
> IoSetCompletionRoutine( newIrp, DirectoryDone, NULL, TRUE, TRUE,
> TRUE );
> status = IoCallDriver( hookExt->FileSystem, newIrp );
> }
>
> }
> if( newIrp )
> {
> Irp->IoStatus.Status = newIrp->IoStatus.Status;
> IoFreeIrp( newIrp );
> }
> }
> break;
> }
>
> //
> // No more entries
> //
> if( curEntry == nextEntry ) break;
> }
> else
> {
> //
> // No more entries
> //
> if( curEntry == nextEntry ) break;
>
> prevEntry = curEntry;
> curEntry = nextEntry;
> }
>
> } while( curEntry );
>
> —
> You are currently subscribed to ntfsd as: xxxxx@nryan.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@occultsoft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

Yes, there is! If there are additional files, they would not be seen
this way.
In pseudo language, one needs to:

  • Do IoCallDriver (first call)
  • Filter the buffer
  • If at least one file is not hidden in the buffer, set
    Irp->IoStatus.Information to reflect the required data buffer size, and
    return STATUS_SUCCESS
  • If the buffer is empty, after filtering, re-call the lower driver, and
    do filtering again.
  • If the lower driver returns a non success code, return that code.

Just in case - to do IoCallDriver again, you must return
STATUS_MORE_PROCESSING_REQUIRED in the completion, and wait on an event…
then IoCompleteRequest the IRP.

Nicholas Ryan wrote:

In the case where the file you’re skipping is the only file being
returned, and you don’t want it to show, all you need to do is just
return STATUS_NO_MORE_FILES (if AT LEAST one previous file was returned
for this directory query) or STATUS_NO_SUCH_FILE (if NO previous files
have been returned for this directory query). There’s no reason you would
have to query the lower driver again.


Kind regards, Dejan M. www.alfasp.com
E-mail: xxxxx@alfasp.com ICQ#: 56570367
Alfa File Monitor - File monitoring library for Win32 developers.
Alfa File Protector - File protection and hiding library for Win32
developers.

Then you are doing something ELSE wrong.
And looking at your code - YOU REALLY ARE! You are not waiting for the
completion routine to finish, nor does it seem to be set! Thus you are not
returning STATUS_MORE_PROCESSING_REQUIRED in it, and will eventually bug check
the system - I’m surprised you did not already:-)

I suggest doing some studying around STATUS_MORE_PROCESSING_REQUIRED and
completion routines, before you take on this task. It will save you a lot of
headaches:-)


Kind regards, Dejan M. www.alfasp.com
E-mail: xxxxx@alfasp.com ICQ#: 56570367
Alfa File Monitor - File monitoring library for Win32 developers.
Alfa File Protector - File protection and hiding library for Win32 developers.

Oops, I suppose that is a corner case, where a single file is returned
with STATUS_SUCCESS and not STATUS_NO_MORE_FILES - meaning there are
still more files to be returned. Unfortuntely my experience was only
with adding files to a query, not removing them… :slight_smile:

  • Nicholas Ryan

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Dejan Maksimovic
Sent: Sunday, January 19, 2003 7:56 PM
To: File Systems Developers
Subject: [ntfsd] RE: Buffer Filter for IRP_MN_QUERYDIRECTORY

Yes, there is! If there are additional files, they would
not be seen this way.
In pseudo language, one needs to:

  • Do IoCallDriver (first call)
  • Filter the buffer
  • If at least one file is not hidden in the buffer, set
    Irp->IoStatus.Information to reflect the required data buffer
    size, and
    return STATUS_SUCCESS
  • If the buffer is empty, after filtering, re-call the
    lower driver, and do filtering again.
  • If the lower driver returns a non success code,
    return that code.

Just in case - to do IoCallDriver again, you must return
STATUS_MORE_PROCESSING_REQUIRED in the completion, and wait
on an event… then IoCompleteRequest the IRP.

Nicholas Ryan wrote:

> In the case where the file you’re skipping is the only file being
> returned, and you don’t want it to show, all you need to do is just
> return STATUS_NO_MORE_FILES (if AT LEAST one previous file was
> returned for this directory query) or STATUS_NO_SUCH_FILE (if NO
> previous files have been returned for this directory
query). There’s
> no reason you would have to query the lower driver again.


Kind regards, Dejan M. www.alfasp.com
E-mail: xxxxx@alfasp.com ICQ#: 56570367
Alfa File Monitor - File monitoring library for Win32
developers. Alfa File Protector - File protection and hiding
library for Win32 developers.


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

Thanx Dejan!

You mean that I should wait for the completion routine of the irp I
allocated to finish. In pseduo language:

  1. in completion routine, filter the buffer returned by lower-level driver
  2. If userbuffer length is 0, allocate new irp and IoCallDriver
  3. waiting for the completion of new irp’s completion routine to finish.
    (should i free the new irp in its completion routine)
    4, return

----- Original Message -----
From: “Dejan Maksimovic”
To: “File Systems Developers”
Sent: Monday, January 20, 2003 11:59 AM
Subject: [ntfsd] RE: Buffer Filter for IRP_MN_QUERYDIRECTORY

>
> Then you are doing something ELSE wrong.
> And looking at your code - YOU REALLY ARE! You are not waiting for the
> completion routine to finish, nor does it seem to be set! Thus you are not
> returning STATUS_MORE_PROCESSING_REQUIRED in it, and will eventually bug
check
> the system - I’m surprised you did not already:-)
>
> I suggest doing some studying around STATUS_MORE_PROCESSING_REQUIRED
and
> completion routines, before you take on this task. It will save you a lot
of
> headaches:-)
>
> –
> Kind regards, Dejan M. www.alfasp.com
> E-mail: xxxxx@alfasp.com ICQ#: 56570367
> Alfa File Monitor - File monitoring library for Win32 developers.
> Alfa File Protector - File protection and hiding library for Win32
developers.
>
>
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@occultsoft.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

Grr! Don’t allocate a new IRP…
In your dispatch, wait on an event that your completion sets (the completion
must do nothing except setting the event, and returning
STATUS_MORE_PROCESSING_REQUIRED - remember NOT to call IoMarkIrpPending then!)
In your dispatch process the buffer afterwards - use Irp->IoStatus.Status as
the status code, NOT the result of IoCallDriver, which will most of the time be
STATUS_PENDING, especially on removable media, on XP.
After you are finished processing the buffer, call IoCompleteRequest on the
IRP - as you returned SMPR from the completion, this is a must.

Regards, Dejan.

Ken Li wrote:

Thanx Dejan!

You mean that I should wait for the completion routine of the irp I
allocated to finish. In pseduo language:

  1. in completion routine, filter the buffer returned by lower-level driver
  2. If userbuffer length is 0, allocate new irp and IoCallDriver
  3. waiting for the completion of new irp’s completion routine to finish.
    (should i free the new irp in its completion routine)
    4, return


Kind regards, Dejan M. www.alfasp.com
E-mail: xxxxx@alfasp.com ICQ#: 56570367
Alfa File Monitor - File monitoring library for Win32 developers.
Alfa File Protector - File protection and hiding library for Win32 developers.