- 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.

svn path=/trunk/; revision=22787
This commit is contained in:
Alex Ionescu 2006-07-02 22:14:20 +00:00
parent 7dc0e5e4e8
commit b17492f448

View file

@ -2642,111 +2642,137 @@ NtQueryVolumeInformationFile(IN HANDLE FileHandle,
IN FS_INFORMATION_CLASS FsInformationClass) IN FS_INFORMATION_CLASS FsInformationClass)
{ {
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PDEVICE_OBJECT DeviceObject;
PIRP Irp; PIRP Irp;
NTSTATUS Status = STATUS_SUCCESS;
PIO_STACK_LOCATION StackPtr; PIO_STACK_LOCATION StackPtr;
PVOID SystemBuffer; PDEVICE_OBJECT DeviceObject;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); PKEVENT Event = NULL;
BOOLEAN LocalEvent = FALSE;
KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();
NTSTATUS Status = STATUS_SUCCESS;
OBJECT_HANDLE_INFORMATION HandleInformation;
IO_STATUS_BLOCK KernelIosb;
PAGED_CODE();
/* Check if we're called from user mode */
if (PreviousMode != KernelMode) if (PreviousMode != KernelMode)
{ {
/* Enter SEH for probing */
_SEH_TRY _SEH_TRY
{ {
if (IoStatusBlock) /* Probe the I/O Status block */
{ ProbeForWrite(IoStatusBlock,
ProbeForWrite(IoStatusBlock, sizeof(IO_STATUS_BLOCK),
sizeof(IO_STATUS_BLOCK), sizeof(ULONG));
sizeof(ULONG));
}
/* Probe the information */
if (Length) ProbeForWrite(FsInformation, Length, 1); if (Length) ProbeForWrite(FsInformation, Length, 1);
} }
_SEH_HANDLE _SEH_HANDLE
{ {
/* Get the exception code */
Status = _SEH_GetExceptionCode(); Status = _SEH_GetExceptionCode();
} }
_SEH_END; _SEH_END;
if (!NT_SUCCESS(Status)) /* Check if probing failed */
{ if (!NT_SUCCESS(Status)) return Status;
return Status;
}
} }
/* Get File Object */
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
0, /* FIXME - depends on the information class! */ 0, // FIXME
IoFileObjectType, IoFileObjectType,
PreviousMode, PreviousMode,
(PVOID*)&FileObject, (PVOID*)&FileObject,
NULL); &HandleInformation);
if (!NT_SUCCESS(Status)) return Status; if (!NT_SUCCESS(Status)) return Status;
DeviceObject = FileObject->DeviceObject; /* Check if we should use Sync IO or not */
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
if (!Irp)
{ {
ObDereferenceObject(FileObject); /* Lock it */
return STATUS_INSUFFICIENT_RESOURCES; IopLockFileObject(FileObject);
}
else
{
/* Use local event */
Event = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEVENT), TAG_IO);
KeInitializeEvent(Event, SynchronizationEvent, FALSE);
LocalEvent = TRUE;
} }
SystemBuffer = ExAllocatePoolWithTag(NonPagedPool, Length, TAG_SYSB); /* Get the device object */
if (!SystemBuffer) DeviceObject = IoGetRelatedDeviceObject(FileObject);
{
IoFreeIrp(Irp);
ObDereferenceObject(FileObject);
return STATUS_INSUFFICIENT_RESOURCES;
}
/* Trigger FileObject/Event dereferencing */ /* Clear File Object event */
Irp->Tail.Overlay.OriginalFileObject = FileObject; 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->RequestorMode = PreviousMode;
Irp->AssociatedIrp.SystemBuffer = SystemBuffer; Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
KeResetEvent( &FileObject->Event ); Irp->UserIosb = (LocalEvent) ? &KernelIosb : IoStatusBlock;
Irp->UserEvent = &FileObject->Event; Irp->UserEvent = (LocalEvent) ? Event : NULL;
Irp->UserIosb = IoStatusBlock;
Irp->Tail.Overlay.Thread = PsGetCurrentThread(); 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 = IoGetNextIrpStackLocation(Irp);
StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION; StackPtr->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
StackPtr->MinorFunction = 0;
StackPtr->Flags = 0;
StackPtr->Control = 0;
StackPtr->DeviceObject = DeviceObject;
StackPtr->FileObject = FileObject; StackPtr->FileObject = FileObject;
StackPtr->Parameters.QueryVolume.Length = Length;
StackPtr->Parameters.QueryVolume.FsInformationClass =
FsInformationClass;
Status = IoCallDriver(DeviceObject, Irp); /* Allocate system buffer */
if (Status == STATUS_PENDING) Irp->AssociatedIrp.SystemBuffer = ExAllocatePoolWithTag(NonPagedPool,
Length,
TAG_SYSB);
if (!Irp->AssociatedIrp.SystemBuffer)
{ {
KeWaitForSingleObject(&FileObject->Event, /* Fail */
UserRequest, IoFreeIrp(Irp);
PreviousMode, if (Event) ObDereferenceObject(Event);
FALSE, ObDereferenceObject(FileObject);
NULL); return STATUS_INSUFFICIENT_RESOURCES;
Status = IoStatusBlock->Status; }
}
if (NT_SUCCESS(Status)) /* Set the flags for this buffered + deferred I/O */
{ Irp->Flags |= (IRP_BUFFERED_IO |
_SEH_TRY IRP_DEALLOCATE_BUFFER |
{ IRP_INPUT_OPERATION |
RtlCopyMemory(FsInformation, IRP_DEFER_IO_COMPLETION);
SystemBuffer,
IoStatusBlock->Information);
}
_SEH_HANDLE
{
Status = _SEH_GetExceptionCode();
}
_SEH_END;
}
ExFreePool(SystemBuffer); /* Set Parameters */
StackPtr->Parameters.QueryVolume.Length = Length;
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; return Status;
} }