📄 volinfo.c
字号:
/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
VolInfo.c
Abstract:
This module implements the volume information routines for Fat called by
the dispatch driver.
--*/
#include "FatProcs.h"
//
// The local debug trace level
//
#define Dbg (DEBUG_TRACE_VOLINFO)
NTSTATUS
FatQueryFsVolumeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_VOLUME_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
FatQueryFsSizeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_SIZE_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
FatQueryFsDeviceInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_DEVICE_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
FatQueryFsAttributeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
FatQueryFsFullSizeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
IN OUT PULONG Length
);
NTSTATUS
FatSetFsLabelInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_LABEL_INFORMATION Buffer
);
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, FatCommonQueryVolumeInfo)
#pragma alloc_text(PAGE, FatCommonSetVolumeInfo)
#pragma alloc_text(PAGE, FatFsdQueryVolumeInformation)
#pragma alloc_text(PAGE, FatFsdSetVolumeInformation)
#pragma alloc_text(PAGE, FatQueryFsAttributeInfo)
#pragma alloc_text(PAGE, FatQueryFsDeviceInfo)
#pragma alloc_text(PAGE, FatQueryFsSizeInfo)
#pragma alloc_text(PAGE, FatQueryFsVolumeInfo)
#pragma alloc_text(PAGE, FatQueryFsFullSizeInfo)
#pragma alloc_text(PAGE, FatSetFsLabelInfo)
#endif
NTSTATUS
FatFsdQueryVolumeInformation (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the Fsd part of the NtQueryVolumeInformation API
call.
Arguments:
VolumeDeviceObject - Supplies the volume device object where the file
being queried exists.
Irp - Supplies the Irp being processed.
Return Value:
NTSTATUS - The FSD status for the Irp.
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
DebugTrace(+1, Dbg, "FatFsdQueryVolumeInformation\n", 0);
//
// Call the common query routine, with blocking allowed if synchronous
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonQueryVolumeInfo( IrpContext, Irp );
} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdQueryVolumeInformation -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatFsdSetVolumeInformation (
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
This routine implements the FSD part of the NtSetVolumeInformation API
call.
Arguments:
VolumeDeviceObject - Supplies the volume device object where the file
being set exists.
Irp - Supplies the Irp being processed.
Return Value:
NTSTATUS - The FSD status for the Irp.
--*/
{
NTSTATUS Status;
PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
DebugTrace(+1, Dbg, "FatFsdSetVolumeInformation\n", 0);
//
// Call the common set routine
//
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
try {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonSetVolumeInfo( IrpContext, Irp );
} except(FatExceptionFilter( IrpContext, GetExceptionInformation() )) {
//
// We had some trouble trying to perform the requested
// operation, so we'll abort the I/O request with
// the error status that we get back from the
// execption code
//
Status = FatProcessException( IrpContext, Irp, GetExceptionCode() );
}
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
//
// And return to our caller
//
DebugTrace(-1, Dbg, "FatFsdSetVolumeInformation -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;
}
NTSTATUS
FatCommonQueryVolumeInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for querying volume information called by both
the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
ULONG Length;
FS_INFORMATION_CLASS FsInformationClass;
PVOID Buffer;
BOOLEAN WeAcquiredVcb = FALSE;
//
// Get the current stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonQueryVolumeInfo...\n", 0);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, "->Length = %08lx\n", IrpSp->Parameters.QueryVolume.Length);
DebugTrace( 0, Dbg, "->FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass);
DebugTrace( 0, Dbg, "->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
//
// Reference our input parameters to make things easier
//
Length = IrpSp->Parameters.QueryVolume.Length;
FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Decode the file object to get the Vcb
//
(VOID) FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );
ASSERT( Vcb != NULL );
try {
//
// Make sure the vcb is in a usable condition. This will raise
// and error condition if the volume is unusable
//
// Also verify the Root Dcb since we need info from there.
//
FatVerifyFcb( IrpContext, Vcb->RootDcb );
//
// Based on the information class we'll do different actions. Each
// of the procedures that we're calling fills up the output buffer
// if possible and returns true if it successfully filled the buffer
// and false if it couldn't wait for any I/O to complete.
//
switch (FsInformationClass) {
case FileFsVolumeInformation:
//
// This is the only routine we need the Vcb shared because of
// copying the volume label. All other routines copy fields that
// cannot change or are just manifest constants.
//
if (!FatAcquireSharedVcb( IrpContext, Vcb )) {
DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);
Status = FatFsdPostRequest( IrpContext, Irp );
IrpContext = NULL;
Irp = NULL;
} else {
WeAcquiredVcb = TRUE;
Status = FatQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length );
}
break;
case FileFsSizeInformation:
Status = FatQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length );
break;
case FileFsDeviceInformation:
Status = FatQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length );
break;
case FileFsAttributeInformation:
Status = FatQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length );
break;
case FileFsFullSizeInformation:
Status = FatQueryFsFullSizeInfo( IrpContext, Vcb, Buffer, &Length );
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
//
// Set the information field to the number of bytes actually filled in.
//
if (Irp != NULL) {
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
}
} finally {
DebugUnwind( FatCommonQueryVolumeInfo );
if ( WeAcquiredVcb ) { FatReleaseVcb( IrpContext, Vcb ); }
if (!AbnormalTermination()) {
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatCommonQueryVolumeInfo -> %08lx\n", Status);
}
return Status;
}
NTSTATUS
FatCommonSetVolumeInfo (
IN PIRP_CONTEXT IrpContext,
IN PIRP Irp
)
/*++
Routine Description:
This is the common routine for setting Volume Information called by both
the fsd and fsp threads.
Arguments:
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The return status for the operation
--*/
{
NTSTATUS Status;
PIO_STACK_LOCATION IrpSp;
PVCB Vcb;
PFCB Fcb;
PCCB Ccb;
TYPE_OF_OPEN TypeOfOpen;
ULONG Length;
FS_INFORMATION_CLASS FsInformationClass;
PVOID Buffer;
//
// Get the current stack location
//
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonSetVolumeInfo...\n", 0);
DebugTrace( 0, Dbg, "Irp = %08lx\n", Irp );
DebugTrace( 0, Dbg, "->Length = %08lx\n", IrpSp->Parameters.SetVolume.Length);
DebugTrace( 0, Dbg, "->FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass);
DebugTrace( 0, Dbg, "->Buffer = %08lx\n", Irp->AssociatedIrp.SystemBuffer);
//
// Reference our input parameters to make things easier
//
Length = IrpSp->Parameters.SetVolume.Length;
FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
Buffer = Irp->AssociatedIrp.SystemBuffer;
//
// Decode the file object to get the Vcb
//
TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );
if (TypeOfOpen != UserVolumeOpen) {
FatCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED );
DebugTrace(-1, Dbg, "FatCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n", 0);
return STATUS_ACCESS_DENIED;
}
//
// Acquire exclusive access to the Vcb and enqueue the Irp if we didn't
// get access
//
if (!FatAcquireExclusiveVcb( IrpContext, Vcb )) {
DebugTrace(0, Dbg, "Cannot acquire Vcb\n", 0);
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatCommonSetVolumeInfo -> %08lx\n", Status );
return Status;
}
try {
//
// Make sure the vcb is in a usable condition. This will raise
// and error condition if the volume is unusable
//
// Also verify the Root Dcb since we need info from there.
//
FatVerifyFcb( IrpContext, Vcb->RootDcb );
//
// Based on the information class we'll do different actions. Each
// of the procedures that we're calling performs the action if
// possible and returns true if it successful and false if it couldn't
// wait for any I/O to complete.
//
switch (FsInformationClass) {
case FileFsLabelInformation:
Status = FatSetFsLabelInfo( IrpContext, Vcb, Buffer );
break;
default:
Status = STATUS_INVALID_PARAMETER;
break;
}
FatUnpinRepinnedBcbs( IrpContext );
} finally {
DebugUnwind( FatCommonSetVolumeInfo );
FatReleaseVcb( IrpContext, Vcb );
if (!AbnormalTermination()) {
FatCompleteRequest( IrpContext, Irp, Status );
}
DebugTrace(-1, Dbg, "FatCommonSetVolumeInfo -> %08lx\n", Status);
}
return Status;
}
//
// Internal support routine
//
NTSTATUS
FatQueryFsVolumeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_VOLUME_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume info call
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies a pointer to the output buffer where the information
is to be returned
Length - Supplies the length of the buffer in byte. This variable
upon return recieves the remaining bytes free in the buffer
Return Value:
NTSTATUS - Returns the status for the query
--*/
{
ULONG BytesToCopy;
NTSTATUS Status;
DebugTrace(0, Dbg, "FatQueryFsVolumeInfo...\n", 0);
//
// Zero out the buffer, then extract and fill up the non zero fields.
//
RtlZeroMemory( Buffer, sizeof(FILE_FS_VOLUME_INFORMATION) );
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
Buffer->SupportsObjects = FALSE;
*Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
//
// Check if the buffer we're given is long enough
//
if ( *Length >= (ULONG)Vcb->Vpb->VolumeLabelLength ) {
BytesToCopy = Vcb->Vpb->VolumeLabelLength;
Status = STATUS_SUCCESS;
} else {
BytesToCopy = *Length;
Status = STATUS_BUFFER_OVERFLOW;
}
//
// Copy over what we can of the volume label, and adjust *Length
//
Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
RtlCopyMemory( &Buffer->VolumeLabel[0],
&Vcb->Vpb->VolumeLabel[0],
BytesToCopy );
*Length -= BytesToCopy;
//
// Set our status and return to our caller
//
UNREFERENCED_PARAMETER( IrpContext );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -