📄 volinfo.c
字号:
return Status;
}
//
// Internal support routine
//
NTSTATUS
FatQueryFsSizeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_SIZE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume size 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:
Status - Returns the status for the query
--*/
{
DebugTrace(0, Dbg, "FatQueryFsSizeInfo...\n", 0);
RtlZeroMemory( Buffer, sizeof(FILE_FS_SIZE_INFORMATION) );
//
// Set the output buffer.
//
Buffer->TotalAllocationUnits.LowPart =
Vcb->AllocationSupport.NumberOfClusters;
Buffer->AvailableAllocationUnits.LowPart =
Vcb->AllocationSupport.NumberOfFreeClusters;
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
//
// Adjust the length variable
//
*Length -= sizeof(FILE_FS_SIZE_INFORMATION);
//
// And return success to our caller
//
UNREFERENCED_PARAMETER( IrpContext );
return STATUS_SUCCESS;
}
//
// Internal support routine
//
NTSTATUS
FatQueryFsDeviceInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_DEVICE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume device 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:
Status - Returns the status for the query
--*/
{
DebugTrace(0, Dbg, "FatQueryFsDeviceInfo...\n", 0);
RtlZeroMemory( Buffer, sizeof(FILE_FS_DEVICE_INFORMATION) );
//
// Set the output buffer
//
Buffer->DeviceType = FILE_DEVICE_DISK;
Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
//
// Adjust the length variable
//
*Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
//
// And return success to our caller
//
UNREFERENCED_PARAMETER( IrpContext );
return STATUS_SUCCESS;
}
//
// Internal support routine
//
NTSTATUS
FatQueryFsAttributeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_ATTRIBUTE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume attribute 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:
Status - Returns the status for the query
--*/
{
ULONG BytesToCopy;
NTSTATUS Status;
DebugTrace(0, Dbg, "FatQueryFsAttributeInfo...\n", 0);
//
// Set the output buffer
//
Buffer->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES |
FILE_UNICODE_ON_DISK;
if (FlagOn( Vcb->VcbState, VCB_STATE_FLAG_WRITE_PROTECTED )) {
SetFlag( Buffer->FileSystemAttributes, FILE_READ_ONLY_VOLUME );
}
Buffer->MaximumComponentNameLength = FatData.ChicagoMode ? 255 : 12;
if (FatIsFat32(Vcb)) {
//
// Determine how much of the file system name will fit.
//
if ( (*Length - FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
FileSystemName[0] )) >= 10 ) {
BytesToCopy = 10;
*Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
FileSystemName[0] ) + 10;
Status = STATUS_SUCCESS;
} else {
BytesToCopy = *Length - FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
FileSystemName[0]);
*Length = 0;
Status = STATUS_BUFFER_OVERFLOW;
}
RtlCopyMemory( &Buffer->FileSystemName[0], L"FAT32", BytesToCopy );
} else {
//
// Determine how much of the file system name will fit.
//
if ( (*Length - FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
FileSystemName[0] )) >= 6 ) {
BytesToCopy = 6;
*Length -= FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
FileSystemName[0] ) + 6;
Status = STATUS_SUCCESS;
} else {
BytesToCopy = *Length - FIELD_OFFSET( FILE_FS_ATTRIBUTE_INFORMATION,
FileSystemName[0]);
*Length = 0;
Status = STATUS_BUFFER_OVERFLOW;
}
RtlCopyMemory( &Buffer->FileSystemName[0], L"FAT", BytesToCopy );
}
Buffer->FileSystemNameLength = BytesToCopy;
//
// And return success to our caller
//
UNREFERENCED_PARAMETER( IrpContext );
UNREFERENCED_PARAMETER( Vcb );
return Status;
}
//
// Internal support routine
//
NTSTATUS
FatQueryFsFullSizeInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_FULL_SIZE_INFORMATION Buffer,
IN OUT PULONG Length
)
/*++
Routine Description:
This routine implements the query volume full size 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:
Status - Returns the status for the query
--*/
{
DebugTrace(0, Dbg, "FatQueryFsSizeInfo...\n", 0);
RtlZeroMemory( Buffer, sizeof(FILE_FS_FULL_SIZE_INFORMATION) );
Buffer->TotalAllocationUnits.LowPart =
Vcb->AllocationSupport.NumberOfClusters;
Buffer->CallerAvailableAllocationUnits.LowPart =
Vcb->AllocationSupport.NumberOfFreeClusters;
Buffer->ActualAvailableAllocationUnits.LowPart =
Buffer->CallerAvailableAllocationUnits.LowPart;
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
//
// Adjust the length variable
//
*Length -= sizeof(FILE_FS_FULL_SIZE_INFORMATION);
//
// And return success to our caller
//
UNREFERENCED_PARAMETER( IrpContext );
return STATUS_SUCCESS;
}
//
// Internal support routine
//
NTSTATUS
FatSetFsLabelInfo (
IN PIRP_CONTEXT IrpContext,
IN PVCB Vcb,
IN PFILE_FS_LABEL_INFORMATION Buffer
)
/*++
Routine Description:
This routine implements the set volume label call
Arguments:
Vcb - Supplies the Vcb being queried
Buffer - Supplies the input where the information is stored.
Return Value:
NTSTATUS - Returns the status for the operation
--*/
{
NTSTATUS Status;
PDIRENT Dirent;
PBCB DirentBcb = NULL;
ULONG ByteOffset;
WCHAR TmpBuffer[11];
UCHAR OemBuffer[11];
OEM_STRING OemLabel;
UNICODE_STRING UnicodeString;
UNICODE_STRING UpcasedLabel;
DebugTrace(+1, Dbg, "FatSetFsLabelInfo...\n", 0);
//
// Setup our local variable
//
UnicodeString.Length = (USHORT)Buffer->VolumeLabelLength;
UnicodeString.MaximumLength = UnicodeString.Length;
UnicodeString.Buffer = (PWSTR) &Buffer->VolumeLabel[0];
//
// Make sure the name can fit into the stack buffer
//
if ( UnicodeString.Length > 11*sizeof(WCHAR) ) {
return STATUS_INVALID_VOLUME_LABEL;
}
//
// Upcase the name and convert it to the Oem code page.
//
OemLabel.Buffer = &OemBuffer[0];
OemLabel.Length = 0;
OemLabel.MaximumLength = 11;
Status = RtlUpcaseUnicodeStringToCountedOemString( &OemLabel,
&UnicodeString,
FALSE );
//
// Volume label that fits in 11 unicode character length limit
// is not necessary within 11 characters in OEM character set.
//
if (!NT_SUCCESS( Status )) {
DebugTrace(-1, Dbg, "FatSetFsLabelInfo: Label must be too long. %08lx\n", Status );
return STATUS_INVALID_VOLUME_LABEL;
}
//
// Strip spaces off of the label.
//
if (OemLabel.Length > 0) {
USHORT i;
USHORT LastSpaceIndex = MAXUSHORT;
//
// Check the label for illegal characters
//
for ( i = 0; i < (ULONG)OemLabel.Length; i += 1 ) {
if ( FsRtlIsLeadDbcsCharacter( OemLabel.Buffer[i] ) ) {
LastSpaceIndex = MAXUSHORT;
i += 1;
continue;
}
if (!FsRtlIsAnsiCharacterLegalFat(OemLabel.Buffer[i], FALSE) ||
(OemLabel.Buffer[i] == '.')) {
return STATUS_INVALID_VOLUME_LABEL;
}
//
// Watch for the last run of spaces, so we can strip them.
//
if (OemLabel.Buffer[i] == ' ' &&
LastSpaceIndex == MAXUSHORT) {
LastSpaceIndex = i;
} else {
LastSpaceIndex = MAXUSHORT;
}
}
if (LastSpaceIndex != MAXUSHORT) {
OemLabel.Length = LastSpaceIndex;
}
}
//
// Get the Unicode upcased string to store in the VPB.
//
UpcasedLabel.Length = UnicodeString.Length;
UpcasedLabel.MaximumLength = 11*sizeof(WCHAR);
UpcasedLabel.Buffer = &TmpBuffer[0];
Status = RtlOemStringToCountedUnicodeString( &UpcasedLabel,
&OemLabel,
FALSE );
if (!NT_SUCCESS( Status )) {
DebugTrace(-1, Dbg, "FatSetFsLabelInfo: Label must be too long. %08lx\n", Status );
return STATUS_INVALID_VOLUME_LABEL;
}
DirentBcb = NULL;
//
// Make this look like a write through to disk. This is important to
// avoid a unpleasant window where it looks like we have the wrong volume.
//
SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH );
try {
//
// Are we setting or removing the label? Note that shaving spaces could
// make this different than wondering if the input buffer is non-zero length.
//
if (OemLabel.Length > 0) {
//
// Locate the volume label if there already is one
//
FatLocateVolumeLabel( IrpContext,
Vcb,
&Dirent,
&DirentBcb,
&ByteOffset );
//
// Check that we really got one, if not then we need to create
// a new one. The procedure we call will raise an appropriate
// status if we are not able to allocate a new dirent
//
if (Dirent == NULL) {
ByteOffset = FatCreateNewDirent( IrpContext,
Vcb->RootDcb,
1 );
FatPrepareWriteDirectoryFile( IrpContext,
Vcb->RootDcb,
ByteOffset,
sizeof(DIRENT),
&DirentBcb,
&Dirent,
FALSE,
TRUE,
&Status );
ASSERT( NT_SUCCESS( Status ));
} else {
//
// Just mark this guy dirty now.
//
FatSetDirtyBcb( IrpContext, DirentBcb, Vcb, TRUE );
}
//
// Now reconstruct the volume label dirent.
//
FatConstructLabelDirent( IrpContext,
Dirent,
&OemLabel );
//
// Unpin the Bcb here so that we will get any IO errors
// here before changing the VPB label.
//
FatUnpinBcb( IrpContext, DirentBcb );
FatUnpinRepinnedBcbs( IrpContext );
//
// Now set the upcased label in the VPB
//
RtlCopyMemory( &Vcb->Vpb->VolumeLabel[0],
&UpcasedLabel.Buffer[0],
UpcasedLabel.Length );
Vcb->Vpb->VolumeLabelLength = UpcasedLabel.Length;
} else {
//
// Otherwise we're trying to delete the label
// Locate the current volume label if there already is one
//
FatLocateVolumeLabel( IrpContext,
Vcb,
&Dirent,
&DirentBcb,
&ByteOffset );
//
// Check that we really got one
//
if (Dirent == NULL) {
try_return( Status = STATUS_SUCCESS );
}
//
// Now delete the current label.
//
Dirent->FileName[0] = FAT_DIRENT_DELETED;
ASSERT( (Vcb->RootDcb->Specific.Dcb.UnusedDirentVbo == 0xffffffff) ||
RtlAreBitsSet( &Vcb->RootDcb->Specific.Dcb.FreeDirentBitmap,
ByteOffset / sizeof(DIRENT),
1 ) );
RtlClearBits( &Vcb->RootDcb->Specific.Dcb.FreeDirentBitmap,
ByteOffset / sizeof(DIRENT),
1 );
FatSetDirtyBcb( IrpContext, DirentBcb, Vcb, TRUE );
//
// Unpin the Bcb here so that we will get any IO errors
// here before changing the VPB label.
//
FatUnpinBcb( IrpContext, DirentBcb );
FatUnpinRepinnedBcbs( IrpContext );
//
// Now set the label in the VPB
//
Vcb->Vpb->VolumeLabelLength = 0;
}
Status = STATUS_SUCCESS;
try_exit: NOTHING;
} finally {
DebugUnwind( FatSetFsALabelInfo );
FatUnpinBcb( IrpContext, DirentBcb );
DebugTrace(-1, Dbg, "FatSetFsALabelInfo -> STATUS_SUCCESS\n", 0);
}
return Status;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -