FastIoQueryOpen

Hi all:

I thought I understood the semantics of the FastIoQueryOpen routine. What I
thought was:

* If the FSD can handle this routine, it always returns TRUE.
* If the file is not present, then the EndOfFile field of the
FILE_NETWORK_OPEN_INFORMATION is 0, and the AllocationSize is NON-ZERO.
* If the file is present and the length is zero, then both the
AllocationSize and the EndOfFile fields are set to 0.
* If the file is present and has length, then both the AllocationSize
and EndOfFile fields are non-zero.

Apparently, I have something wrong. I implemented this in my FSD, and I’m
seeing many consecutive FastIoQueryOpen calls for the same (non-existent)
file – apparently, my method of signalling this fact is in error.

Given no documentation on this from Microsoft, can anybody tell me what I’m
doing wrong?

Thanks,
Curt

>I thought I understood the semantics of the FastIoQueryOpen routine. What

I thought was:
If the FSD can handle this routine, it always returns TRUE.

No.
The semantics is - if the file attributes (use the CurrentLoc of the
specified IRP in order to find the file object) can be retrieved in a fast
way, then retrieve them. Surely that the file name must exist for such a
thing.
Otherwise, return FALSE - this will force the IO manager to send
IRP_MJ_CREATE and then IRP_MJ_QUERY_INFORMATION to your FSD.
Fail there IRPs to fail the attribute query at all.

Filter drivers and FastIoQueryOpen note:

  • when calling the lower driver’s FastIoQueryOpen routine (FASTFAT have no
    such, NTFS has), do the following:

IoGetCurrentIrpStackLocation(Irp)->DeviceObject = TargetDeviceObject;
// Call target’s FastIoQueryOpen
TargetFastIo.FastIoQueryOpen(…);
// Use the device object specified as FastIoQueryOpen’s parameter here
IoGetCurrentIrpStackLocation(Irp)->DeviceObject = DeviceObject;

Forgetting to do this causes BSOD NTFS_FILE_SYSTEM with the code of
0x0019xxxx - the uncaught exception in NtfsPingVolume routine.

Max

Hi Max:

>I thought I understood the semantics of the FastIoQueryOpen
routine. What
>I thought was:
>If the FSD can handle this routine, it always returns TRUE.

No.
The semantics is - if the file attributes (use the CurrentLoc of the
specified IRP in order to find the file object) can be
retrieved in a fast
way, then retrieve them. Surely that the file name must exist
for such a
thing.
Otherwise, return FALSE - this will force the IO manager to send
IRP_MJ_CREATE and then IRP_MJ_QUERY_INFORMATION to your FSD.
Fail there IRPs to fail the attribute query at all.

This doesn’t match what I see from Filemon filtering an NTFS drive.

I see the FastIoQueryOpen calls to NTFS ALWAYS returning TRUE, regardless of
whether the file specified in the IRP exists or not.

This is used heavily when searching for DLLs for an app; there are
successful FastIoQueryOpen calls looking for a DLL in the same directory as
where the app resides – where there is no DLL present – followed by other
successful FastIoQueryOpen calls looking in a “standard” place (e.g.,
C:\WINNT\System32), followed by a successful CREATE IRP.

The only difference I see in the NETWORK_OPEN_INFORMATION buffer between the
two types of “successful” FastIoQueryOpen calls is:

  • in the case where the file exists, the buffer fields have reasonable
    values
  • in the case where the file doesn’t exist, the EOF size is 0, and all
    other fields are garbage (but not 0).

Any ideas why?

Thanks,
Curt

RE: [ntfsd] Re: FastIoQueryOpen>This doesn’t match what I see from Filemon
filtering an NTFS drive.

This matches the IopParseDevice machine code behavior - the one which calls
the FastIoQueryOpen routines of the filesystems.
Returning FALSE from FastIoQueryOpen forces the IO manager to use
CREATE/QUERY_INFORMATION IRPs to query the attributes.
FastIoQueryOpen is only used by 2 routines - NtQueryAttributesFile and
NtQueryFullAttributesFile - they use the pathname for input, not the handle,
and provide the pathname->attributes resolution without any handles.

  • in the case where the file doesn’t exist, the EOF size is 0, and all
    other fields are garbage (but not 0).
    Any ideas why?

FastIoQueryOpen can return:

  1. FALSE - see the description above.
    This forces NtQueryAttributesFile to go IRP_MJ_CREATE way.
  2. TRUE with Irp->IoStatus.Status set to STATUS_SUCCESS
  3. TRUE with Irp->IoStatus.Status set to error code.
    The latter one fails NtQueryAttributesFile without going IRP_MJ_CREATE way.

Max

THANK YOU MAX!

The Irp->IoStatus.Status field was the key – I didn’t intuit this.
Excellent!

Curt

FastIoQueryOpen can return:

  1. FALSE - see the description above.
    This forces NtQueryAttributesFile to go IRP_MJ_CREATE way.
  2. TRUE with Irp->IoStatus.Status set to STATUS_SUCCESS
  3. TRUE with Irp->IoStatus.Status set to error code.
    The latter one fails NtQueryAttributesFile without going
    IRP_MJ_CREATE way.