IRP_MN_QUERY_DIRECTORY howto ...

Hi,
I wrote an Filter Driver in which I try to get the long path name
of each file opened by the system.
However my “get_long_path_name” routine don’t work because I don’t
know how to send an irp with :
MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
MinorFunction = IRP_MN_QUERY_DIRECTORY;

I wrote the little program below which doesn’t report any error, but
which doesn’t work at all : my FILE_BOTH_DIR_INFORMATION buffer is
not updated by the low level driver (both NTFS and FAT).

What’s wrong ?

Thanks in advance,
Philippe.

Ps: Also, I’m surprised that the IRP takes only ANSI strings and not
UNICODE strings:

IrpSp->Parameters.QueryDirectory.FileName
Optional name of a file within the specified directory.

and:

//
// System service parameters for: NtQueryDirectoryFile
//
struct {
ULONG Length;
PSTRING FileName; // <- ANSI string …
FILE_INFORMATION_CLASS FileInformationClass;
ULONG FileIndex;
} QueryDirectory;

Does anyone know why?


#include <ntifs.h>

VOID
DriverUnload(
IN PDRIVER_OBJECT DriverObject
);

NTSTATUS
DriverRoutine(
IN PWCHAR PathName,
IN PCHAR FileName
);

NTSTATUS
DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath
)
{
DriverObject->DriverUnload = DriverUnload;
DriverRoutine(L"\??\C:\“, “Progra~1”);
KdPrint((”=========================\n"));
DriverRoutine(L"\??\C:\“, “Program Files”);
KdPrint((”=========================\n"));
DriverRoutine(L"\??\C:\“, “boot.ini”);
KdPrint((”=========================\n"));
DriverRoutine(L"\??\C:\", “progra*”);
return STATUS_SUCCESS;
}

VOID
DriverUnload(
IN PDRIVER_OBJECT DriverObject
)
{
}

NTSTATUS
DriverRoutine(
IN PWCHAR PathName,
IN PCHAR FileName
)
{
NTSTATUS Status;
UNICODE_STRING UnicodePathName;
ANSI_STRING AnsiFileName;
HANDLE hFile;
PFILE_BOTH_DIR_INFORMATION FileBothDirInfo;
ULONG BufferLen;
PFILE_OBJECT FileObject;
KEVENT FileEvent;
PIRP Irp;
PIO_STACK_LOCATION IrpSp;
OBJECT_ATTRIBUTES ObjectAttributes;
IO_STATUS_BLOCK IoStatusBlock;
ACCESS_MASK AccessMask;

RtlInitUnicodeString(&UnicodePathName, PathName);
RtlInitAnsiString(&AnsiFileName, FileName);

KdPrint((“QueryDir: InitializeObjectAttributes\n”));

InitializeObjectAttributes(&ObjectAttributes, &UnicodePathName,
OBJ_CASE_INSENSITIVE, NULL, NULL);

KdPrint((“QueryDir: IoCreateFile(%wZ) [Looking for %Z]\n”,
&UnicodePathName,
&AnsiFileName));

AccessMask = FILE_READ_ATTRIBUTES | FILE_READ_EA | SYNCHRONIZE |
FILE_LIST_DIRECTORY;

Status = IoCreateFile(&hFile, AccessMask, &ObjectAttributes,
&IoStatusBlock, 0, FILE_ATTRIBUTE_DIRECTORY,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0, CreateFileTypeNone, NULL,
0 /* IO_NO_PARAMETER_CHECKING */);

if (Status != STATUS_SUCCESS) {
KdPrint((“QueryDir: IoCreateFile failed : %.8x\n”, Status));
return Status;
}

KdPrint((“QueryDir: IoCreateFile(‘%wZ’) succeeded\n”,
&UnicodePathName));

Status = ObReferenceObjectByHandle(hFile, AccessMask, NULL,
KernelMode, &FileObject, NULL);

if (Status != STATUS_SUCCESS) {
KdPrint((“QueryDir: ObReferenceObjectByHandle failed [%.8x])\n”,
Status));
ZwClose(hFile);
return Status;
}

KdPrint((“QueryDir: Got %wZ FileObject [%p]\n”, &UnicodePathName,
FileObject));

BufferLen = sizeof(FILE_BOTH_DIR_INFORMATION) + sizeof(WCHAR) * 384;
FileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)
ExAllocatePool(NonPagedPool, BufferLen);
if (FileBothDirInfo == NULL) {
KdPrint((“QueryDir: ExAllocatePool failed\n”));
ObDereferenceObject(FileObject);
ZwClose(hFile);
return STATUS_NO_MEMORY;
}

memset(FileBothDirInfo, 0, BufferLen);

KeInitializeEvent(&FileEvent, SynchronizationEvent, FALSE);

Irp = IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
FileObject->DeviceObject,
NULL, 0, NULL, &FileEvent, &IoStatusBlock);

if (Irp == NULL) {
KdPrint((“QueryDir: IoBuildSynchronousFsdRequest failed\n”));
Status = STATUS_NO_MEMORY;
goto end;
}

KdPrint((“QueryDir: Got %wZ Irp [%p]\n”, &UnicodePathName, Irp));

Irp->UserBuffer = FileBothDirInfo;

IrpSp = IoGetCurrentIrpStackLocation(Irp);
if (IrpSp == NULL) {
KdPrint((“QueryDir: IoGetCurrentIrpStackLocation failed\n”));
Status = STATUS_NO_MEMORY;
goto end;
}

KdPrint((“QueryDir: Got %wZ IrpSp [%p]\n”, &UnicodePathName,
IrpSp));

IrpSp->FileObject = FileObject;
IrpSp->DeviceObject = FileObject->DeviceObject;
IrpSp->Flags = SL_RESTART_SCAN | SL_RETURN_SINGLE_ENTRY;
IrpSp->MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
IrpSp->MinorFunction = IRP_MN_QUERY_DIRECTORY;
IrpSp->Parameters.QueryDirectory.FileIndex = 0;
IrpSp->Parameters.QueryDirectory.FileInformationClass =
FileBothDirectoryInformation;
IrpSp->Parameters.QueryDirectory.FileName = &AnsiFileName;
IrpSp->Parameters.QueryDirectory.Length = BufferLen;

KdPrint((“QueryDir: IoCallDriver IRP_MJ_DIRECTORY_CONTROL
IRP_MN_QUERY_DIRECTORY\n”));

Status = IoCallDriver(FileObject->DeviceObject, Irp);

KdPrint((“QueryDir: IoCallDriver returned %.8x\n”, Status));

if (Status == STATUS_PENDING) {
Status = KeWaitForSingleObject(&FileEvent, Executive, KernelMode,
FALSE, NULL);
if (Status != STATUS_SUCCESS) {
KdPrint((“QueryDir: KeWaitForSingleObject failed [%.8x])\n”,
Status));
goto end;
}
}

KdPrint((“QueryDir: Irp->IoStatus.Status = %.8x\n”,
Irp->IoStatus.Status));
Status = Irp->IoStatus.Status;

if (Status == STATUS_SUCCESS) {
UNICODE_STRING LongFileName;
UNICODE_STRING ShortFileName;

LongFileName.Buffer = FileBothDirInfo->FileName;
LongFileName.Length = LongFileName.MaximumLength = (USHORT)
FileBothDirInfo->FileNameLength;

ShortFileName.Buffer = FileBothDirInfo->ShortName;
ShortFileName.Length = ShortFileName.MaximumLength = (USHORT)
FileBothDirInfo->ShortNameLength;

KdPrint((“QueryDir: LongFileName.Buffer = %p\n”,
LongFileName.Buffer));
KdPrint((“QueryDir: LongFileName.Length = %d\n”,
LongFileName.Length));
KdPrint((“QueryDir: LongFileName = %wZ\n”, &LongFileName));

KdPrint((“QueryDir: ShortFileName.Buffer = %p\n”,
ShortFileName.Buffer));
KdPrint((“QueryDir: ShortFileName.Length = %d\n”,
ShortFileName.Length));
KdPrint((“QueryDir: ShortFileName = %wZ\n”,
&ShortFileName));
}

end:
ExFreePool(FileBothDirInfo);
ObDereferenceObject(FileObject);
ZwClose(hFile);

return Status;
}</ntifs.h>

A quick search of the archives found this:
http://www.ntfsd.org/archive/ntfsd0208/msg0350.html

This is at least part of the problem.

Randy

— Philippe Anel wrote:
>
> Hi,
> I wrote an Filter Driver in which I try to get the
> long path name
> of each file opened by the system.
> However my “get_long_path_name” routine don’t work
> because I don’t
> know how to send an irp with :
> MajorFunction = IRP_MJ_DIRECTORY_CONTROL;
> MinorFunction = IRP_MN_QUERY_DIRECTORY;
>
> I wrote the little program below which doesn’t
> report any error, but
> which doesn’t work at all : my
> FILE_BOTH_DIR_INFORMATION buffer is
> not updated by the low level driver (both NTFS and
> FAT).
>
> What’s wrong ?
>
> Thanks in advance,
> Philippe.
>
> Ps: Also, I’m surprised that the IRP takes only ANSI
> strings and not
> UNICODE strings:
>
> IrpSp->Parameters.QueryDirectory.FileName
> Optional name of a file within the specified
> directory.
>
> and:
>
> //
> // System service parameters for:
> NtQueryDirectoryFile
> //
> struct {
> ULONG Length;
> PSTRING FileName; // <- ANSI string
> …
> FILE_INFORMATION_CLASS
> FileInformationClass;
> ULONG FileIndex;
> } QueryDirectory;
>
>
> Does anyone know why?
>
>
>
>
----------------------------------------------------------------------
>
>
> #include <ntifs.h>
>
> VOID
> DriverUnload(
> IN PDRIVER_OBJECT DriverObject
> );
>
> NTSTATUS
> DriverRoutine(
> IN PWCHAR PathName,
> IN PCHAR FileName
> );
>
> NTSTATUS
> DriverEntry(
> IN PDRIVER_OBJECT DriverObject,
> IN PUNICODE_STRING RegistryPath
> )
> {
> DriverObject->DriverUnload = DriverUnload;
> DriverRoutine(L"\??\C:\“, “Progra~1”);
> KdPrint((”=========================\n"));
> DriverRoutine(L"\??\C:\“, “Program Files”);
> KdPrint((”=========================\n"));
> DriverRoutine(L"\??\C:\“, “boot.ini”);
> KdPrint((”=========================\n"));
> DriverRoutine(L"\??\C:\", “progra*”);
> return STATUS_SUCCESS;
> }
>
> VOID
> DriverUnload(
> IN PDRIVER_OBJECT DriverObject
> )
> {
> }
>
> NTSTATUS
> DriverRoutine(
> IN PWCHAR PathName,
> IN PCHAR FileName
> )
> {
> NTSTATUS Status;
> UNICODE_STRING UnicodePathName;
> ANSI_STRING AnsiFileName;
> HANDLE hFile;
> PFILE_BOTH_DIR_INFORMATION FileBothDirInfo;
> ULONG BufferLen;
> PFILE_OBJECT FileObject;
> KEVENT FileEvent;
> PIRP Irp;
> PIO_STACK_LOCATION IrpSp;
> OBJECT_ATTRIBUTES ObjectAttributes;
> IO_STATUS_BLOCK IoStatusBlock;
> ACCESS_MASK AccessMask;
>
> RtlInitUnicodeString(&UnicodePathName, PathName);
> RtlInitAnsiString(&AnsiFileName, FileName);
>
> KdPrint((“QueryDir:
> InitializeObjectAttributes\n”));
>
> InitializeObjectAttributes(&ObjectAttributes,
> &UnicodePathName,
> OBJ_CASE_INSENSITIVE, NULL, NULL);
>
> KdPrint((“QueryDir: IoCreateFile(%wZ) [Looking for
> %Z]\n”,
> &UnicodePathName,
> &AnsiFileName));
>
> AccessMask = FILE_READ_ATTRIBUTES | FILE_READ_EA |
> SYNCHRONIZE |
> FILE_LIST_DIRECTORY;
>
> Status = IoCreateFile(&hFile, AccessMask,
> &ObjectAttributes,
> &IoStatusBlock, 0, FILE_ATTRIBUTE_DIRECTORY,
> FILE_SHARE_READ | FILE_SHARE_WRITE |
> FILE_SHARE_DELETE,
> FILE_OPEN, FILE_DIRECTORY_FILE, NULL, 0,
> CreateFileTypeNone, NULL,
> 0 /* IO_NO_PARAMETER_CHECKING */);
>
> if (Status != STATUS_SUCCESS) {
> KdPrint((“QueryDir: IoCreateFile failed : %.8x\n”,
> Status));
> return Status;
> }
>
> KdPrint((“QueryDir: IoCreateFile(‘%wZ’)
> succeeded\n”,
> &UnicodePathName));
>
> Status = ObReferenceObjectByHandle(hFile,
> AccessMask, NULL,
> KernelMode, &FileObject, NULL);
>
> if (Status != STATUS_SUCCESS) {
> KdPrint((“QueryDir: ObReferenceObjectByHandle
> failed [%.8x])\n”,
> Status));
> ZwClose(hFile);
> return Status;
> }
>
> KdPrint((“QueryDir: Got %wZ FileObject [%p]\n”,
> &UnicodePathName,
> FileObject));
>
> BufferLen = sizeof(FILE_BOTH_DIR_INFORMATION) +
> sizeof(WCHAR) * 384;
> FileBothDirInfo = (PFILE_BOTH_DIR_INFORMATION)
> ExAllocatePool(NonPagedPool, BufferLen);
> if (FileBothDirInfo == NULL) {
> KdPrint((“QueryDir: ExAllocatePool failed\n”));
> ObDereferenceObject(FileObject);
> ZwClose(hFile);
> return STATUS_NO_MEMORY;
> }
>
> memset(FileBothDirInfo, 0, BufferLen);
>
> KeInitializeEvent(&FileEvent, SynchronizationEvent,
> FALSE);
>
> Irp =
> IoBuildSynchronousFsdRequest(IRP_MJ_FLUSH_BUFFERS,
> FileObject->DeviceObject,
> NULL, 0, NULL, &FileEvent, &IoStatusBlock);
>
> if (Irp == NULL) {
> KdPrint((“QueryDir: IoBuildSynchronousFsdRequest
> failed\n”));
> Status = STATUS_NO_MEMORY;
> goto end;
> }
>
> KdPrint((“QueryDir: Got %wZ Irp [%p]\n”,
> &UnicodePathName, Irp));
>
> Irp->UserBuffer = FileBothDirInfo;
>
> IrpSp = IoGetCurrentIrpStackLocation(Irp);
> if (IrpSp == NULL) {
> KdPrint((“QueryDir: IoGetCurrentIrpStackLocation
> failed\n”));
>
=== message truncated ===

__________________________________
Do you Yahoo!?
Yahoo! SiteBuilder - Free, easy-to-use web site design software
http://sitebuilder.yahoo.com</ntifs.h>