Randy’s post led me to discover a bug in the below algorithm (that I use
in my own driver). If you hide all of files in a query directory buffer,
then ask the filesystem for more, and the filesystem returns
STATUS_NO_MORE_FILES, you may in fact have to return STATUS_NO_SUCH_FILE
instead. Because the filesystem has returned at least one file up to
you, the filter, it will give you STATUS_NO_MORE_FILES if you ask for
more files and there are no more to give. But if you have hidden all of
the files returned by the filesystem, the caller has seen no files at
all so far, so you need to return STATUS_NO_SUCH_FILE instead of
STATUS_NO_MORE_FILES.
If you look in FastFat source, directory query state is maintained using
fields in the CCB structure, which is kept per-file object by the
filesystem. The first IRP_MN_QUERY_DIRECTORY send down on a newly-opened
directory handle begins the directory query, and each subsequent
IRP_MN_QUERY_DIRECTORY will return additional files.
As described above, your filter needs to know if, for the current
directory query, any files at all have been returned to the caller.
Since an individual query can encompass many separate
IRP_MN_QUERY_DIRECTORY requests, you need to maintain some per-query
state in your filter. I suggest you create a list keyed by file object
that contains a structure for each ongoing directory query in the
system. Mark in this structure whether any files have been returned up
to the caller so far.
Let’s see if we can pseudocode this algorithm into a workable state
(completely untested of course):
struct DirQueryInfo
{
PFILE_OBJECT fileObject;
BOOLEAN:1 bReturnedAnyFiles;
};
ProcessIrpMnQueryDirectory(pIrp, pIrpStack, FileObject)
{
DirQueryInfo *pQueryInfo;
// lookup dir query in our private list
pQueryInfo = LookupDirQuery(FileObject);
if (NULL == pQueryInfo)
{
// new dir query, track it
pQueryInfo = new DirQueryInfo; // check for NULL
pQueryInfo->fileObject = fileObject;
pQueryInfo->bReturnedAnyFiles = FALSE;
TrackDirQuery(pQueryInfo);
// on CLOSE of this file object, we will call
// StopTrackDirQuery to remove pQueryInfo from
// our list, then we delete pQueryInfo
}
// pass down request to filesystem and wait
status = PassDownIrpAndWait(pIrp);
if (STATUS_SUCCESS != status)
{
// filesystem is returning no files to filter
goto complete_irp;
}
while (TRUE)
{
// at this point we know the filesystem is returning some
// files to the filter
for (every entry in query buffer)
{
if (ShouldHideThisFileName(fileName))
remove this entry from query buffer;
}
if (!(query buffer is empty))
{
// we ARE returning files to caller, note this and return
pQueryInfo->bReturnedAnyFiles = TRUE;
status = STATUS_SUCCESS;
goto complete_irp;
}
// we’ve hidden all files that the filesystem gave us, ask it
// for more
// can’t let these flags go down again…
pIrpStack->Flags &= ~SL_INDEX_SPECIFIED;
pIrpStack->Flags &= ~SL_RESTART_SCAN;
status = PassDownIrpAndWait(Irp);
if (STATUS_SUCCESS == status)
{
// filesystem gave us more files, loop and examine them
}
else if (STATUS_NO_MORE_FILES == status)
{
// filesystem has no more files to give, but indicates
// that it had previously returned at least one file…
if (!pQueryInfo->bReturnedAnyFiles)
{
// … but if the filter has hidden all files that
// it has seen, return a different status
status = STATUS_NO_SUCH_FILE;
}
// complete IRP
goto complete_irp;
}
else
{
// assert that the filesystem thinks it has returned
// at least one file to us
ASSERT(STATUS_NO_SUCH_FILE != status);
// complete IRP with whatever status this is
goto complete_irp;
}
}
complete_irp:
complete with status
}
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Nicholas Ryan
Sent: Tuesday, April 29, 2003 4:01 PM
To: File Systems Developers
Subject: [ntfsd] RE: IRP_MN_QUERY_DIRECTORY on XP
Which value you return depends on the results of previous
directory queries on this handle. If you end up hiding
everything in the buffer, just call the underlying filesystem
again. If returns STATUS_SUCCESS, re-process the buffer
again, and if it returns STATUS_NO_SUCH_FILE or
STATUS_MORE_FILES, return that (not always one or the other).
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Rene
Gonzalez Rodriguez
Sent: Tuesday, April 29, 2003 3:37 PM
To: File Systems Developers
Subject: [ntfsd] RE: IRP_MN_QUERY_DIRECTORY on XP
Thanks Nicholas,
I have changed STATUS_NO_SUCH_FILE by STATUS_NO_MORE_FILES.
But exists another problem, I have the same bug.
If you have some another suggestion about difference between
IRP_MN_QUERY_DIRECTORY on XP and W2K.
In W2k my FSD work fine, it fail just in XP. I?m using W2K
DDK, it will be a problem in XP?
Thanks.
Voltus.
----- Original Message -----
From: “Nicholas Ryan”
> To: “File Systems Developers”
> Sent: Tuesday, April 29, 2003 3:13 PM
> Subject: [ntfsd] RE: IRP_MN_QUERY_DIRECTORY on XP
>
>
> > One problem is that you are always returning STATUS_NO_SUCH_FILE in
> the
> > case where your FilterDirectory function hides all of the
> files in the
> > current query directory buffer (at least this is what I think your
> code
> > is doing). You should be returning STATUS_NO_MORE_FILES
> instead if ANY
> > files have been returned for ANY previous directory query on this
> > handle.
> >
> > - Nick Ryan
> >
> > > -----Original Message-----
> > > From: xxxxx@lists.osr.com
> > > [mailto:xxxxx@lists.osr.com] On Behalf Of Rene
> > > Gonzalez Rodriguez
> > > Sent: Tuesday, April 29, 2003 1:50 PM
> > > To: File Systems Developers
> > > Subject: [ntfsd] IRP_MN_QUERY_DIRECTORY on XP
> > >
> > >
> > > Hi,
> > >
> > > I use IRP_MN_QUERY_DIRECTORY for HIDE in my File System
> > > Driver, and it work fine in alone PC, but when share some
> > > protected folder in a network all files apper more than
> > > once(Just in XP).
> > >
> > > e.g:
> > > 1. HIDE c:\windows*.txt
> > > 2.dir c:\windows (work OK, dir all files
> > > except *.txt).
> > > 3.dir \pc\windows (hide *.txt, but all others
> > > files apper
> > > more
> > > than once).
> > >
> > > What you think?
> > >
> > > It’s my code
> > >
> > > case IRP_MN_QUERY_DIRECTORY:
> > > // MN function parameters to get FileName,
> > > queryDirectory =
> > > (PQUERY_DIRECTORY)¤tIrpStack->Parameters;
> > >
> > > *nextIrpStack = *currentIrpStack;
> > >
> > > KeInitializeEvent(&EventHide,NotificationEvent,
> FALSE);
> > > // Put completion routine and pass the context
> > > to the event.
> > > IoSetCompletionRoutine( Irp, VFSXHideDone,
> > > (void *)&EventHide, TRUE, TRUE, TRUE );
> > > //
> > > // Return the results of the call to the caller
> > > //
> > >
> > > RC = IoCallDriver( hookExt->FileSystem, Irp );
> > > //DbgPrint((“Waiting for the event\n” ));
> > > // Wait
> > >
> > > KeWaitForSingleObject(&EventHide,Executive,KernelMode,TRUE,0);
> > > if (Irp->IoStatus.Status == STATUS_SUCCESS){
> > > RC = FilterDirectory(Irp, fullPathName); //
> > > This function check the buffer and filter the hide files
> > > if (RC){
> > > Irp->IoStatus.Status = STATUS_NO_SUCH_FILE;
> > > Irp->IoStatus.Information = 0;
> > > }
> > >
> > > if( fullPathName && fullPathName !=
> > > InsufficientResources ) {
> > > ExFreeToNPagedLookasideList(
> > > &FullPathLookaside, fullPathName );
> > > }
> > >
> > > // IoCompleteRequest(Irp, IO_NO_INCREMENT);
> > > IoCompleteRequest(Irp, IO_DISK_INCREMENT);
> > > return Irp->IoStatus.Status;
> > >
> > >
> > > break; // End IRP_MN_QUERY_DIRECTORY
> > >
> > >
> > > Thanks
> > >
> > > voltus
> > >
> > >
> > >
> > > ------------------------------------------------------------
> > > This message has been scanned for viruses and dangerous
> > > content by MailScan for MDaemon and is believed to be clean.
> > >
> > >
> > >
> > >
> > > —
> > > 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@esivic.cu
> > To unsubscribe send a blank email to xxxxx@lists.osr.com
> >
> > ------------------------------------------------------------
> > This message has been scanned for viruses and dangerous
> > content by MailScan for MDaemon and is believed to be clean.
> >
> > —
> You are currently subscribed to ntfsd as: xxxxx@nryan.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
> ------------------------------------------------------------
> This message has been scanned for viruses and dangerous
> content by MailScan for MDaemon and is believed to be clean.
>
>
>
> —
> You are currently subscribed to ntfsd as: xxxxx@nryan.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>