Author: ion Date: Mon Jul 3 06:50:16 2006 New Revision: 22791
URL: http://svn.reactos.org/svn/reactos?rev=22791&view=rev Log: - 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
Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c
Modified: trunk/reactos/ntoskrnl/io/iomgr/iofunc.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/iofunc.c?... ============================================================================== --- trunk/reactos/ntoskrnl/io/iomgr/iofunc.c (original) +++ trunk/reactos/ntoskrnl/io/iomgr/iofunc.c Mon Jul 3 06:50:16 2006 @@ -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 // ///
@@ -533,16 +539,6 @@ /* Return the Length and Status. ReturnedLength is NOT optional */ *ReturnedLength = IoStatusBlock.Information; 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 @@ 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 @@ { 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 @@ PreviousMode, (PVOID *)&FileObject, NULL); - if (!NT_SUCCESS(Status)) goto Cleanup; - - /* Get Event Object */ - if (PEvent) - { - Status = ObReferenceObjectByHandle(PEvent, + if (!NT_SUCCESS(Status)) + { + /* 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)) - { - goto Cleanup; - } - + if (!NT_SUCCESS(Status)) + { + /* 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 @@ 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 @@ 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); - } - - /* 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; + /* Set deferred I/O */ + Irp->Flags |= IRP_DEFER_IO_COMPLETION; + + /* Perform the call */ + return IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + LockedForSynch, + IopOtherTransfer); }
/*