Another weird thing about ZwQueryDirectoryFile

Regarding to the previous post about ZwQueryDirectoryFile, now i’m at it
i was looking for a way to optimize my dir scan routine, by adding a
filemask.

trying the FileName parameter a PUNICODE_STRING, lets’say L"*.ext", it
still returns as if i put NULL (all the entries).

The code is the standard :

// browse 1st file
Status = ZwQueryDirectoryFile(hCacheDir, eventHandle, NULL, NULL, &Iosb,
FileInformationBuffer, FILEBLOCKINFOSIZE, FileDirectoryInformation,
TRUE,pExt, TRUE);

if (Status == STATUS_PENDING)
{
ZwWaitForSingleObject(eventHandle, TRUE, NULL);
KeClearEvent(pEventObject);
Status = Iosb.Status;
}

if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_FILES))
{
Status = STATUS_SUCCESS;
goto __exit;
}
// loop until no more files
while (TRUE)
{
// … // go on
next file
Status = ZwQueryDirectoryFile(hCacheDir, eventHandle, NULL, NULL,
&Iosb, FileInformationBuffer, FILEBLOCKINFOSIZE,
FileDirectoryInformation, TRUE, pExt, FALSE);
// …
// etc…etc…
}

Any clues ?

regards,
Valerio

You can only specify the file name parameter on the first call. It
caches the information and future changes to the parameter are ignored.
You would need to close the directory handle and re-open it to change
it.

Neal Christiansen
Microsoft File System Filter Group Lead
This posting is provided “AS IS” with no warranties, and confers no
rights

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of valerino
Sent: Tuesday, September 28, 2004 12:34 PM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] Another weird thing about ZwQueryDirectoryFile

Regarding to the previous post about ZwQueryDirectoryFile, now i’m at it
i was looking for a way to optimize my dir scan routine, by adding a
filemask.

trying the FileName parameter a PUNICODE_STRING, lets’say L"*.ext", it
still returns as if i put NULL (all the entries).

The code is the standard :

// browse 1st file
Status = ZwQueryDirectoryFile(hCacheDir, eventHandle, NULL, NULL, &Iosb,
FileInformationBuffer, FILEBLOCKINFOSIZE, FileDirectoryInformation,
TRUE,pExt, TRUE);

if (Status == STATUS_PENDING)
{
ZwWaitForSingleObject(eventHandle, TRUE, NULL);
KeClearEvent(pEventObject);
Status = Iosb.Status;
}

if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_FILES))
{
Status = STATUS_SUCCESS;
goto __exit;
}
// loop until no more files
while (TRUE)
{
// …
// go on
next file
Status = ZwQueryDirectoryFile(hCacheDir, eventHandle, NULL,
NULL,
&Iosb, FileInformationBuffer, FILEBLOCKINFOSIZE,
FileDirectoryInformation, TRUE, pExt, FALSE);
// …
// etc…etc…
}

Any clues ?

regards,
Valerio


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Neal, i do that… i specify filename as PUNICODE_STRING on the first
call with RtlInitUnicodeString (&myString,L"*.txt").
In the subsequent calls i pass NULL as Filename. Still, it gets all the
entries…
Maybe the dir handle must be opened with something particular ? i’m
still investigating it…

regards,
Valerio

Neal Christiansen wrote:

You can only specify the file name parameter on the first call. It
caches the information and future changes to the parameter are ignored.
You would need to close the directory handle and re-open it to change
it.

Neal Christiansen
Microsoft File System Filter Group Lead
This posting is provided “AS IS” with no warranties, and confers no
rights

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of valerino
Sent: Tuesday, September 28, 2004 12:34 PM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] Another weird thing about ZwQueryDirectoryFile

Regarding to the previous post about ZwQueryDirectoryFile, now i’m at it
i was looking for a way to optimize my dir scan routine, by adding a
filemask.

trying the FileName parameter a PUNICODE_STRING, lets’say L"*.ext", it
still returns as if i put NULL (all the entries).

The code is the standard :

// browse 1st file
Status = ZwQueryDirectoryFile(hCacheDir, eventHandle, NULL, NULL, &Iosb,
FileInformationBuffer, FILEBLOCKINFOSIZE, FileDirectoryInformation,
TRUE,pExt, TRUE);

if (Status == STATUS_PENDING)
{
ZwWaitForSingleObject(eventHandle, TRUE, NULL);
KeClearEvent(pEventObject);
Status = Iosb.Status;
}

if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_FILES))
{
Status = STATUS_SUCCESS;
goto __exit;
}
// loop until no more files
while (TRUE)
{
// …
// go on
next file
Status = ZwQueryDirectoryFile(hCacheDir, eventHandle, NULL,
NULL,
&Iosb, FileInformationBuffer, FILEBLOCKINFOSIZE,
FileDirectoryInformation, TRUE, pExt, FALSE);
// …
// etc…etc…
}

Any clues ?

regards,
Valerio


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Uhm, something is really goin’ wrong. I can’t think of what’s wrong with
my code, i have tried to roll my own irp too, but still no success. I
specify a filemask, and it still returns all file entries as with
FileName = NULL.

Here is the code i use to roll the irp :

/***********************************************************************/
NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE FileHandle, char*
FileMask, PVOID FileInfoBuffer, ULONG FileInfoLength, BOOLEAN
RestartScan, BOOLEAN ReturnSingleEntry)
{
NTSTATUS Status;
PIRP irp = NULL;
PDEVICE_OBJECT pDeviceObject = NULL;
PFILE_OBJECT pFileObject = NULL;
ANSI_STRING asName;
PIO_STACK_LOCATION irpSp;
IO_STATUS_BLOCK Iosb;
KEVENT Event;

// get device from fileobject
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
NULL,KernelMode,&pFileObject,NULL);

if (!pFileObject)
goto __exit;

// use base filesystem object directly
pDeviceObject = IoGetBaseFileSystemDeviceObject(pFileObject);
if (!pDeviceObject)
goto __exit;

// build irp
irp = IoAllocateIrp (pDeviceObject->StackSize,TRUE);
if (!irp)
goto __exit;

irpSp = IoGetNextIrpStackLocation(irp);

// fill irp params
irp->Tail.Overlay.Thread = PsGetCurrentThread();
KeInitializeEvent(&Event,NotificationEvent,FALSE);
irp->UserIosb = &Iosb;

irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
irp->UserBuffer = FileInfoBuffer;
irp->UserEvent = NULL;
irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
irp->Tail.Overlay.AuxiliaryBuffer = NULL;
irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
irp->Flags = (ULONG) (IRP_BUFFERED_IO | IRP_INPUT_OPERATION);

irpSp->Parameters.QueryDirectory.Length = FileInfoLength;
irpSp->Parameters.QueryDirectory.FileInformationClass =
FileDirectoryInformation;
irpSp->Parameters.QueryDirectory.FileIndex = 0;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
irpSp->FileObject = pFileObject;

// set completion routine which just set event and
// return MORE_PROCESSING_REQUIRED

irpSp->Context = &Event;
irpSp->CompletionRoutine = UtilSetEventCompletionRoutine;
irpSp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR |
SL_INVOKE_ON_CANCEL;

if (FileMask)
{
RtlInitAnsiString(&asName,FileMask);
irpSp->Parameters.QueryDirectory.FileName = &asName;
}
else
irpSp->Parameters.QueryDirectory.FileName = NULL;

if (RestartScan)
{
irpSp->Flags = SL_RESTART_SCAN;
}
if (ReturnSingleEntry)
{
irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
}

// fire IRP
Status = IoCallDriver (pDeviceObject,irp);
if (Status == STATUS_PENDING)
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);

Status = irp->IoStatus.Status;

__exit:
if (pFileObject)
ObDereferenceObject(pFileObject);
if (irp)
IoFreeIrp (irp);

return Status;
}
/***********************************************************************/

I call this function with :

Status = UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_FILES))
{
Status = STATUS_SUCCESS;
goto __exit;
}

// … process first returned buffer here …

// then loop for every other entries in the directory
while (TRUE)
{
// … process returned buffer here …

// go on next file
Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);

if (!NT_SUCCESS(Status))
{
if (Status == STATUS_NO_MORE_FILES)
{
Status = STATUS_SUCCESS;
}
break;
}
}

I think my implementation is the same as ZwQueryDirectoryFile, but still
the same result. Please tell me what’s wrong (i’d like to use
ZwQueryDirectoryFile directly, using my own irp was just a test).
Ah… i’ve used an ANSI_STRING for the filename, since i’ve found that
the OS cast it to a PSTRING ( = ANSI_STRING, from ntdef.h) when building
the irp. Still, if i use unicode, same result (as for ZwQueryDirectoryFile).

waiting clues…

regards,
Valerio

Try using a Unicode string - the interface supports UNICODE only. I’m
not sure what it would do when presented with an ANSI string that it
thinks is a UNICODE string.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of valerino
Sent: Wednesday, September 29, 2004 12:21 PM
To: ntfsd redirect
Subject: Re:[ntfsd] Another weird thing about ZwQueryDirectoryFile

Uhm, something is really goin’ wrong. I can’t think of what’s wrong with
my code, i have tried to roll my own irp too, but still no success. I
specify a filemask, and it still returns all file entries as with
FileName = NULL.

Here is the code i use to roll the irp :

/***********************************************************************
/
NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE FileHandle, char*
FileMask, PVOID FileInfoBuffer, ULONG FileInfoLength, BOOLEAN
RestartScan, BOOLEAN ReturnSingleEntry)
{
NTSTATUS Status;
PIRP irp = NULL;
PDEVICE_OBJECT pDeviceObject = NULL;
PFILE_OBJECT pFileObject = NULL;
ANSI_STRING asName;
PIO_STACK_LOCATION irpSp;
IO_STATUS_BLOCK Iosb;
KEVENT Event;

// get device from fileobject
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
NULL,KernelMode,&pFileObject,NULL);

if (!pFileObject)
goto __exit;

// use base filesystem object directly
pDeviceObject = IoGetBaseFileSystemDeviceObject(pFileObject);
if (!pDeviceObject)
goto __exit;

// build irp
irp = IoAllocateIrp (pDeviceObject->StackSize,TRUE);
if (!irp)
goto __exit;

irpSp = IoGetNextIrpStackLocation(irp);

// fill irp params
irp->Tail.Overlay.Thread = PsGetCurrentThread();
KeInitializeEvent(&Event,NotificationEvent,FALSE);
irp->UserIosb = &Iosb;

irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
irp->UserBuffer = FileInfoBuffer;
irp->UserEvent = NULL;
irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
irp->Tail.Overlay.AuxiliaryBuffer = NULL;
irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
irp->Flags = (ULONG) (IRP_BUFFERED_IO | IRP_INPUT_OPERATION);

irpSp->Parameters.QueryDirectory.Length = FileInfoLength;
irpSp->Parameters.QueryDirectory.FileInformationClass =
FileDirectoryInformation;
irpSp->Parameters.QueryDirectory.FileIndex = 0;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
irpSp->FileObject = pFileObject;

// set completion routine which just set event and
// return MORE_PROCESSING_REQUIRED

irpSp->Context = &Event;
irpSp->CompletionRoutine = UtilSetEventCompletionRoutine;
irpSp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR |
SL_INVOKE_ON_CANCEL;

if (FileMask)
{
RtlInitAnsiString(&asName,FileMask);
irpSp->Parameters.QueryDirectory.FileName = &asName;
}
else
irpSp->Parameters.QueryDirectory.FileName = NULL;

if (RestartScan)
{
irpSp->Flags = SL_RESTART_SCAN;
}
if (ReturnSingleEntry)
{
irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
}

// fire IRP
Status = IoCallDriver (pDeviceObject,irp);
if (Status == STATUS_PENDING)

KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);

Status = irp->IoStatus.Status;

__exit:
if (pFileObject)
ObDereferenceObject(pFileObject);
if (irp)
IoFreeIrp (irp);

return Status;
}
/***********************************************************************
/

I call this function with :

Status = UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_FILES))
{
Status = STATUS_SUCCESS;
goto __exit;
}

// … process first returned buffer here …

// then loop for every other entries in the directory
while (TRUE)
{
// … process returned buffer here …

// go on next file
Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);

if (!NT_SUCCESS(Status))
{
if (Status == STATUS_NO_MORE_FILES)
{
Status = STATUS_SUCCESS;
}
break;
}
}

I think my implementation is the same as ZwQueryDirectoryFile, but still
the same result. Please tell me what’s wrong (i’d like to use
ZwQueryDirectoryFile directly, using my own irp was just a test).
Ah… i’ve used an ANSI_STRING for the filename, since i’ve found that
the OS cast it to a PSTRING ( = ANSI_STRING, from ntdef.h) when building

the irp. Still, if i use unicode, same result (as for
ZwQueryDirectoryFile).

waiting clues…

regards,
Valerio


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

The search string is a unicode string.

Maybe try “<.txt”.

Tony Mason said in a previous post:
There are five wildcard characters in the Windows
pattern matching
syntax (that is the syntax implemented by
FsRtlIsNameInExpression, that
venerable and nearly inscrutable function.)

* = “match one or more characters”
? = “match one character”
< = “match one or more characters using MS-DOS
semantics”

= “match one character using MS-DOS semantics”
" = “match dot using MS-DOS semantics”

Thus, the last three are for MS-DOS compatibility,
which restricts the
character set that can match. For example, spaces are
allowed in MS-DOS
names, but not before or after the dot. These MS-DOS
patterns match
those semantics.

For building your own strings, I highly recommend
sticking with the
Windows semantics, not the MS-DOS semantics.

— valerino wrote:

> Uhm, something is really goin’ wrong. I can’t think
> of what’s wrong with
> my code, i have tried to roll my own irp too, but
> still no success. I
> specify a filemask, and it still returns all file
> entries as with
> FileName = NULL.
>
> Here is the code i use to roll the irp :
>
>
//
> NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE
> FileHandle, char*
> FileMask, PVOID FileInfoBuffer, ULONG
> FileInfoLength, BOOLEAN
> RestartScan, BOOLEAN ReturnSingleEntry)
> {
> NTSTATUS Status;
> PIRP irp = NULL;
> PDEVICE_OBJECT pDeviceObject = NULL;
> PFILE_OBJECT pFileObject = NULL;
> ANSI_STRING asName;
> PIO_STACK_LOCATION irpSp;
> IO_STATUS_BLOCK Iosb;
> KEVENT Event;
>
> // get device from fileobject
>
>
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
> NULL,KernelMode,&pFileObject,NULL);
>
> if (!pFileObject)
> goto __exit;
>
> // use base filesystem object directly
> pDeviceObject =
> IoGetBaseFileSystemDeviceObject(pFileObject);
> if (!pDeviceObject)
> goto__exit;
>
> // build irp
> irp = IoAllocateIrp
> (pDeviceObject->StackSize,TRUE);
> if (!irp)
> goto __exit;
>
> irpSp = IoGetNextIrpStackLocation(irp);
>
> // fill irp params
> irp->Tail.Overlay.Thread = PsGetCurrentThread();
>
> KeInitializeEvent(&Event,NotificationEvent,FALSE);
> irp->UserIosb = &Iosb;
>
> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> irp->MdlAddress = (PMDL) NULL;
> irp->UserBuffer = FileInfoBuffer;
> irp->UserEvent = NULL;
>
> irp->Overlay.AsynchronousParameters.UserApcRoutine =
> NULL;
>
> irp->Overlay.AsynchronousParameters.UserApcContext =
> NULL;
> irp->Tail.Overlay.AuxiliaryBuffer = NULL;
> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> irp->MdlAddress = (PMDL) NULL;
> irp->Flags = (ULONG) (IRP_BUFFERED_IO |
> IRP_INPUT_OPERATION);
>
> irpSp->Parameters.QueryDirectory.Length =
> FileInfoLength;
>
>
irpSp->Parameters.QueryDirectory.FileInformationClass
> =
> FileDirectoryInformation;
> irpSp->Parameters.QueryDirectory.FileIndex = 0;
> irpSp = IoGetNextIrpStackLocation( irp );
> irpSp->MajorFunction =
> IRP_MJ_DIRECTORY_CONTROL;
> irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
> irpSp->FileObject = pFileObject;
>
> // set completion routine which just set event and
> // return MORE_PROCESSING_REQUIRED
>
> irpSp->Context = &Event;
> irpSp->CompletionRoutine =
> UtilSetEventCompletionRoutine;
> irpSp->Control = SL_INVOKE_ON_SUCCESS |
> SL_INVOKE_ON_ERROR |
> SL_INVOKE_ON_CANCEL;
>
> if (FileMask)
> {
> RtlInitAnsiString(&asName,FileMask);
> irpSp->Parameters.QueryDirectory.FileName =
> &asName;
> }
> else
> irpSp->Parameters.QueryDirectory.FileName = NULL;
>
> if (RestartScan)
> {
> irpSp->Flags = SL_RESTART_SCAN;
> }
> if (ReturnSingleEntry)
> {
> irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
> }
>
> // fire IRP
> Status = IoCallDriver (pDeviceObject,irp);
> if (Status == STATUS_PENDING)
>
>
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
>
> Status = irp->IoStatus.Status;
>
>__exit:
> if (pFileObject)
> ObDereferenceObject(pFileObject);
> if (irp)
> IoFreeIrp (irp);
>
> return Status;
> }
>
/
/
>
> I call this function with :
>
> Status =
> UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
> FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
> if (!NT_SUCCESS(Status) && (Status !=
> STATUS_NO_MORE_FILES))
> {
> Status = STATUS_SUCCESS;
> goto __exit;
> }
>
> // … process first returned buffer here
> …
>
> // then loop for every other entries in the
> directory
> while (TRUE)
> {
> // … process returned buffer here
> …
>
> // go on next file
> Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
>
> FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);
>
> if (!NT_SUCCESS(Status))
> {
> if (Status == STATUS_NO_MORE_FILES)
> {
> Status = STATUS_SUCCESS;
> }
> break;
> }
> }
>
> I think my implementation is the same as
> ZwQueryDirectoryFile, but still
> the same result. Please tell me what’s wrong (i’d
> like to use
> ZwQueryDirectoryFile directly, using my own irp was
> just a test).
> Ah… i’ve used an ANSI_STRING for the filename,
> since i’ve found that
> the OS cast it to a PSTRING ( = ANSI_STRING, from
> ntdef.h) when building
> the irp. Still, if i use unicode, same result (as
> for ZwQueryDirectoryFile).
>
> waiting clues…
>
> regards,
> Valerio
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as:
> xxxxx@yahoo.com
> To unsubscribe send a blank email to
> xxxxx@lists.osr.com
>

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail

Also, what happens if you uppercase…“*.TXT”?

— valerino wrote:

> Uhm, something is really goin’ wrong. I can’t think
> of what’s wrong with
> my code, i have tried to roll my own irp too, but
> still no success. I
> specify a filemask, and it still returns all file
> entries as with
> FileName = NULL.
>
> Here is the code i use to roll the irp :
>
>
//
> NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE
> FileHandle, char*
> FileMask, PVOID FileInfoBuffer, ULONG
> FileInfoLength, BOOLEAN
> RestartScan, BOOLEAN ReturnSingleEntry)
> {
> NTSTATUS Status;
> PIRP irp = NULL;
> PDEVICE_OBJECT pDeviceObject = NULL;
> PFILE_OBJECT pFileObject = NULL;
> ANSI_STRING asName;
> PIO_STACK_LOCATION irpSp;
> IO_STATUS_BLOCK Iosb;
> KEVENT Event;
>
> // get device from fileobject
>
>
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
> NULL,KernelMode,&pFileObject,NULL);
>
> if (!pFileObject)
> goto __exit;
>
> // use base filesystem object directly
> pDeviceObject =
> IoGetBaseFileSystemDeviceObject(pFileObject);
> if (!pDeviceObject)
> goto__exit;
>
> // build irp
> irp = IoAllocateIrp
> (pDeviceObject->StackSize,TRUE);
> if (!irp)
> goto __exit;
>
> irpSp = IoGetNextIrpStackLocation(irp);
>
> // fill irp params
> irp->Tail.Overlay.Thread = PsGetCurrentThread();
>
> KeInitializeEvent(&Event,NotificationEvent,FALSE);
> irp->UserIosb = &Iosb;
>
> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> irp->MdlAddress = (PMDL) NULL;
> irp->UserBuffer = FileInfoBuffer;
> irp->UserEvent = NULL;
>
> irp->Overlay.AsynchronousParameters.UserApcRoutine =
> NULL;
>
> irp->Overlay.AsynchronousParameters.UserApcContext =
> NULL;
> irp->Tail.Overlay.AuxiliaryBuffer = NULL;
> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> irp->MdlAddress = (PMDL) NULL;
> irp->Flags = (ULONG) (IRP_BUFFERED_IO |
> IRP_INPUT_OPERATION);
>
> irpSp->Parameters.QueryDirectory.Length =
> FileInfoLength;
>
>
irpSp->Parameters.QueryDirectory.FileInformationClass
> =
> FileDirectoryInformation;
> irpSp->Parameters.QueryDirectory.FileIndex = 0;
> irpSp = IoGetNextIrpStackLocation( irp );
> irpSp->MajorFunction =
> IRP_MJ_DIRECTORY_CONTROL;
> irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
> irpSp->FileObject = pFileObject;
>
> // set completion routine which just set event and
> // return MORE_PROCESSING_REQUIRED
>
> irpSp->Context = &Event;
> irpSp->CompletionRoutine =
> UtilSetEventCompletionRoutine;
> irpSp->Control = SL_INVOKE_ON_SUCCESS |
> SL_INVOKE_ON_ERROR |
> SL_INVOKE_ON_CANCEL;
>
> if (FileMask)
> {
> RtlInitAnsiString(&asName,FileMask);
> irpSp->Parameters.QueryDirectory.FileName =
> &asName;
> }
> else
> irpSp->Parameters.QueryDirectory.FileName = NULL;
>
> if (RestartScan)
> {
> irpSp->Flags = SL_RESTART_SCAN;
> }
> if (ReturnSingleEntry)
> {
> irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
> }
>
> // fire IRP
> Status = IoCallDriver (pDeviceObject,irp);
> if (Status == STATUS_PENDING)
>
>
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
>
> Status = irp->IoStatus.Status;
>
>__exit:
> if (pFileObject)
> ObDereferenceObject(pFileObject);
> if (irp)
> IoFreeIrp (irp);
>
> return Status;
> }
>
/
/
>
> I call this function with :
>
> Status =
> UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
> FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
> if (!NT_SUCCESS(Status) && (Status !=
> STATUS_NO_MORE_FILES))
> {
> Status = STATUS_SUCCESS;
> goto __exit;
> }
>
> // … process first returned buffer here
> …
>
> // then loop for every other entries in the
> directory
> while (TRUE)
> {
> // … process returned buffer here
> …
>
> // go on next file
> Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
>
> FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);
>
> if (!NT_SUCCESS(Status))
> {
> if (Status == STATUS_NO_MORE_FILES)
> {
> Status = STATUS_SUCCESS;
> }
> break;
> }
> }
>
> I think my implementation is the same as
> ZwQueryDirectoryFile, but still
> the same result. Please tell me what’s wrong (i’d
> like to use
> ZwQueryDirectoryFile directly, using my own irp was
> just a test).
> Ah… i’ve used an ANSI_STRING for the filename,
> since i’ve found that
> the OS cast it to a PSTRING ( = ANSI_STRING, from
> ntdef.h) when building
> the irp. Still, if i use unicode, same result (as
> for ZwQueryDirectoryFile).
>
> waiting clues…
>
> regards,
> Valerio
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as:
> xxxxx@yahoo.com
> To unsubscribe send a blank email to
> xxxxx@lists.osr.com
>

_______________________________
Do you Yahoo!?
Declare Yourself - Register online to vote today!
http://vote.yahoo.com

I’m confused. How can the search string be a Unicode string? What I
see is:
if (FileMask)
{
RtlInitAnsiString(&asName,FileMask);
irpSp->Parameters.QueryDirectory.FileName =
&asName;
}

Maybe I don’t understand the code (that’s possible) but when I read this
it looked like it was initializing an ANSI string. I see that the
original comments indicated they tried with a UNICODE string, but if
this routine were passed an ANSI string and initialized into a UNICODE
structure, it wouldn’t work right. If this same code were used with a
wide character string, it wouldn’t work right.

I know this API works. The results obtained indicate that the caller
thinks this is a wildcard search - and that would fit with passing in a
zero length search string or possibly an invalid string. FAT at least
validates the UNICODE_STRING structure (ensuring the # of bytes is even,
for instance) but I can’t see how it will return EVERYTHING if you pass
a valid name into it. The only way that seems to happen is a zero
length string or explicit search request.

What am I missing?

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Randy Cook
Sent: Wednesday, September 29, 2004 1:08 PM
To: ntfsd redirect
Subject: Re:[ntfsd] Another weird thing about ZwQueryDirectoryFile

The search string is a unicode string.

Maybe try “<.txt”.

Tony Mason said in a previous post:
There are five wildcard characters in the Windows
pattern matching
syntax (that is the syntax implemented by
FsRtlIsNameInExpression, that
venerable and nearly inscrutable function.)

* = “match one or more characters”
? = “match one character”
< = “match one or more characters using MS-DOS
semantics”

= “match one character using MS-DOS semantics”
" = “match dot using MS-DOS semantics”

Thus, the last three are for MS-DOS compatibility,
which restricts the
character set that can match. For example, spaces are
allowed in MS-DOS
names, but not before or after the dot. These MS-DOS
patterns match
those semantics.

For building your own strings, I highly recommend
sticking with the
Windows semantics, not the MS-DOS semantics.

— valerino wrote:

> Uhm, something is really goin’ wrong. I can’t think
> of what’s wrong with
> my code, i have tried to roll my own irp too, but
> still no success. I
> specify a filemask, and it still returns all file
> entries as with
> FileName = NULL.
>
> Here is the code i use to roll the irp :
>
>
/
/
> NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE
> FileHandle, char*
> FileMask, PVOID FileInfoBuffer, ULONG
> FileInfoLength, BOOLEAN
> RestartScan, BOOLEAN ReturnSingleEntry)
> {
> NTSTATUS Status;
> PIRP irp = NULL;
> PDEVICE_OBJECT pDeviceObject = NULL;
> PFILE_OBJECT pFileObject = NULL;
> ANSI_STRING asName;
> PIO_STACK_LOCATION irpSp;
> IO_STATUS_BLOCK Iosb;
> KEVENT Event;
>
> // get device from fileobject
>
>
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
> NULL,KernelMode,&pFileObject,NULL);
>
> if (!pFileObject)
> goto __exit;
>
> // use base filesystem object directly
> pDeviceObject =
> IoGetBaseFileSystemDeviceObject(pFileObject);
> if (!pDeviceObject)
> goto__exit;
>
> // build irp
> irp = IoAllocateIrp
> (pDeviceObject->StackSize,TRUE);
> if (!irp)
> goto __exit;
>
> irpSp = IoGetNextIrpStackLocation(irp);
>
> // fill irp params
> irp->Tail.Overlay.Thread = PsGetCurrentThread();
>
> KeInitializeEvent(&Event,NotificationEvent,FALSE);
> irp->UserIosb = &Iosb;
>
> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> irp->MdlAddress = (PMDL) NULL;
> irp->UserBuffer = FileInfoBuffer;
> irp->UserEvent = NULL;
>
> irp->Overlay.AsynchronousParameters.UserApcRoutine =
> NULL;
>
> irp->Overlay.AsynchronousParameters.UserApcContext =
> NULL;
> irp->Tail.Overlay.AuxiliaryBuffer = NULL;
> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> irp->MdlAddress = (PMDL) NULL;
> irp->Flags = (ULONG) (IRP_BUFFERED_IO |
> IRP_INPUT_OPERATION);
>
> irpSp->Parameters.QueryDirectory.Length =
> FileInfoLength;
>
>
irpSp->Parameters.QueryDirectory.FileInformationClass
> =
> FileDirectoryInformation;
> irpSp->Parameters.QueryDirectory.FileIndex = 0;
> irpSp = IoGetNextIrpStackLocation( irp );
> irpSp->MajorFunction =
> IRP_MJ_DIRECTORY_CONTROL;
> irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
> irpSp->FileObject = pFileObject;
>
> // set completion routine which just set event and
> // return MORE_PROCESSING_REQUIRED
>
> irpSp->Context = &Event;
> irpSp->CompletionRoutine =
> UtilSetEventCompletionRoutine;
> irpSp->Control = SL_INVOKE_ON_SUCCESS |
> SL_INVOKE_ON_ERROR |
> SL_INVOKE_ON_CANCEL;
>
> if (FileMask)
> {
> RtlInitAnsiString(&asName,FileMask);
> irpSp->Parameters.QueryDirectory.FileName =
> &asName;
> }
> else
> irpSp->Parameters.QueryDirectory.FileName = NULL;
>
> if (RestartScan)
> {
> irpSp->Flags = SL_RESTART_SCAN;
> }
> if (ReturnSingleEntry)
> {
> irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
> }
>
> // fire IRP
> Status = IoCallDriver (pDeviceObject,irp);
> if (Status == STATUS_PENDING)
>
>
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
>
> Status = irp->IoStatus.Status;
>
>__exit:
> if (pFileObject)
> ObDereferenceObject(pFileObject);
> if (irp)
> IoFreeIrp (irp);
>
> return Status;
> }
>
/

/
>
> I call this function with :
>
> Status =
> UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
> FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
> if (!NT_SUCCESS(Status) && (Status !=
> STATUS_NO_MORE_FILES))
> {
> Status = STATUS_SUCCESS;
> goto __exit;
> }
>
> // … process first returned buffer here
> …
>
> // then loop for every other entries in the
> directory
> while (TRUE)
> {
> // … process returned buffer here
> …
>
> // go on next file
> Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
>
> FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);
>
> if (!NT_SUCCESS(Status))
> {
> if (Status == STATUS_NO_MORE_FILES)
> {
> Status = STATUS_SUCCESS;
> }
> break;
> }
> }
>
> I think my implementation is the same as
> ZwQueryDirectoryFile, but still
> the same result. Please tell me what’s wrong (i’d
> like to use
> ZwQueryDirectoryFile directly, using my own irp was
> just a test).
> Ah… i’ve used an ANSI_STRING for the filename,
> since i’ve found that
> the OS cast it to a PSTRING ( = ANSI_STRING, from
> ntdef.h) when building
> the irp. Still, if i use unicode, same result (as
> for ZwQueryDirectoryFile).
>
> waiting clues…
>
> regards,
> Valerio
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as:
> xxxxx@yahoo.com
> To unsubscribe send a blank email to
> xxxxx@lists.osr.com
>

__________________________________
Do you Yahoo!?
New and Improved Yahoo! Mail - 100MB free storage!
http://promotions.yahoo.com/new_mail


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Sorry Tony, i think i replied to your private email, i was using my new
Mac and i probably hit the wrong “send to” :slight_smile:

Anyway,
i’ve surely tried with UNICODE! I’ve tried with ANSI too since
irpSp->Parameters.QueryDirectory.FileName is a PSTRING, and PSTRING is
defined as PANSI_STRING in ntdef.h

As far Randy said, yes … even with the syntax you suggested (where the
hell have you found that info ? never known about that!), it still
returns every entry. The FileName parameter is simply ignored.

The OS i’m testing with is XP SP1, i wonder if noone else noticed that
before ? I still hope its a bug in my code…

Tony Mason wrote:

Try using a Unicode string - the interface supports UNICODE only. I’m
not sure what it would do when presented with an ANSI string that it
thinks is a UNICODE string.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of valerino
Sent: Wednesday, September 29, 2004 12:21 PM
To: ntfsd redirect
Subject: Re:[ntfsd] Another weird thing about ZwQueryDirectoryFile

Uhm, something is really goin’ wrong. I can’t think of what’s wrong with
my code, i have tried to roll my own irp too, but still no success. I
specify a filemask, and it still returns all file entries as with
FileName = NULL.

Here is the code i use to roll the irp :

/***********************************************************************
/
NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE FileHandle, char*
FileMask, PVOID FileInfoBuffer, ULONG FileInfoLength, BOOLEAN
RestartScan, BOOLEAN ReturnSingleEntry)
{
NTSTATUS Status;
PIRP irp = NULL;
PDEVICE_OBJECT pDeviceObject = NULL;
PFILE_OBJECT pFileObject = NULL;
ANSI_STRING asName;
PIO_STACK_LOCATION irpSp;
IO_STATUS_BLOCK Iosb;
KEVENT Event;

// get device from fileobject
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
NULL,KernelMode,&pFileObject,NULL);

if (!pFileObject)
goto __exit;

// use base filesystem object directly
pDeviceObject = IoGetBaseFileSystemDeviceObject(pFileObject);
if (!pDeviceObject)
goto __exit;

// build irp
irp = IoAllocateIrp (pDeviceObject->StackSize,TRUE);
if (!irp)
goto __exit;

irpSp = IoGetNextIrpStackLocation(irp);

// fill irp params
irp->Tail.Overlay.Thread = PsGetCurrentThread();
KeInitializeEvent(&Event,NotificationEvent,FALSE);
irp->UserIosb = &Iosb;

irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
irp->UserBuffer = FileInfoBuffer;
irp->UserEvent = NULL;
irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
irp->Overlay.AsynchronousParameters.UserApcContext = NULL;
irp->Tail.Overlay.AuxiliaryBuffer = NULL;
irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
irp->MdlAddress = (PMDL) NULL;
irp->Flags = (ULONG) (IRP_BUFFERED_IO | IRP_INPUT_OPERATION);

irpSp->Parameters.QueryDirectory.Length = FileInfoLength;
irpSp->Parameters.QueryDirectory.FileInformationClass =
FileDirectoryInformation;
irpSp->Parameters.QueryDirectory.FileIndex = 0;
irpSp = IoGetNextIrpStackLocation( irp );
irpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
irpSp->FileObject = pFileObject;

// set completion routine which just set event and
// return MORE_PROCESSING_REQUIRED

irpSp->Context = &Event;
irpSp->CompletionRoutine = UtilSetEventCompletionRoutine;
irpSp->Control = SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR |
SL_INVOKE_ON_CANCEL;

if (FileMask)
{
RtlInitAnsiString(&asName,FileMask);
irpSp->Parameters.QueryDirectory.FileName = &asName;
}
else
irpSp->Parameters.QueryDirectory.FileName = NULL;

if (RestartScan)
{
irpSp->Flags = SL_RESTART_SCAN;
}
if (ReturnSingleEntry)
{
irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
}

// fire IRP
Status = IoCallDriver (pDeviceObject,irp);
if (Status == STATUS_PENDING)

KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);

Status = irp->IoStatus.Status;

__exit:
if (pFileObject)
ObDereferenceObject(pFileObject);
if (irp)
IoFreeIrp (irp);

return Status;
}
/***********************************************************************
/

I call this function with :

Status = UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
if (!NT_SUCCESS(Status) && (Status != STATUS_NO_MORE_FILES))
{
Status = STATUS_SUCCESS;
goto __exit;
}

// … process first returned buffer here …

// then loop for every other entries in the directory
while (TRUE)
{
// … process returned buffer here …

// go on next file
Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);

if (!NT_SUCCESS(Status))
{
if (Status == STATUS_NO_MORE_FILES)
{
Status = STATUS_SUCCESS;
}
break;
}
}

I think my implementation is the same as ZwQueryDirectoryFile, but still
the same result. Please tell me what’s wrong (i’d like to use
ZwQueryDirectoryFile directly, using my own irp was just a test).
Ah… i’ve used an ANSI_STRING for the filename, since i’ve found that
the OS cast it to a PSTRING ( = ANSI_STRING, from ntdef.h) when building

the irp. Still, if i use unicode, same result (as for
ZwQueryDirectoryFile).

waiting clues…

regards,
Valerio


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

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

Sorry for the confusion… That’s my message to
HIM… that the parameter SHOULD be a unicode string.

I replied to him before I saw your reply.

— Tony Mason wrote:

> I’m confused. How can the search string be a
> Unicode string? What I
> see is:
> if (FileMask)
> {
> RtlInitAnsiString(&asName,FileMask);
> irpSp->Parameters.QueryDirectory.FileName =
> &asName;
> }
>
> Maybe I don’t understand the code (that’s possible)
> but when I read this
> it looked like it was initializing an ANSI string.
> I see that the
> original comments indicated they tried with a
> UNICODE string, but if
> this routine were passed an ANSI string and
> initialized into a UNICODE
> structure, it wouldn’t work right. If this same
> code were used with a
> wide character string, it wouldn’t work right.
>
> I know this API works. The results obtained
> indicate that the caller
> thinks this is a wildcard search - and that would
> fit with passing in a
> zero length search string or possibly an invalid
> string. FAT at least
> validates the UNICODE_STRING structure (ensuring the
> # of bytes is even,
> for instance) but I can’t see how it will return
> EVERYTHING if you pass
> a valid name into it. The only way that seems to
> happen is a zero
> length string or explicit search request.
>
> What am I missing?
>
> Regards,
>
> Tony
>
> Tony Mason
> Consulting Partner
> OSR Open Systems Resources, Inc.
> http://www.osr.com
>
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of
> Randy Cook
> Sent: Wednesday, September 29, 2004 1:08 PM
> To: ntfsd redirect
> Subject: Re:[ntfsd] Another weird thing about
> ZwQueryDirectoryFile
>
> The search string is a unicode string.
>
> Maybe try “<.txt”.
>
> Tony Mason said in a previous post:
> There are five wildcard characters in the Windows
> pattern matching
> syntax (that is the syntax implemented by
> FsRtlIsNameInExpression, that
> venerable and nearly inscrutable function.)
>
> * = “match one or more characters”
> ? = “match one character”
> < = “match one or more characters using MS-DOS
> semantics”
> > = “match one character using MS-DOS semantics”
> " = “match dot using MS-DOS semantics”
>
> Thus, the last three are for MS-DOS compatibility,
> which restricts the
> character set that can match. For example, spaces
> are
> allowed in MS-DOS
> names, but not before or after the dot. These
> MS-DOS
> patterns match
> those semantics.
>
> For building your own strings, I highly recommend
> sticking with the
> Windows semantics, not the MS-DOS semantics.
>
>
> — valerino wrote:
>
> > Uhm, something is really goin’ wrong. I can’t
> think
> > of what’s wrong with
> > my code, i have tried to roll my own irp too, but
> > still no success. I
> > specify a filemask, and it still returns all file
> > entries as with
> > FileName = NULL.
> >
> > Here is the code i use to roll the irp :
> >
> >
>
/ ***********************************************************************
> /
> > NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE
> > FileHandle, char*
> > FileMask, PVOID FileInfoBuffer, ULONG
> > FileInfoLength, BOOLEAN
> > RestartScan, BOOLEAN ReturnSingleEntry)
> > {
> > NTSTATUS Status;
> > PIRP irp = NULL;
> > PDEVICE_OBJECT pDeviceObject = NULL;
> > PFILE_OBJECT pFileObject = NULL;
> > ANSI_STRING asName;
> > PIO_STACK_LOCATION irpSp;
> > IO_STATUS_BLOCK Iosb;
> > KEVENT Event;
> >
> > // get device from fileobject
> >
> >
>
ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
> > NULL,KernelMode,&pFileObject,NULL);
> >
> > if (!pFileObject)
> > goto __exit;
> >
> > // use base filesystem object directly
> > pDeviceObject =
> > IoGetBaseFileSystemDeviceObject(pFileObject);
> > if (!pDeviceObject)
> > goto__exit;
> >
> > // build irp
> > irp = IoAllocateIrp
> > (pDeviceObject->StackSize,TRUE);
> > if (!irp)
> > goto __exit;
> >
> > irpSp = IoGetNextIrpStackLocation(irp);
> >
> > // fill irp params
> > irp->Tail.Overlay.Thread = PsGetCurrentThread();
> >
> > KeInitializeEvent(&Event,NotificationEvent,FALSE);
> > irp->UserIosb = &Iosb;
> >
> > irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
> > irp->MdlAddress = (PMDL) NULL;
> > irp->UserBuffer = FileInfoBuffer;
> > irp->UserEvent = NULL;
> >
> > irp->Overlay.AsynchronousParameters.UserApcRoutine
> =
> > NULL;
> >
> > irp->Overlay.AsynchronousParameters.UserApcContext
> =
> > NULL;
> > irp->Tail.Overlay.AuxiliaryBuffer = NULL;
> > irp->AssociatedIrp.SystemBuffer = (PVOID)
> NULL;
> > irp->MdlAddress = (PMDL) NULL;
> > irp->Flags = (ULONG) (IRP_BUFFERED_IO |
> > IRP_INPUT_OPERATION);
> >
> > irpSp->Parameters.QueryDirectory.Length =
> > FileInfoLength;
> >
> >
>
irpSp->Parameters.QueryDirectory.FileInformationClass
> > =
> > FileDirectoryInformation;
> > irpSp->Parameters.QueryDirectory.FileIndex =
> 0;
> > irpSp = IoGetNextIrpStackLocation( irp );
> > irpSp->MajorFunction =
> > IRP_MJ_DIRECTORY_CONTROL;
> > irpSp->MinorFunction =
> IRP_MN_QUERY_DIRECTORY;
> > irpSp->FileObject = pFileObject;
> >
> > // set completion routine which just set event
> and
> > // return MORE_PROCESSING_REQUIRED
> >
> > irpSp->Context = &Event;
> > irpSp->CompletionRoutine =
> > UtilSetEventCompletionRoutine;
> > irpSp->Control = SL_INVOKE_ON_SUCCESS |
> > SL_INVOKE_ON_ERROR |
> > SL_INVOKE_ON_CANCEL;
> >
> > if (FileMask)
> > {
> > RtlInitAnsiString(&asName,FileMask);
> > irpSp->Parameters.QueryDirectory.FileName =
> > &asName;
>
=== message truncated ===

_______________________________
Do you Yahoo!?
Declare Yourself - Register online to vote today!
http://vote.yahoo.com

Tony you’re right, that’s just an experimental code thrown in in 5
minutes, maybe i’ve mystiped some comments. I’ve tried to pass both
unicode and ansi strings, both to this test routine and to
ZwQueryDirectoryFile. Still all entries are returned.
I pass “*.txt” as a mask, and there’s plenty of txt files in such dir.

regards,
Valerio

Tony Mason wrote:

I’m confused. How can the search string be a Unicode string? What I
see is:
if (FileMask)
{
RtlInitAnsiString(&asName,FileMask);
irpSp->Parameters.QueryDirectory.FileName =
&asName;
}

Maybe I don’t understand the code (that’s possible) but when I read this
it looked like it was initializing an ANSI string. I see that the
original comments indicated they tried with a UNICODE string, but if
this routine were passed an ANSI string and initialized into a UNICODE
structure, it wouldn’t work right. If this same code were used with a
wide character string, it wouldn’t work right.

I know this API works. The results obtained indicate that the caller
thinks this is a wildcard search - and that would fit with passing in a
zero length search string or possibly an invalid string. FAT at least
validates the UNICODE_STRING structure (ensuring the # of bytes is even,
for instance) but I can’t see how it will return EVERYTHING if you pass
a valid name into it. The only way that seems to happen is a zero
length string or explicit search request.

What am I missing?

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Randy Cook
Sent: Wednesday, September 29, 2004 1:08 PM
To: ntfsd redirect
Subject: Re:[ntfsd] Another weird thing about ZwQueryDirectoryFile

The search string is a unicode string.

Maybe try “<.txt”.

Tony Mason said in a previous post:
There are five wildcard characters in the Windows
pattern matching
syntax (that is the syntax implemented by
FsRtlIsNameInExpression, that
venerable and nearly inscrutable function.)

* = “match one or more characters”
? = “match one character”
< = “match one or more characters using MS-DOS
semantics”

>= “match one character using MS-DOS semantics”

" = “match dot using MS-DOS semantics”

Thus, the last three are for MS-DOS compatibility,
which restricts the
character set that can match. For example, spaces are
allowed in MS-DOS
names, but not before or after the dot. These MS-DOS
patterns match
those semantics.

For building your own strings, I highly recommend
sticking with the
Windows semantics, not the MS-DOS semantics.

— valerino wrote:
>
>
>>Uhm, something is really goin’ wrong. I can’t think
>>of what’s wrong with
>>my code, i have tried to roll my own irp too, but
>>still no success. I
>>specify a filemask, and it still returns all file
>>entries as with
>>FileName = NULL.
>>
>>Here is the code i use to roll the irp :
>>
>>
>
> /
> /
>
>>NTSTATUS UtilBuildQueryDirectoryIrp( IN HANDLE
>>FileHandle, char*
>>FileMask, PVOID FileInfoBuffer, ULONG
>>FileInfoLength, BOOLEAN
>>RestartScan, BOOLEAN ReturnSingleEntry)
>>{
>> NTSTATUS Status;
>> PIRP irp = NULL;
>> PDEVICE_OBJECT pDeviceObject = NULL;
>> PFILE_OBJECT pFileObject = NULL;
>> ANSI_STRING asName;
>> PIO_STACK_LOCATION irpSp;
>> IO_STATUS_BLOCK Iosb;
>> KEVENT Event;
>>
>> // get device from fileobject
>>
>>
>
> ObReferenceObjectByHandle(FileHandle,FILE_ANY_ACCESS,
>
>> NULL,KernelMode,&pFileObject,NULL);
>>
>> if (!pFileObject)
>> goto __exit;
>>
>> // use base filesystem object directly
>> pDeviceObject =
>>IoGetBaseFileSystemDeviceObject(pFileObject);
>> if (!pDeviceObject)
>> goto__exit;
>>
>> // build irp
>> irp = IoAllocateIrp
>>(pDeviceObject->StackSize,TRUE);
>> if (!irp)
>> goto __exit;
>>
>> irpSp = IoGetNextIrpStackLocation(irp);
>>
>> // fill irp params
>> irp->Tail.Overlay.Thread = PsGetCurrentThread();
>>
>>KeInitializeEvent(&Event,NotificationEvent,FALSE);
>> irp->UserIosb = &Iosb;
>>
>> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
>> irp->MdlAddress = (PMDL) NULL;
>> irp->UserBuffer = FileInfoBuffer;
>> irp->UserEvent = NULL;
>>
>>irp->Overlay.AsynchronousParameters.UserApcRoutine =
>>NULL;
>>
>>irp->Overlay.AsynchronousParameters.UserApcContext =
>>NULL;
>> irp->Tail.Overlay.AuxiliaryBuffer = NULL;
>> irp->AssociatedIrp.SystemBuffer = (PVOID) NULL;
>> irp->MdlAddress = (PMDL) NULL;
>> irp->Flags = (ULONG) (IRP_BUFFERED_IO |
>>IRP_INPUT_OPERATION);
>>
>> irpSp->Parameters.QueryDirectory.Length =
>>FileInfoLength;
>>
>>
>
> irpSp->Parameters.QueryDirectory.FileInformationClass
>
>>=
>>FileDirectoryInformation;
>> irpSp->Parameters.QueryDirectory.FileIndex = 0;
>> irpSp = IoGetNextIrpStackLocation( irp );
>> irpSp->MajorFunction =
>>IRP_MJ_DIRECTORY_CONTROL;
>> irpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
>> irpSp->FileObject = pFileObject;
>>
>> // set completion routine which just set event and
>> // return MORE_PROCESSING_REQUIRED
>>
>> irpSp->Context = &Event;
>> irpSp->CompletionRoutine =
>>UtilSetEventCompletionRoutine;
>> irpSp->Control = SL_INVOKE_ON_SUCCESS |
>>SL_INVOKE_ON_ERROR |
>>SL_INVOKE_ON_CANCEL;
>>
>> if (FileMask)
>> {
>> RtlInitAnsiString(&asName,FileMask);
>> irpSp->Parameters.QueryDirectory.FileName =
>>&asName;
>> }
>> else
>> irpSp->Parameters.QueryDirectory.FileName = NULL;
>>
>> if (RestartScan)
>> {
>> irpSp->Flags = SL_RESTART_SCAN;
>> }
>> if (ReturnSingleEntry)
>> {
>> irpSp->Flags |= SL_RETURN_SINGLE_ENTRY;
>> }
>>
>> // fire IRP
>> Status = IoCallDriver (pDeviceObject,irp);
>> if (Status == STATUS_PENDING)
>>
>>
>
> KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,NULL);
>
>> Status = irp->IoStatus.Status;
>>
>>__exit:
>> if (pFileObject)
>> ObDereferenceObject(pFileObject);
>> if (irp)
>> IoFreeIrp (irp);
>>
>> return Status;
>>}
>>
>
> /

> /
>
>>I call this function with :
>>
>>Status =
>>UtilBuildQueryDirectoryIrp(hCacheDir,“*.txt”,
>> FileInformationBuffer,FILEBLOCKINFOSIZE,TRUE,TRUE);
>>if (!NT_SUCCESS(Status) && (Status !=
>>STATUS_NO_MORE_FILES))
>>{
>> Status = STATUS_SUCCESS;
>> goto __exit;
>>}
>>
>>// … process first returned buffer here
>>…
>>
>>// then loop for every other entries in the
>>directory
>>while (TRUE)
>>{
>> // … process returned buffer here
>>…
>>
>> // go on next file
>> Status = UtilBuildQueryDirectoryIrp(hCacheDir,NULL,
>>
>>FileInformationBuffer,FILEBLOCKINFOSIZE,FALSE,TRUE);
>>
>> if (!NT_SUCCESS(Status))
>> {
>> if (Status == STATUS_NO_MORE_FILES)
>> {
>> Status = STATUS_SUCCESS;
>> }
>> break;
>> }
>>}
>>
>>I think my implementation is the same as
>>ZwQueryDirectoryFile, but still
>>the same result. Please tell me what’s wrong (i’d
>>like to use
>>ZwQueryDirectoryFile directly, using my own irp was
>>just a test).
>>Ah… i’ve used an ANSI_STRING for the filename,
>>since i’ve found that
>>the OS cast it to a PSTRING ( = ANSI_STRING, from
>>ntdef.h) when building
>>the irp. Still, if i use unicode, same result (as
>>for ZwQueryDirectoryFile).
>>
>>waiting clues…
>>
>>regards,
>>Valerio
>>
>>—
>>Questions? First check the IFS FAQ at
>>https://www.osronline.com/article.cfm?id=17
>>
>>You are currently subscribed to ntfsd as:
>>xxxxx@yahoo.com
>>To unsubscribe send a blank email to
>>xxxxx@lists.osr.com
>>
>
>
>
>
>
>
>__________________________________
> Do you Yahoo!?
> New and Improved Yahoo! Mail - 100MB free storage!
> http://promotions.yahoo.com/new_mail
>
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@osr.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

> I’ve tried to pass both unicode and ansi strings

i mean, adapting my routine to use ansi or unicode string in input too.

regards,
Valerio

Randy,
i’ve tried everything :slight_smile: i’m starting to bet there’s a bug in the OS.
I’ve tried now too by using plain ZwQueryDirectoryFile with Filename
param as unicode string,
using the syntax you suggested and as normal with “*.ext”. No luck,
still all entries are returned.

Are you sure your code works specifying a filemask ? I never noticed
that too, since i’ve always used it with Filename = NULL.

Now, i’m going to look thru IDA on how findfirst/findnext are
implemented in usermode… that’s my only chance. I wonder if they
just get all the entries and just sort out the unwanted ones.
Thanks for the private reply :slight_smile:

regards,
Valerio

Can’t be a bug in the OS or “dir *.txt” from a cmd
prompt wouldn’t work either.

I haven’t used this function with wildcards, but I
have specified the FileName parameter and had it work.

BTW, I verified that “*.txt” in userland translates to
“<.txt” in kernelland (at least from a cmd window).

If code like the following does not work for you then
I would bet that you have a problem with your file
handle as Neal suggested.

*******
bInitialQuery = TRUE;

RtlInitUnicodeString(
&fileNameUniString,
L"<.txt");

status = ZwQueryDirectoryFile(
dirHandle,
NULL,
NULL, 0, &ioStatus, pMyBuffer,
MY_DIR_INFO_BUFF_SIZE,
FileBothDirectoryInformation,
FALSE, &fileNameUniString,
bInitialQuery);
bInitialQuery = FALSE;

etc, etc

— valerino wrote:

> Randy,
> i’ve tried everything :slight_smile: i’m starting to bet there’s
> a bug in the OS.
> I’ve tried now too by using plain
> ZwQueryDirectoryFile with Filename
> param as unicode string,
> using the syntax you suggested and as normal with
> “*.ext”. No luck,
> still all entries are returned.
>
> Are you sure your code works specifying a filemask ?
> I never noticed
> that too, since i’ve always used it with Filename =
> NULL.
>
> Now, i’m going to look thru IDA on how
> findfirst/findnext are
> implemented in usermode… that’s my only chance.
> I wonder if they
> just get all the entries and just sort out the
> unwanted ones.
> Thanks for the private reply :slight_smile:
>
> regards,
> Valerio
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as:
> xxxxx@yahoo.com
> To unsubscribe send a blank email to
> xxxxx@lists.osr.com
>

_______________________________
Do you Yahoo!?
Declare Yourself - Register online to vote today!
http://vote.yahoo.com

Valerio,

Might I suggest directly coding this in your test code? Also, if you
are feeling truly adventurous, try building fastfat and walking through
the code to see if you can determine why it is treating it as a
wildcard. That’s unlikely to be more work than pulling out IDA to do
more analysis.

I know this work - I’ve written test code to validate that directory
enumeration works on our own file systems and I have done this sort of
enumeration.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

Argh, i’m going really mad about this :slight_smile:
I can’t doubt of what you all are saing, maybe its my OS which is
doomed…

I open the directory this way :

RtlInitUnicodeString(&ObjectName, CacheDir);
InitializeObjectAttributes(&ObjectAttributes, &ObjectName,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, hBaseDir, 0);

Status = ZwCreateFile(&hCacheDir, GENERIC_READ | GENERIC_WRITE |
FILE_LIST_DIRECTORY, &ObjectAttributes, &Iosb, NULL,
FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN_IF,
FILE_DIRECTORY_FILE, NULL, 0);

Then i use the handle in ZwQueryDirectoryFile using always
ReturnSingleEntry. Both using wildcard and plain filename is ignored.
Could be something related to the OBJ_KERNEL_HANDLE (i need to use that) ?

regards,
Valerio

Randy Cook wrote:

Can’t be a bug in the OS or “dir *.txt” from a cmd
prompt wouldn’t work either.

I haven’t used this function with wildcards, but I
have specified the FileName parameter and had it work.

BTW, I verified that “*.txt” in userland translates to
“<.txt” in kernelland (at least from a cmd window).

If code like the following does not work for you then
I would bet that you have a problem with your file
handle as Neal suggested.

*******
bInitialQuery = TRUE;

RtlInitUnicodeString(
&fileNameUniString,
L"<.txt");

status = ZwQueryDirectoryFile(
dirHandle,
NULL,
NULL, 0, &ioStatus, pMyBuffer,
MY_DIR_INFO_BUFF_SIZE,
FileBothDirectoryInformation,
FALSE, &fileNameUniString,
bInitialQuery);
bInitialQuery = FALSE;

etc, etc

— valerino wrote:
>
>
>>Randy,
>>i’ve tried everything :slight_smile: i’m starting to bet there’s
>>a bug in the OS.
>>I’ve tried now too by using plain
>>ZwQueryDirectoryFile with Filename
>>param as unicode string,
>>using the syntax you suggested and as normal with
>>“*.ext”. No luck,
>>still all entries are returned.
>>
>>Are you sure your code works specifying a filemask ?
>>I never noticed
>>that too, since i’ve always used it with Filename =
>>NULL.
>>
>>Now, i’m going to look thru IDA on how
>>findfirst/findnext are
>>implemented in usermode… that’s my only chance.
>>I wonder if they
>>just get all the entries and just sort out the
>>unwanted ones.
>>Thanks for the private reply :slight_smile:
>>
>>regards,
>>Valerio
>>
>>—
>>Questions? First check the IFS FAQ at
>>https://www.osronline.com/article.cfm?id=17
>>
>>You are currently subscribed to ntfsd as:
>>xxxxx@yahoo.com
>>To unsubscribe send a blank email to
>>xxxxx@lists.osr.com
>>
>
>
>
>
>
>
>
> _______________________________
> Do you Yahoo!?
> Declare Yourself - Register online to vote today!
> http://vote.yahoo.com
>
>