mirror of
https://github.com/reactos/reactos.git
synced 2025-01-10 08:10:18 +00:00
- Combine IoQueryVolumeInformation and IoQueryFileInformation
- Fix them to lock the fileobject for synch operations, use IopCleanupFailedIrp, queue the IRP in the thread's list, support aborting the I/o operation through IopAbortInterruptedIrp, and properly wait for comlpetion. svn path=/trunk/; revision=22770
This commit is contained in:
parent
13ef11ff23
commit
588b81a0ba
1 changed files with 136 additions and 133 deletions
|
@ -354,6 +354,128 @@ IopDeviceFsIoControl(IN HANDLE DeviceHandle,
|
|||
IopOtherTransfer);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopQueryDeviceInformation(IN PFILE_OBJECT FileObject,
|
||||
IN ULONG InformationClass,
|
||||
IN ULONG Length,
|
||||
OUT PVOID Information,
|
||||
OUT PULONG ReturnedLength,
|
||||
IN BOOLEAN File)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIRP Irp;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PIO_STACK_LOCATION StackPtr;
|
||||
BOOLEAN LocalEvent = FALSE;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
PAGED_CODE();
|
||||
|
||||
/* Reference the object */
|
||||
ObReferenceObject(FileObject);
|
||||
|
||||
/* Check if this is a file that was opened for Synch I/O */
|
||||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Lock it */
|
||||
IopLockFileObject(FileObject);
|
||||
|
||||
/* Use File Object event */
|
||||
KeClearEvent(&FileObject->Event);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use local event */
|
||||
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
||||
LocalEvent = TRUE;
|
||||
}
|
||||
|
||||
/* Get the Device Object */
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
|
||||
/* Allocate the IRP */
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
if (!Irp) return IopCleanupFailedIrp(FileObject, NULL);
|
||||
|
||||
/* Set the IRP */
|
||||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||
Irp->RequestorMode = KernelMode;
|
||||
Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
|
||||
Irp->UserIosb = &IoStatusBlock;
|
||||
Irp->UserEvent = (LocalEvent) ? &Event : NULL;
|
||||
Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
|
||||
Irp->Flags |= IRP_BUFFERED_IO;
|
||||
Irp->AssociatedIrp.SystemBuffer = Information;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
|
||||
/* Set the Stack Data */
|
||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||
StackPtr->MajorFunction = File ? IRP_MJ_QUERY_INFORMATION:
|
||||
IRP_MJ_QUERY_VOLUME_INFORMATION;
|
||||
StackPtr->FileObject = FileObject;
|
||||
|
||||
/* Check which type this is */
|
||||
if (File)
|
||||
{
|
||||
/* Set Parameters */
|
||||
StackPtr->Parameters.QueryFile.FileInformationClass = InformationClass;
|
||||
StackPtr->Parameters.QueryFile.Length = Length;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Parameters */
|
||||
StackPtr->Parameters.QueryVolume.FsInformationClass = InformationClass;
|
||||
StackPtr->Parameters.QueryVolume.Length = Length;
|
||||
}
|
||||
|
||||
/* Queue the IRP */
|
||||
IopQueueIrpToThread(Irp);
|
||||
|
||||
/* Call the Driver */
|
||||
Status = IoCallDriver(FileObject->DeviceObject, Irp);
|
||||
|
||||
/* Check if this was synch I/O */
|
||||
if (!LocalEvent)
|
||||
{
|
||||
/* Check if the requet is pending */
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* Wait on the file object */
|
||||
Status = KeWaitForSingleObject(&FileObject->Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FileObject->Flags & FO_ALERTABLE_IO,
|
||||
NULL);
|
||||
if (Status == STATUS_ALERTED)
|
||||
{
|
||||
/* Abort the operation */
|
||||
IopAbortInterruptedIrp(&FileObject->Event, Irp);
|
||||
}
|
||||
|
||||
/* Get the final status */
|
||||
Status = FileObject->FinalStatus;
|
||||
}
|
||||
|
||||
/* Release the file lock */
|
||||
IopUnlockFileObject(FileObject);
|
||||
}
|
||||
else if (Status == STATUS_PENDING)
|
||||
{
|
||||
/* Wait on the local event and get the final status */
|
||||
KeWaitForSingleObject(&Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
/* Return the Length and Status. ReturnedLength is NOT optional */
|
||||
*ReturnedLength = IoStatusBlock.Information;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
IopQueryDirectoryFileCompletion(IN PDEVICE_OBJECT DeviceObject,
|
||||
|
@ -470,85 +592,13 @@ IoQueryFileInformation(IN PFILE_OBJECT FileObject,
|
|||
OUT PVOID FileInformation,
|
||||
OUT PULONG ReturnedLength)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIRP Irp;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PIO_STACK_LOCATION StackPtr;
|
||||
BOOLEAN LocalEvent = FALSE;
|
||||
KEVENT Event;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ObReferenceObjectByPointer(FileObject,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
IoFileObjectType,
|
||||
KernelMode);
|
||||
if (!NT_SUCCESS(Status)) return(Status);
|
||||
|
||||
/* Get the Device Object */
|
||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||
|
||||
/* Check if we should use Sync IO or not */
|
||||
if (FileObject->Flags & FO_SYNCHRONOUS_IO)
|
||||
{
|
||||
/* Use File Object event */
|
||||
KeClearEvent(&FileObject->Event);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use local event */
|
||||
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
||||
LocalEvent = TRUE;
|
||||
}
|
||||
|
||||
/* Allocate the IRP */
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||
|
||||
/* Set the IRP */
|
||||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||
Irp->RequestorMode = KernelMode;
|
||||
Irp->AssociatedIrp.SystemBuffer = FileInformation;
|
||||
Irp->UserIosb = &IoStatusBlock;
|
||||
Irp->UserEvent = (LocalEvent) ? &Event : NULL;
|
||||
Irp->Flags = (LocalEvent) ? IRP_SYNCHRONOUS_API : 0;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
|
||||
/* Set the Stack Data */
|
||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||
StackPtr->MajorFunction = IRP_MJ_QUERY_INFORMATION;
|
||||
StackPtr->FileObject = FileObject;
|
||||
|
||||
/* Set Parameters */
|
||||
StackPtr->Parameters.QueryFile.FileInformationClass = FileInformationClass;
|
||||
StackPtr->Parameters.QueryFile.Length = Length;
|
||||
|
||||
/* Call the Driver */
|
||||
Status = IoCallDriver(FileObject->DeviceObject, Irp);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
if (LocalEvent)
|
||||
{
|
||||
KeWaitForSingleObject(&Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FileObject->Flags & FO_ALERTABLE_IO,
|
||||
NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
else
|
||||
{
|
||||
KeWaitForSingleObject(&FileObject->Event,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FileObject->Flags & FO_ALERTABLE_IO,
|
||||
NULL);
|
||||
Status = FileObject->FinalStatus;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the Length and Status. ReturnedLength is NOT optional */
|
||||
*ReturnedLength = IoStatusBlock.Information;
|
||||
return Status;
|
||||
/* Call the shared routine */
|
||||
return IopQueryDeviceInformation(FileObject,
|
||||
FileInformationClass,
|
||||
Length,
|
||||
FileInformation,
|
||||
ReturnedLength,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -562,60 +612,13 @@ IoQueryVolumeInformation(IN PFILE_OBJECT FileObject,
|
|||
OUT PVOID FsInformation,
|
||||
OUT PULONG ReturnedLength)
|
||||
{
|
||||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
PIO_STACK_LOCATION StackPtr;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PIRP Irp;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = ObReferenceObjectByPointer(FileObject,
|
||||
FILE_READ_ATTRIBUTES,
|
||||
IoFileObjectType,
|
||||
KernelMode);
|
||||
if (!NT_SUCCESS(Status)) return(Status);
|
||||
|
||||
DeviceObject = FileObject->DeviceObject;
|
||||
|
||||
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
||||
if (!Irp)
|
||||
{
|
||||
ObDereferenceObject(FileObject);
|
||||
return(STATUS_INSUFFICIENT_RESOURCES);
|
||||
}
|
||||
|
||||
/* Trigger FileObject/Event dereferencing */
|
||||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||
Irp->RequestorMode = KernelMode;
|
||||
Irp->AssociatedIrp.SystemBuffer = FsInformation;
|
||||
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;
|
||||
StackPtr->Parameters.QueryVolume.Length = Length;
|
||||
StackPtr->Parameters.QueryVolume.FsInformationClass =
|
||||
FsInformationClass;
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&FileObject->Event,
|
||||
UserRequest,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
Status = IoStatusBlock.Status;
|
||||
}
|
||||
|
||||
if (ReturnedLength) *ReturnedLength = IoStatusBlock.Information;
|
||||
return Status;
|
||||
/* Call the shared routine */
|
||||
return IopQueryDeviceInformation(FileObject,
|
||||
FsInformationClass,
|
||||
Length,
|
||||
FsInformation,
|
||||
ReturnedLength,
|
||||
FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue