- NtQueryDirectoryFile:

- Setup a buffer/MDL and the correct IRP flags so that that I/O manager can handle allocation, copy, free for us.
  - Setup the search pattern as an auxiliary buffer so that the I/O Mgr can track that one for us as well.
  - Update to use the correct sync semantics/routines.
  - Use deferred I/O completion.
- Outline TODOs and workplan for iofunc.c

svn path=/trunk/; revision=22791
This commit is contained in:
Alex Ionescu
2006-07-03 02:50:16 +00:00
parent 933ef1952d
commit 0ffb1da110
+122 -101
View File
@@ -24,11 +24,17 @@
///
//
// TODO:
// - Update to new semantics:
// - Lock/Unlock <= DONE
// - Query/Set Volume Info <= DONE
// - Read/Write file <= DONE
// - QueryDirectoryFile <= DONE
// - Query/Set File Info
// - QueryDirectoryFile
// - Add SEH to some places where it's missing (MDLs, etc)
// - Add a generic Cleanup/Exception Routine
// - Add another parameter to IopCleanupFailedIrp
// - Add support for Fast Dispatch I/O
// - Add support for some fast-paths when querying/setting data
//
///
@@ -535,16 +541,6 @@ IopQueryDeviceInformation(IN PFILE_OBJECT FileObject,
return Status;
}
NTSTATUS
NTAPI
IopQueryDirectoryFileCompletion(IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
IN PVOID Context)
{
ExFreePool(Context);
return STATUS_SUCCESS;
}
/* PUBLIC FUNCTIONS **********************************************************/
/*
@@ -1273,7 +1269,7 @@ NtLockFile(IN HANDLE FileHandle,
NTSTATUS
NTAPI
NtQueryDirectoryFile(IN HANDLE FileHandle,
IN HANDLE PEvent OPTIONAL,
IN HANDLE EventHandle OPTIONAL,
IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,
IN PVOID ApcContext OPTIONAL,
OUT PIO_STATUS_BLOCK IoStatusBlock,
@@ -1286,55 +1282,73 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
{
PIRP Irp;
PDEVICE_OBJECT DeviceObject;
PFILE_OBJECT FileObject = NULL;
PFILE_OBJECT FileObject;
PIO_STACK_LOCATION StackPtr;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
BOOLEAN LocalEvent = FALSE;
BOOLEAN LockedForSynch = FALSE;
PKEVENT Event = NULL;
PUNICODE_STRING SearchPattern = NULL;
PVOID AuxBuffer = NULL;
PMDL Mdl;
UNICODE_STRING CapturedFileName;
PUNICODE_STRING SearchPattern;
PAGED_CODE();
/* Validate User-Mode Buffers */
/* Check if we came from user mode */
if(PreviousMode != KernelMode)
{
/* Enter SEH for probing */
_SEH_TRY
{
/* Probe the I/O Status Block */
ProbeForWrite(IoStatusBlock,
sizeof(IO_STATUS_BLOCK),
sizeof(ULONG));
ProbeForWrite(FileInformation,
Length,
sizeof(ULONG));
/* Probe the file information */
ProbeForWrite(FileInformation, Length, sizeof(ULONG));
/* Check if we have a file name */
if (FileName)
{
UNICODE_STRING CapturedFileName;
/* Capture it */
CapturedFileName = ProbeForReadUnicodeString(FileName);
ProbeForRead(CapturedFileName.Buffer,
CapturedFileName.MaximumLength,
1);
SearchPattern = ExAllocatePool(NonPagedPool, CapturedFileName.Length + sizeof(WCHAR) + sizeof(UNICODE_STRING));
if (SearchPattern == NULL)
if (CapturedFileName.Length)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
_SEH_LEAVE;
/* Probe its buffer */
ProbeForRead(CapturedFileName.Buffer,
CapturedFileName.Length,
1);
}
SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)SearchPattern + sizeof(UNICODE_STRING));
SearchPattern->MaximumLength = CapturedFileName.Length + sizeof(WCHAR);
RtlCopyUnicodeString(SearchPattern, &CapturedFileName);
/* Allocate the auxiliary buffer */
AuxBuffer = ExAllocatePoolWithTag(NonPagedPool,
CapturedFileName.Length +
sizeof(UNICODE_STRING),
TAG_SYSB);
RtlCopyMemory((PVOID)((ULONG_PTR)AuxBuffer +
sizeof(UNICODE_STRING)),
CapturedFileName.Buffer,
CapturedFileName.Length);
/* Setup the search pattern */
SearchPattern = (PUNICODE_STRING)AuxBuffer;
SearchPattern->Buffer = (PWCHAR)((ULONG_PTR)AuxBuffer +
sizeof(UNICODE_STRING));
SearchPattern->Length = CapturedFileName.Length;
SearchPattern->MaximumLength = CapturedFileName.Length;
}
}
_SEH_HANDLE
{
/* Get exception code and free the buffer */
if (AuxBuffer) ExFreePool(AuxBuffer);
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
goto Cleanup;
}
/* Return status on failure */
if (!NT_SUCCESS(Status)) return Status;
}
/* Get File Object */
@@ -1344,53 +1358,53 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
PreviousMode,
(PVOID *)&FileObject,
NULL);
if (!NT_SUCCESS(Status)) goto Cleanup;
/* Get Event Object */
if (PEvent)
if (!NT_SUCCESS(Status))
{
Status = ObReferenceObjectByHandle(PEvent,
/* Fail */
if (AuxBuffer) ExFreePool(AuxBuffer);
return Status;
}
/* Check if we have an even handle */
if (EventHandle)
{
/* Get its pointer */
Status = ObReferenceObjectByHandle(EventHandle,
EVENT_MODIFY_STATE,
ExEventObjectType,
PreviousMode,
(PVOID *)&Event,
NULL);
if (!NT_SUCCESS(Status))
if (!NT_SUCCESS(Status))
{
goto Cleanup;
/* Fail */
ObDereferenceObject(FileObject);
return Status;
}
/* Clear it */
KeClearEvent(Event);
}
/* Check if this is a direct open or not */
if (FileObject->Flags & FO_DIRECT_DEVICE_OPEN)
{
DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
}
else
{
DeviceObject = IoGetRelatedDeviceObject(FileObject);
}
/* Check if we should use Sync IO or not */
/* Check if this is a file that was opened for Synch I/O */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
{
/* Use File Object event */
KeClearEvent(&FileObject->Event);
}
else
{
LocalEvent = TRUE;
/* Lock it */
IopLockFileObject(FileObject);
/* Remember to unlock later */
LockedForSynch = TRUE;
}
/* Get the device object */
DeviceObject = IoGetRelatedDeviceObject(FileObject);
/* Clear the File Object's event */
KeClearEvent(&FileObject->Event);
/* Allocate the IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
if (!Irp)
{
Status = STATUS_INSUFFICIENT_RESOURCES;
goto Cleanup;
}
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
if (!Irp) return IopCleanupFailedIrp(FileObject, EventHandle);
/* Set up the IRP */
Irp->RequestorMode = PreviousMode;
@@ -1398,9 +1412,38 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
Irp->UserEvent = Event;
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
Irp->Tail.Overlay.OriginalFileObject = FileObject;
Irp->UserBuffer = FileInformation;
Irp->Overlay.AsynchronousParameters.UserApcRoutine = ApcRoutine;
Irp->Overlay.AsynchronousParameters.UserApcContext = ApcContext;
Irp->MdlAddress = NULL;
Irp->Tail.Overlay.AuxiliaryBuffer = AuxBuffer;
Irp->AssociatedIrp.SystemBuffer = NULL;
/* Check if this is buffered I/O */
if (DeviceObject->Flags & DO_BUFFERED_IO)
{
/* Allocate a buffer */
Irp->AssociatedIrp.SystemBuffer =
ExAllocatePoolWithTag(NonPagedPool,
Length,
TAG_SYSB);
/* Set the buffer and flags */
Irp->UserBuffer = FileInformation;
Irp->Flags = (IRP_BUFFERED_IO |
IRP_DEALLOCATE_BUFFER |
IRP_INPUT_OPERATION);
}
else if (DeviceObject->Flags & DO_DIRECT_IO)
{
/* Allocate an MDL */
Mdl = IoAllocateMdl(FileInformation, Length, FALSE, TRUE, Irp);
MmProbeAndLockPages(Mdl, PreviousMode, IoWriteAccess);
}
else
{
/* No allocation flags, and use the buffer directly */
Irp->UserBuffer = FileInformation;
}
/* Set up Stack Data */
StackPtr = IoGetNextIrpStackLocation(Irp);
@@ -1409,48 +1452,26 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
StackPtr->MinorFunction = IRP_MN_QUERY_DIRECTORY;
/* Set Parameters */
StackPtr->Parameters.QueryDirectory.FileInformationClass = FileInformationClass;
StackPtr->Parameters.QueryDirectory.FileName = SearchPattern ? SearchPattern : FileName;
StackPtr->Parameters.QueryDirectory.FileInformationClass =
FileInformationClass;
StackPtr->Parameters.QueryDirectory.FileName = AuxBuffer;
StackPtr->Parameters.QueryDirectory.FileIndex = 0;
StackPtr->Parameters.QueryDirectory.Length = Length;
StackPtr->Flags = 0;
if (RestartScan) StackPtr->Flags = SL_RESTART_SCAN;
if (ReturnSingleEntry) StackPtr->Flags |= SL_RETURN_SINGLE_ENTRY;
if (SearchPattern)
{
IoSetCompletionRoutine(Irp,
IopQueryDirectoryFileCompletion,
SearchPattern,
TRUE,
TRUE,
TRUE);
}
/* Set deferred I/O */
Irp->Flags |= IRP_DEFER_IO_COMPLETION;
/* Call the Driver */
Status = IoCallDriver(DeviceObject, Irp);
if (Status == STATUS_PENDING)
{
if (!LocalEvent)
{
KeWaitForSingleObject(&FileObject->Event,
Executive,
PreviousMode,
FileObject->Flags & FO_ALERTABLE_IO,
NULL);
Status = FileObject->FinalStatus;
}
}
return Status;
Cleanup:
if (FileObject) ObDereferenceObject(FileObject);
if (Event) ObDereferenceObject(Event);
if (SearchPattern) ExFreePool(SearchPattern);
/* Return the Status */
return Status;
/* Perform the call */
return IopPerformSynchronousRequest(DeviceObject,
Irp,
FileObject,
TRUE,
PreviousMode,
LockedForSynch,
IopOtherTransfer);
}
/*