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;
}