[fastfat_new]
authorAleksey Bragin <aleksey@reactos.org>
Wed, 14 Oct 2009 15:59:14 +0000 (15:59 +0000)
committerAleksey Bragin <aleksey@reactos.org>
Wed, 14 Oct 2009 15:59:14 +0000 (15:59 +0000)
- Implement shared VCB locking.
- Implement QueryVolumeInfo common handler, and a handler of QueryFsVolumeInfo class. Doesn't currently work due to missing VPB.

svn path=/trunk/; revision=43453

reactos/drivers/filesystems/fastfat_new/fastfat.c
reactos/drivers/filesystems/fastfat_new/fastfat.h
reactos/drivers/filesystems/fastfat_new/volume.c

index 52db0af..533e752 100644 (file)
@@ -385,6 +385,23 @@ FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
     }
 }
 
+BOOLEAN
+NTAPI
+FatAcquireSharedVcb(IN PFAT_IRP_CONTEXT IrpContext,
+                    IN PVCB Vcb)
+{
+    /* Acquire VCB's resource if possible */
+    if (ExAcquireResourceSharedLite(&Vcb->Resource,
+                                    BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
+    {
+        return TRUE;
+    }
+    else
+    {
+        return FALSE;
+    }
+}
+
 VOID
 NTAPI
 FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
index ccfb7a2..1ecdb6c 100644 (file)
@@ -143,6 +143,10 @@ BOOLEAN NTAPI
 FatAcquireExclusiveVcb(IN PFAT_IRP_CONTEXT IrpContext,
                        IN PVCB Vcb);
 
+BOOLEAN NTAPI
+FatAcquireSharedVcb(IN PFAT_IRP_CONTEXT IrpContext,
+                    IN PVCB Vcb);
+
 VOID NTAPI
 FatReleaseVcb(IN PFAT_IRP_CONTEXT IrpContext,
               IN PVCB Vcb);
index 3bcb558..f32f4ef 100644 (file)
 
 /* INCLUDES *****************************************************************/
 
-#define NDEBUG
+//#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
+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;
+    default:
+        DPRINT1("Volume information class %d is not supported!\n", InfoClass);
+        UNIMPLEMENTED;
+    }
+
+    /* 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)
 {
-    DPRINT1("FatQueryVolumeInfo()\n");
-    return STATUS_NOT_IMPLEMENTED;
+    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 */
+    if (IoGetTopLevelIrp() == NULL)
+    {
+        IoSetTopLevelIrp(Irp);
+        TopLevel = TRUE;
+    }
+
+    /* 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