mirror of
https://github.com/reactos/reactos.git
synced 2024-09-10 04:42:00 +00:00
![Amine Khaldi](/assets/img/avatar_default.png)
* Create a branch for some evul shell experiments. svn path=/branches/shell-experiments/; revision=61927
272 lines
7.1 KiB
C
272 lines
7.1 KiB
C
/*
|
|
* PROJECT: ReactOS FAT file system driver
|
|
* LICENSE: GNU GPLv3 as published by the Free Software Foundation
|
|
* FILE: drivers/filesystems/fastfat/volume.c
|
|
* PURPOSE: Volume information
|
|
* PROGRAMMERS: Aleksey Bragin (aleksey@reactos.org)
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#define NDEBUG
|
|
#include "fastfat.h"
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatiQueryFsVolumeInfo(PVCB Vcb,
|
|
PFILE_FS_VOLUME_INFORMATION Buffer,
|
|
PLONG Length)
|
|
{
|
|
ULONG ByteSize;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/* Deduct the minimum written length */
|
|
*Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
|
|
|
|
/* Zero it */
|
|
RtlZeroMemory(Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
|
|
|
|
DPRINT("Serial number 0x%x, label length %d\n",
|
|
Vcb->Vpb->SerialNumber, Vcb->Vpb->VolumeLabelLength);
|
|
|
|
/* Save serial number */
|
|
Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
|
|
|
|
/* Set max byte size */
|
|
ByteSize = Vcb->Vpb->VolumeLabelLength;
|
|
|
|
/* Check buffer length and reduce byte size if needed */
|
|
if (*Length < Vcb->Vpb->VolumeLabelLength)
|
|
{
|
|
/* Copy only up to what buffer size was provided */
|
|
ByteSize = *Length;
|
|
Status = STATUS_BUFFER_OVERFLOW;
|
|
}
|
|
|
|
/* Copy volume label */
|
|
Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
|
|
RtlCopyMemory(Buffer->VolumeLabel, Vcb->Vpb->VolumeLabel, ByteSize);
|
|
*Length -= ByteSize;
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatiQueryFsSizeInfo(PVCB Vcb,
|
|
PFILE_FS_SIZE_INFORMATION Buffer,
|
|
PLONG Length)
|
|
{
|
|
FF_PARTITION *Partition;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/* Deduct the minimum written length */
|
|
*Length -= sizeof(FILE_FS_SIZE_INFORMATION);
|
|
|
|
/* Zero it */
|
|
RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION));
|
|
|
|
/* Reference FullFAT's partition */
|
|
Partition = Vcb->Ioman->pPartition;
|
|
|
|
/* Set values */
|
|
Buffer->AvailableAllocationUnits.LowPart = Partition->FreeClusterCount;
|
|
Buffer->TotalAllocationUnits.LowPart = Partition->NumClusters;
|
|
Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
|
|
Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
|
|
|
|
DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->NumClusters,
|
|
Partition->FreeClusterCount, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatiQueryFsDeviceInfo(PVCB Vcb,
|
|
PFILE_FS_DEVICE_INFORMATION Buffer,
|
|
PLONG Length)
|
|
{
|
|
/* Deduct the minimum written length */
|
|
*Length -= sizeof(FILE_FS_DEVICE_INFORMATION);
|
|
|
|
/* Zero it */
|
|
RtlZeroMemory(Buffer, sizeof(FILE_FS_DEVICE_INFORMATION));
|
|
|
|
/* Set values */
|
|
Buffer->DeviceType = FILE_DEVICE_DISK;
|
|
Buffer->Characteristics = Vcb->TargetDeviceObject->Characteristics;
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatiQueryVolumeInfo(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
|
|
{
|
|
PFILE_OBJECT FileObject;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
FILE_INFORMATION_CLASS InfoClass;
|
|
TYPE_OF_OPEN FileType;
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PCCB Ccb;
|
|
LONG Length;
|
|
PVOID Buffer;
|
|
BOOLEAN VcbLocked = FALSE;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
|
|
/* Get IRP stack location */
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
|
|
/* Get the file object */
|
|
FileObject = IrpSp->FileObject;
|
|
|
|
/* Copy variables to something with shorter names */
|
|
InfoClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
|
|
Length = IrpSp->Parameters.QueryVolume.Length;
|
|
Buffer = Irp->AssociatedIrp.SystemBuffer;
|
|
|
|
DPRINT("FatiQueryVolumeInfo\n", 0);
|
|
DPRINT("\tIrp = %08lx\n", Irp);
|
|
DPRINT("\tLength = %08lx\n", Length);
|
|
DPRINT("\tFsInformationClass = %08lx\n", InfoClass);
|
|
DPRINT("\tBuffer = %08lx\n", Buffer);
|
|
|
|
FileType = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);
|
|
|
|
DPRINT("Vcb %p, Fcb %p, Ccb %p, open type %d\n", Vcb, Fcb, Ccb, FileType);
|
|
|
|
switch (InfoClass)
|
|
{
|
|
case FileFsVolumeInformation:
|
|
/* Acquired the shared VCB lock */
|
|
if (!FatAcquireSharedVcb(IrpContext, Vcb))
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
|
|
/* Remember we locked it */
|
|
VcbLocked = TRUE;
|
|
|
|
/* Call FsVolumeInfo handler */
|
|
Status = FatiQueryFsVolumeInfo(Vcb, Buffer, &Length);
|
|
break;
|
|
|
|
case FileFsSizeInformation:
|
|
/* Call FsVolumeInfo handler */
|
|
Status = FatiQueryFsSizeInfo(Vcb, Buffer, &Length);
|
|
break;
|
|
|
|
case FileFsDeviceInformation:
|
|
Status = FatiQueryFsDeviceInfo(Vcb, Buffer, &Length);
|
|
break;
|
|
|
|
case FileFsAttributeInformation:
|
|
UNIMPLEMENTED;
|
|
//Status = FatiQueryFsAttributeInfo(IrpContext, Vcb, Buffer, &Length);
|
|
break;
|
|
|
|
case FileFsFullSizeInformation:
|
|
UNIMPLEMENTED;
|
|
//Status = FatiQueryFsFullSizeInfo(IrpContext, Vcb, Buffer, &Length);
|
|
break;
|
|
|
|
default:
|
|
Status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
/* Set IoStatus.Information to amount of filled bytes */
|
|
Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
|
|
|
|
/* Release VCB lock */
|
|
if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
|
|
|
|
/* Complete request and return status */
|
|
FatCompleteRequest(IrpContext, Irp, Status);
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatQueryVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
NTSTATUS Status;
|
|
BOOLEAN TopLevel, CanWait;
|
|
PFAT_IRP_CONTEXT IrpContext;
|
|
|
|
CanWait = TRUE;
|
|
TopLevel = FALSE;
|
|
Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
|
|
/* Get CanWait flag */
|
|
if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
|
|
CanWait = IoIsOperationSynchronous(Irp);
|
|
|
|
/* Enter FsRtl critical region */
|
|
FsRtlEnterFileSystem();
|
|
|
|
/* Set Top Level IRP if not set */
|
|
TopLevel = FatIsTopLevelIrp(Irp);
|
|
|
|
/* Build an irp context */
|
|
IrpContext = FatBuildIrpContext(Irp, CanWait);
|
|
|
|
/* Call the request handler */
|
|
Status = FatiQueryVolumeInfo(IrpContext, Irp);
|
|
|
|
/* Restore top level Irp */
|
|
if (TopLevel)
|
|
IoSetTopLevelIrp(NULL);
|
|
|
|
/* Leave FsRtl critical region */
|
|
FsRtlExitFileSystem();
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
NTAPI
|
|
FatSetVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
|
|
{
|
|
DPRINT1("FatSetVolumeInfo()\n");
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
VOID
|
|
NTAPI
|
|
FatReadStreamFile(PVCB Vcb,
|
|
ULONGLONG ByteOffset,
|
|
ULONG ByteSize,
|
|
PBCB *Bcb,
|
|
PVOID *Buffer)
|
|
{
|
|
LARGE_INTEGER Offset;
|
|
|
|
Offset.QuadPart = ByteOffset;
|
|
|
|
if (!CcMapData(Vcb->StreamFileObject,
|
|
&Offset,
|
|
ByteSize,
|
|
TRUE, // FIXME: CanWait
|
|
Bcb,
|
|
Buffer))
|
|
{
|
|
ASSERT(FALSE);
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
NTAPI
|
|
FatCheckForDismount(IN PFAT_IRP_CONTEXT IrpContext,
|
|
PVCB Vcb,
|
|
IN BOOLEAN Force)
|
|
{
|
|
/* We never allow deletion of a volume for now */
|
|
return FALSE;
|
|
}
|
|
|
|
/* EOF */
|