Author: ion Date: Mon Jul 3 02:14:20 2006 New Revision: 22787
URL: http://svn.reactos.org/svn/reactos?rev=22787&view=rev Log: - Fix sync usage in NtQueryVolumeInformationFile, set the right IRP flags so that the I/O manager can handle copying the data back and freeing the buffer, and enable deferred completion.
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 02:14:20 2006 @@ -2642,111 +2642,137 @@ IN FS_INFORMATION_CLASS FsInformationClass) { PFILE_OBJECT FileObject; + PIRP Irp; + PIO_STACK_LOCATION StackPtr; PDEVICE_OBJECT DeviceObject; - PIRP Irp; + PKEVENT Event = NULL; + BOOLEAN LocalEvent = FALSE; + KPROCESSOR_MODE PreviousMode = KeGetPreviousMode(); NTSTATUS Status = STATUS_SUCCESS; - PIO_STACK_LOCATION StackPtr; - PVOID SystemBuffer; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); - + OBJECT_HANDLE_INFORMATION HandleInformation; + IO_STATUS_BLOCK KernelIosb; + PAGED_CODE(); + + /* Check if we're called from user mode */ if (PreviousMode != KernelMode) { + /* Enter SEH for probing */ _SEH_TRY { - if (IoStatusBlock) - { - ProbeForWrite(IoStatusBlock, - sizeof(IO_STATUS_BLOCK), - sizeof(ULONG)); - } - + /* Probe the I/O Status block */ + ProbeForWrite(IoStatusBlock, + sizeof(IO_STATUS_BLOCK), + sizeof(ULONG)); + + /* Probe the information */ if (Length) ProbeForWrite(FsInformation, Length, 1); } _SEH_HANDLE { + /* Get the exception code */ Status = _SEH_GetExceptionCode(); } _SEH_END;
- if (!NT_SUCCESS(Status)) - { - return Status; - } - } - + /* Check if probing failed */ + if (!NT_SUCCESS(Status)) return Status; + } + + /* Get File Object */ Status = ObReferenceObjectByHandle(FileHandle, - 0, /* FIXME - depends on the information class! */ + 0, // FIXME IoFileObjectType, PreviousMode, (PVOID*)&FileObject, - NULL); + &HandleInformation); if (!NT_SUCCESS(Status)) return Status;
- DeviceObject = FileObject->DeviceObject; - - Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); - if (!Irp) - { + /* Check if we should use Sync IO or not */ + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + /* Lock it */ + IopLockFileObject(FileObject); + } + else + { + /* Use local event */ + Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO); + KeInitializeEvent(Event, SynchronizationEvent, FALSE); + LocalEvent = TRUE; + } + + /* Get the device object */ + DeviceObject = IoGetRelatedDeviceObject(FileObject); + + /* Clear File Object event */ + KeClearEvent(&FileObject->Event); + + /* Allocate the IRP */ + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); + if (!Irp) return IopCleanupFailedIrp(FileObject, Event); + + /* Set up the IRP */ + Irp->RequestorMode = PreviousMode; + Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0; + Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock; + Irp->UserEvent = (LocalEvent) ? Event : NULL; + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; + Irp->UserBuffer = FsInformation; + Irp->AssociatedIrp.SystemBuffer = NULL; + Irp->MdlAddress = NULL; + + /* Set up Stack Data */ + StackPtr = IoGetNextIrpStackLocation(Irp); + StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; + StackPtr->FileObject = FileObject; + + /* Allocate system buffer */ + Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, + Length, + TAG_SYSB); + if (!Irp->AssociatedIrp.SystemBuffer) + { + /* Fail */ + IoFreeIrp(Irp); + if (Event) ObDereferenceObject(Event); ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; }
- SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYSB); - if (!SystemBuffer) - { - IoFreeIrp(Irp); - ObDereferenceObject(FileObject); - return STATUS_INSUFFICIENT_RESOURCES; - } - - /* Trigger FileObject/Event dereferencing */ - Irp->Tail.Overlay.OriginalFileObject = FileObject; - - Irp->RequestorMode = PreviousMode; - Irp->AssociatedIrp.SystemBuffer = SystemBuffer; - KeResetEvent( &FileObject->Event ); - Irp->UserEvent = &FileObject->Event; - Irp->UserIosb = IoStatusBlock; - Irp->Tail.Overlay.Thread = PsGetCurrentThread(); - - StackPtr = IoGetNextIrpStackLocation(Irp); - StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; - StackPtr->MinorFunction = 0; - StackPtr->Flags = 0; - StackPtr->Control = 0; - StackPtr->DeviceObject = DeviceObject; - StackPtr->FileObject = FileObject; + /* Set the flags for this buffered + deferred I/O */ + Irp->Flags |= (IRP_BUFFERED_IO | + IRP_DEALLOCATE_BUFFER | + IRP_INPUT_OPERATION | + IRP_DEFER_IO_COMPLETION); + + /* Set Parameters */ StackPtr->Parameters.QueryVolume.Length = Length; - StackPtr->Parameters.QueryVolume.FsInformationClass = - FsInformationClass; - - Status = IoCallDriver(DeviceObject, Irp); - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&FileObject->Event, - UserRequest, - PreviousMode, - FALSE, - NULL); - Status = IoStatusBlock->Status; - } - - if (NT_SUCCESS(Status)) - { - _SEH_TRY - { - RtlCopyMemory(FsInformation, - SystemBuffer, - IoStatusBlock->Information); - } - _SEH_HANDLE - { - Status = _SEH_GetExceptionCode(); - } - _SEH_END; - } - - ExFreePool(SystemBuffer); + StackPtr->Parameters.QueryVolume.FsInformationClass = FsInformationClass; + + /* Call the Driver */ + Status = IopPerformSynchronousRequest(DeviceObject, + Irp, + FileObject, + TRUE, + PreviousMode, + !LocalEvent, + IopOtherTransfer); + + /* Check if this was async I/O */ + if (LocalEvent) + { + /* It was, finalize this request */ + Status = IopFinalizeAsynchronousIo(Status, + Event, + Irp, + PreviousMode, + &KernelIosb, + IoStatusBlock); + } + + /* Return status */ return Status; }