234 lines
6.9 KiB
C
234 lines
6.9 KiB
C
/*++
|
|
|
|
Copyright (c) 1989-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
qsfs.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code to implement the NtQueryVolumeInformationFile
|
|
and NtSetVolumeInformationFile system services for the NT I/O system.
|
|
|
|
--*/
|
|
|
|
#include "iop.h"
|
|
|
|
NTSTATUS
|
|
NtQueryVolumeInformationFile(
|
|
IN HANDLE FileHandle,
|
|
OUT PIO_STATUS_BLOCK IoStatusBlock,
|
|
OUT PVOID FsInformation,
|
|
IN ULONG Length,
|
|
IN FS_INFORMATION_CLASS FsInformationClass
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This service returns information about the volume associated with the
|
|
FileHandle parameter. The information returned in the buffer is defined
|
|
by the FsInformationClass parameter. The legal values for this parameter
|
|
are as follows:
|
|
|
|
o FileFsVolumeInformation
|
|
|
|
o FileFsSizeInformation
|
|
|
|
o FileFsDeviceInformation
|
|
|
|
o FileFsAttributeInformation
|
|
|
|
Arguments:
|
|
|
|
FileHandle - Supplies a handle to an open volume, directory, or file
|
|
for which information about the volume is returned.
|
|
|
|
IoStatusBlock - Address of the caller's I/O status block.
|
|
|
|
FsInformation - Supplies a buffer to receive the requested information
|
|
returned about the volume.
|
|
|
|
Length - Supplies the length, in bytes, of the FsInformation buffer.
|
|
|
|
FsInformationClass - Specifies the type of information which should be
|
|
returned about the volume.
|
|
|
|
Return Value:
|
|
|
|
The status returned is the final completion status of the operation.
|
|
|
|
--*/
|
|
|
|
{
|
|
PIRP irp;
|
|
NTSTATUS status;
|
|
PFILE_OBJECT fileObject;
|
|
PDEVICE_OBJECT deviceObject;
|
|
PIO_STACK_LOCATION irpSp;
|
|
KEVENT localEvent;
|
|
IO_STATUS_BLOCK localIoStatus;
|
|
BOOLEAN synchronousIo;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// Ensure that the FsInformationClass parameter is legal for querying
|
|
// information about the volume.
|
|
//
|
|
|
|
if ((ULONG) FsInformationClass >= FileFsMaximumInformation ||
|
|
IopQueryFsOperationLength[FsInformationClass] == 0) {
|
|
return STATUS_INVALID_INFO_CLASS;
|
|
}
|
|
|
|
//
|
|
// Finally, ensure that the supplied buffer is large enough to contain
|
|
// the information associated with the specified query operation that
|
|
// is to be performed.
|
|
//
|
|
|
|
if (Length < (ULONG) IopQueryFsOperationLength[FsInformationClass]) {
|
|
return STATUS_INFO_LENGTH_MISMATCH;
|
|
}
|
|
|
|
//
|
|
// There were no blatant errors so far, so reference the file object so
|
|
// the target device object can be found. Note that if the handle does
|
|
// not refer to a file object, or if the caller does not have the required
|
|
// access to the file, then it will fail.
|
|
//
|
|
|
|
status = ObReferenceObjectByHandle( FileHandle,
|
|
&IoFileObjectType,
|
|
(PVOID *) &fileObject);
|
|
if (!NT_SUCCESS( status )) {
|
|
return status;
|
|
}
|
|
|
|
if ((IopQueryFsOperationAccess[FsInformationClass] & FILE_READ_DATA) &&
|
|
!fileObject->ReadAccess) {
|
|
ObDereferenceObject( fileObject );
|
|
return STATUS_ACCESS_DENIED;
|
|
}
|
|
|
|
//
|
|
// Make a special check here to determine whether this is a synchronous
|
|
// I/O operation. If it is, then wait here until the file is owned by
|
|
// the current thread. If this is not a (serialized) synchronous I/O
|
|
// operation, then allocate and initialize the local event.
|
|
//
|
|
|
|
if (fileObject->Flags & FO_SYNCHRONOUS_IO) {
|
|
IopAcquireFileObjectLock(fileObject);
|
|
synchronousIo = TRUE;
|
|
} else {
|
|
synchronousIo = FALSE;
|
|
}
|
|
|
|
//
|
|
// Set the file object to the Not-Signaled state.
|
|
//
|
|
|
|
KeClearEvent( &fileObject->Event );
|
|
|
|
//
|
|
// Get a pointer to the device object for the target device.
|
|
//
|
|
|
|
deviceObject = fileObject->DeviceObject;
|
|
|
|
//
|
|
// If this I/O operation is not being performed as synchronous I/O,
|
|
// then allocate an event that will be used to synchronize the
|
|
// completion of this operation. That is, this system service is
|
|
// a synchronous API being invoked for a file that is opened for
|
|
// asynchronous I/O.
|
|
//
|
|
|
|
if (!(fileObject->Flags & FO_SYNCHRONOUS_IO)) {
|
|
KeInitializeEvent( &localEvent, SynchronizationEvent, FALSE );
|
|
}
|
|
|
|
//
|
|
// Allocate and initialize the I/O Request Packet (IRP) for this
|
|
// operation. The allocation is performed with an exception handler
|
|
// in case the caller does not have enough quota to allocate the packet.
|
|
|
|
irp = IoAllocateIrp( deviceObject->StackSize );
|
|
if (!irp) {
|
|
|
|
//
|
|
// An IRP could not be allocated. Cleanup and return an
|
|
// appropriate error status code.
|
|
//
|
|
|
|
return IopAllocateIrpCleanup( fileObject, (PKEVENT) NULL );
|
|
}
|
|
irp->Tail.Overlay.OriginalFileObject = fileObject;
|
|
irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
|
|
|
//
|
|
// Fill in the service independent parameters in the IRP.
|
|
//
|
|
|
|
irp->UserBuffer = FsInformation;
|
|
if (synchronousIo) {
|
|
irp->UserIosb = IoStatusBlock;
|
|
} else {
|
|
irp->UserEvent = &localEvent;
|
|
irp->UserIosb = &localIoStatus;
|
|
irp->Flags = IRP_SYNCHRONOUS_API;
|
|
}
|
|
irp->Flags |= IRP_DEFER_IO_COMPLETION;
|
|
|
|
//
|
|
// Get a pointer to the stack location for the first driver. This will
|
|
// be used to pass the original function codes and parameters.
|
|
//
|
|
|
|
irpSp = IoGetNextIrpStackLocation( irp );
|
|
irpSp->MajorFunction = IRP_MJ_QUERY_VOLUME_INFORMATION;
|
|
irpSp->FileObject = fileObject;
|
|
|
|
//
|
|
// Copy the caller's parameters to the service-specific portion of the
|
|
// IRP.
|
|
//
|
|
|
|
irpSp->Parameters.QueryVolume.Length = Length;
|
|
irpSp->Parameters.QueryVolume.FsInformationClass = FsInformationClass;
|
|
|
|
//
|
|
// Queue the packet, call the driver, and synchronize appopriately with
|
|
// I/O completion.
|
|
//
|
|
|
|
status = IopSynchronousServiceTail( deviceObject,
|
|
irp,
|
|
fileObject,
|
|
TRUE,
|
|
synchronousIo );
|
|
|
|
//
|
|
// If the file for this operation was not opened for synchronous I/O, then
|
|
// synchronization of completion of the I/O operation has not yet occurred
|
|
// since the allocated event must be used for synchronous APIs on files
|
|
// opened for asynchronous I/O. Synchronize the completion of the I/O
|
|
// operation now.
|
|
//
|
|
|
|
if (!synchronousIo) {
|
|
|
|
status = IopSynchronousApiServiceTail( status,
|
|
&localEvent,
|
|
irp,
|
|
&localIoStatus,
|
|
IoStatusBlock );
|
|
}
|
|
|
|
return status;
|
|
}
|