mirror of
https://github.com/reactos/reactos.git
synced 2025-01-10 08:10:18 +00:00
- 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:
parent
7dc0e5e4e8
commit
b17492f448
1 changed files with 92 additions and 66 deletions
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue