[fastfat_new]
[reactos.git] / reactos / drivers / filesystems / fastfat_new / volume.c
index 1ced554..49a67b0 100644 (file)
 /*
- * COPYRIGHT:        See COPYING in the top level directory
- * PROJECT:          ReactOS kernel
- * FILE:             drivers/fs/vfat/volume.c
- * PURPOSE:          VFAT Filesystem
- * PROGRAMMER:       Jason Filby (jasonfilby@yahoo.com)
- *                   Herve Poussineau (reactos@poussine.freesurf.fr)
+ * 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
+//#define NDEBUG
 #include "fastfat.h"
 
 /* FUNCTIONS ****************************************************************/
 
-static NTSTATUS
-FsdGetFsVolumeInformation(PDEVICE_OBJECT DeviceObject,
-                         PFILE_FS_VOLUME_INFORMATION FsVolumeInfo,
-                         PULONG BufferLength)
+NTSTATUS
+NTAPI
+FatiQueryFsVolumeInfo(PVCB Vcb,
+                      PFILE_FS_VOLUME_INFORMATION Buffer,
+                      PLONG Length)
 {
-  DPRINT("FsdGetFsVolumeInformation()\n");
-  DPRINT("FsVolumeInfo = %p\n", FsVolumeInfo);
-  DPRINT("BufferLength %lu\n", *BufferLength);
+    ULONG ByteSize;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-  DPRINT("Required length %lu\n", (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength));
-  DPRINT("LabelLength %hu\n", DeviceObject->Vpb->VolumeLabelLength);
-  DPRINT("Label %*.S\n", DeviceObject->Vpb->VolumeLabelLength / sizeof(WCHAR), DeviceObject->Vpb->VolumeLabel);
+    /* Deduct the minimum written length */
+    *Length -= FIELD_OFFSET(FILE_FS_VOLUME_INFORMATION, VolumeLabel[0]);
 
-  if (*BufferLength < sizeof(FILE_FS_VOLUME_INFORMATION))
-    return STATUS_INFO_LENGTH_MISMATCH;
+    /* Zero it */
+    RtlZeroMemory(Buffer, sizeof(FILE_FS_VOLUME_INFORMATION));
 
-  if (*BufferLength < (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength))
-    return STATUS_BUFFER_OVERFLOW;
+    DPRINT("Serial number 0x%x, label length %d\n",
+        Vcb->Vpb->SerialNumber, Vcb->Vpb->VolumeLabelLength);
 
-  /* valid entries */
-  FsVolumeInfo->VolumeSerialNumber = DeviceObject->Vpb->SerialNumber;
-  FsVolumeInfo->VolumeLabelLength = DeviceObject->Vpb->VolumeLabelLength;
-  RtlCopyMemory(FsVolumeInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabel, FsVolumeInfo->VolumeLabelLength);
+    /* Save serial number */
+    Buffer->VolumeSerialNumber = Vcb->Vpb->SerialNumber;
 
-  /* dummy entries */
-  FsVolumeInfo->VolumeCreationTime.QuadPart = 0;
-  FsVolumeInfo->SupportsObjects = FALSE;
+    /* Set max byte size */
+    ByteSize = Vcb->Vpb->VolumeLabelLength;
 
-  DPRINT("Finished FsdGetFsVolumeInformation()\n");
-
-  *BufferLength -= (sizeof(FILE_FS_VOLUME_INFORMATION) + DeviceObject->Vpb->VolumeLabelLength);
-
-  DPRINT("BufferLength %lu\n", *BufferLength);
-
-  return(STATUS_SUCCESS);
-}
-
-
-static NTSTATUS
-FsdGetFsAttributeInformation(PDEVICE_EXTENSION DeviceExt,
-                            PFILE_FS_ATTRIBUTE_INFORMATION FsAttributeInfo,
-                            PULONG BufferLength)
-{
-  PCWSTR pName; ULONG Length;
-  DPRINT("FsdGetFsAttributeInformation()\n");
-  DPRINT("FsAttributeInfo = %p\n", FsAttributeInfo);
-  DPRINT("BufferLength %lu\n", *BufferLength);
-
-  if (*BufferLength < sizeof (FILE_FS_ATTRIBUTE_INFORMATION))
-    return STATUS_INFO_LENGTH_MISMATCH;
-
-  if (DeviceExt->FatInfo.FatType == FAT32)
-  {
-    Length = 10;
-    pName = L"FAT32";
-  }
-  else
-  {
-    Length = 6;
-    pName = L"FAT";
-  }
-
-  DPRINT("Required length %lu\n", (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length));
-
-  if (*BufferLength < (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length))
-    return STATUS_BUFFER_OVERFLOW;
-
-  FsAttributeInfo->FileSystemAttributes =
-    FILE_CASE_PRESERVED_NAMES | FILE_UNICODE_ON_DISK;
-
-  FsAttributeInfo->MaximumComponentNameLength = 255;
-
-  FsAttributeInfo->FileSystemNameLength = Length;
-
-  RtlCopyMemory(FsAttributeInfo->FileSystemName, pName, Length );
-
-  DPRINT("Finished FsdGetFsAttributeInformation()\n");
+    /* 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;
+    }
 
-  *BufferLength -= (sizeof(FILE_FS_ATTRIBUTE_INFORMATION) + Length);
-  DPRINT("BufferLength %lu\n", *BufferLength);
+    /* Copy volume label */
+    Buffer->VolumeLabelLength = Vcb->Vpb->VolumeLabelLength;
+    RtlCopyMemory(Buffer->VolumeLabel, Vcb->Vpb->VolumeLabel, ByteSize);
+    *Length -= ByteSize;
 
-  return(STATUS_SUCCESS);
+    return Status;
 }
 
-
-static NTSTATUS
-FsdGetFsSizeInformation(PDEVICE_OBJECT DeviceObject,
-                       PFILE_FS_SIZE_INFORMATION FsSizeInfo,
-                       PULONG BufferLength)
+NTSTATUS
+NTAPI
+FatiQueryFsSizeInfo(PVCB Vcb,
+                    PFILE_FS_SIZE_INFORMATION Buffer,
+                    PLONG Length)
 {
-  PDEVICE_EXTENSION DeviceExt;
-  NTSTATUS Status;
+    FF_PARTITION *Partition;
+    NTSTATUS Status = STATUS_SUCCESS;
 
-  DPRINT("FsdGetFsSizeInformation()\n");
-  DPRINT("FsSizeInfo = %p\n", FsSizeInfo);
+    /* Deduct the minimum written length */
+    *Length -= sizeof(FILE_FS_SIZE_INFORMATION);
 
-  if (*BufferLength < sizeof(FILE_FS_SIZE_INFORMATION))
-    return(STATUS_BUFFER_OVERFLOW);
+    /* Zero it */
+    RtlZeroMemory(Buffer, sizeof(FILE_FS_SIZE_INFORMATION));
 
-  DeviceExt = DeviceObject->DeviceExtension;
-  Status = CountAvailableClusters(DeviceExt, &FsSizeInfo->AvailableAllocationUnits);
+    /* Reference FullFAT's partition */
+    Partition = Vcb->Ioman->pPartition;
 
-  FsSizeInfo->TotalAllocationUnits.QuadPart = DeviceExt->FatInfo.NumberOfClusters;
-  FsSizeInfo->SectorsPerAllocationUnit = DeviceExt->FatInfo.SectorsPerCluster;
-  FsSizeInfo->BytesPerSector = DeviceExt->FatInfo.BytesPerSector;
+    /* Set values */
+    Buffer->AvailableAllocationUnits.LowPart = Partition->FreeClusterCount;
+    Buffer->TotalAllocationUnits.LowPart = Partition->NumClusters;
+    Buffer->SectorsPerAllocationUnit = Vcb->Bpb.SectorsPerCluster;
+    Buffer->BytesPerSector = Vcb->Bpb.BytesPerSector;
 
-  DPRINT("Finished FsdGetFsSizeInformation()\n");
-  if (NT_SUCCESS(Status))
-    *BufferLength -= sizeof(FILE_FS_SIZE_INFORMATION);
+    DPRINT1("Total %d, free %d, SPC %d, BPS %d\n", Partition->FreeClusterCount,
+        Partition->NumClusters, Vcb->Bpb.SectorsPerCluster, Vcb->Bpb.BytesPerSector);
 
-  return(Status);
+    return Status;
 }
 
-
-static NTSTATUS
-FsdGetFsDeviceInformation(PFILE_FS_DEVICE_INFORMATION FsDeviceInfo,
-                         PULONG BufferLength)
+NTSTATUS
+NTAPI
+FatiQueryVolumeInfo(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
 {
-  DPRINT("FsdGetFsDeviceInformation()\n");
-  DPRINT("FsDeviceInfo = %p\n", FsDeviceInfo);
-  DPRINT("BufferLength %lu\n", *BufferLength);
-  DPRINT("Required length %lu\n", sizeof(FILE_FS_DEVICE_INFORMATION));
-
-  if (*BufferLength < sizeof(FILE_FS_DEVICE_INFORMATION))
-    return(STATUS_BUFFER_OVERFLOW);
-
-  FsDeviceInfo->DeviceType = FILE_DEVICE_DISK;
-  FsDeviceInfo->Characteristics = 0; /* FIXME: fix this !! */
-
-  DPRINT("FsdGetFsDeviceInformation() finished.\n");
-
-  *BufferLength -= sizeof(FILE_FS_DEVICE_INFORMATION);
-  DPRINT("BufferLength %lu\n", *BufferLength);
-
-  return(STATUS_SUCCESS);
-}
+    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;
 
-static NTSTATUS
-FsdSetFsLabelInformation(PDEVICE_OBJECT DeviceObject,
-                        PFILE_FS_LABEL_INFORMATION FsLabelInfo)
-{
-  PDEVICE_EXTENSION DeviceExt;
-  PVOID Context = NULL;
-  ULONG DirIndex = 0;
-  PDIR_ENTRY Entry;
-  PVFATFCB pRootFcb;
-  LARGE_INTEGER FileOffset;
-  BOOLEAN LabelFound = FALSE;
-  DIR_ENTRY VolumeLabelDirEntry;
-  ULONG VolumeLabelDirIndex;
-  ULONG LabelLen;
-  NTSTATUS Status = STATUS_UNSUCCESSFUL;
-  OEM_STRING StringO;
-  UNICODE_STRING StringW;
-  CHAR cString[43];
-  ULONG SizeDirEntry;
-  ULONG EntriesPerPage;
-
-  DPRINT("FsdSetFsLabelInformation()\n");
-
-  DeviceExt = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
-
-  if (sizeof(DeviceObject->Vpb->VolumeLabel) < FsLabelInfo->VolumeLabelLength)
-  {
-    return STATUS_NAME_TOO_LONG;
-  }
-
-  if (DeviceExt->Flags & VCB_IS_FATX)
-  {
-    if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 42)
-      return STATUS_NAME_TOO_LONG;
-    SizeDirEntry = sizeof(FATX_DIR_ENTRY);
-    EntriesPerPage = FATX_ENTRIES_PER_PAGE;
-  }
-  else
-  {
-    if (FsLabelInfo->VolumeLabelLength / sizeof(WCHAR) > 11)
-      return STATUS_NAME_TOO_LONG;
-    SizeDirEntry = sizeof(FAT_DIR_ENTRY);
-    EntriesPerPage = FAT_ENTRIES_PER_PAGE;
-  }
-
-  /* Create Volume label dir entry */
-  LabelLen = FsLabelInfo->VolumeLabelLength / sizeof(WCHAR);
-  RtlZeroMemory(&VolumeLabelDirEntry, SizeDirEntry);
-  StringW.Buffer = FsLabelInfo->VolumeLabel;
-  StringW.Length = StringW.MaximumLength = (USHORT)FsLabelInfo->VolumeLabelLength;
-  StringO.Buffer = cString;
-  StringO.Length = 0;
-  StringO.MaximumLength = 42;
-  Status = RtlUnicodeStringToOemString(&StringO, &StringW, FALSE);
-  if (!NT_SUCCESS(Status))
-    return Status;
-  if (DeviceExt->Flags & VCB_IS_FATX)
-  {
-    RtlCopyMemory(VolumeLabelDirEntry.FatX.Filename, cString, LabelLen);
-    memset(&VolumeLabelDirEntry.FatX.Filename[LabelLen], ' ', 42 - LabelLen);
-    VolumeLabelDirEntry.FatX.Attrib = 0x08;
-  }
-  else
-  {
-    RtlCopyMemory(VolumeLabelDirEntry.Fat.Filename, cString, LabelLen);
-    memset(&VolumeLabelDirEntry.Fat.Filename[LabelLen], ' ', 11 - LabelLen);
-    VolumeLabelDirEntry.Fat.Attrib = 0x08;
-  }
-
-  pRootFcb = vfatOpenRootFCB(DeviceExt);
-
-  /* Search existing volume entry on disk */
-  FileOffset.QuadPart = 0;
-  if (CcPinRead(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
-  {
-    while (TRUE)
-    {
-      if (ENTRY_VOLUME(DeviceExt, Entry))
-      {
-        /* Update entry */
-        LabelFound = TRUE;
-        RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
-        CcSetDirtyPinnedData(Context, NULL);
-        Status = STATUS_SUCCESS;
+        /* Call FsVolumeInfo handler */
+        Status = FatiQueryFsVolumeInfo(Vcb, Buffer, &Length);
         break;
-      }
-      if (ENTRY_END(DeviceExt, Entry))
-      {
+    case FileFsSizeInformation:
+        /* Call FsVolumeInfo handler */
+        Status = FatiQueryFsSizeInfo(Vcb, Buffer, &Length);
         break;
-      }
-      DirIndex++;
-      Entry = (PDIR_ENTRY)((ULONG_PTR)Entry + SizeDirEntry);
-      if ((DirIndex % EntriesPerPage) == 0)
-      {
-            CcUnpinData(Context);
-            FileOffset.u.LowPart += PAGE_SIZE;
-            if (!CcPinRead(pRootFcb->FileObject, &FileOffset, PAGE_SIZE, TRUE, &Context, (PVOID*)&Entry))
-            {
-              Context = NULL;
-              break;
-            }
-      }
-    }
-    if (Context)
-    {
-      CcUnpinData(Context);
-    }
-  }
-  if (!LabelFound)
-  {
-    /* Add new entry for label */
-    if (!vfatFindDirSpace(DeviceExt, pRootFcb, 1, &VolumeLabelDirIndex))
-      Status = STATUS_DISK_FULL;
-    else
-    {
-      FileOffset.u.HighPart = 0;
-      FileOffset.u.LowPart = VolumeLabelDirIndex * SizeDirEntry;
-      CcPinRead(pRootFcb->FileObject, &FileOffset, SizeDirEntry,
-                 TRUE, &Context, (PVOID*)&Entry);
-      RtlCopyMemory(Entry, &VolumeLabelDirEntry, SizeDirEntry);
-      CcSetDirtyPinnedData(Context, NULL);
-      CcUnpinData(Context);
-      Status = STATUS_SUCCESS;
+    default:
+        DPRINT1("Volume information class %d is not supported!\n", InfoClass);
+        UNIMPLEMENTED;
     }
-  }
 
-  vfatReleaseFCB(DeviceExt, pRootFcb);
-  if (!NT_SUCCESS(Status))
-  {
-    return Status;
-  }
+    /* Set IoStatus.Information to amount of filled bytes */
+    Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;
 
-  /* Update volume label in memory */
-  DeviceObject->Vpb->VolumeLabelLength = (USHORT)FsLabelInfo->VolumeLabelLength;
-  RtlCopyMemory(DeviceObject->Vpb->VolumeLabel, FsLabelInfo->VolumeLabel, DeviceObject->Vpb->VolumeLabelLength);
+    /* Release VCB lock */
+    if (VcbLocked) FatReleaseVcb(IrpContext, Vcb);
 
-  return Status;
+    /* Complete request and return status */
+    FatCompleteRequest(IrpContext, Irp, Status);
+    return Status;
 }
 
-
-NTSTATUS VfatQueryVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
-/*
- * FUNCTION: Retrieve the specified volume information
- */
+NTSTATUS
+NTAPI
+FatQueryVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
-  FS_INFORMATION_CLASS FsInformationClass;
-  NTSTATUS RC = STATUS_SUCCESS;
-  PVOID SystemBuffer;
-  ULONG BufferLength;
-
-  /* PRECONDITION */
-  ASSERT(IrpContext);
+    NTSTATUS Status;
+    BOOLEAN TopLevel, CanWait;
+    PFAT_IRP_CONTEXT IrpContext;
 
-  DPRINT("VfatQueryVolumeInformation(IrpContext %p)\n", IrpContext);
+    CanWait = TRUE;
+    TopLevel = FALSE;
+    Status = STATUS_INVALID_DEVICE_REQUEST;
 
-  if (!ExAcquireResourceSharedLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
-                                   (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
-  {
-     return VfatQueueRequest (IrpContext);
-  }
+    /* Get CanWait flag */
+    if (IoGetCurrentIrpStackLocation(Irp)->FileObject != NULL)
+        CanWait = IoIsOperationSynchronous(Irp);
 
-  /* INITIALIZATION */
-  FsInformationClass = IrpContext->Stack->Parameters.QueryVolume.FsInformationClass;
-  BufferLength = IrpContext->Stack->Parameters.QueryVolume.Length;
-  SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
+    /* Enter FsRtl critical region */
+    FsRtlEnterFileSystem();
 
-
-  DPRINT ("FsInformationClass %d\n", FsInformationClass);
-  DPRINT ("SystemBuffer %p\n", SystemBuffer);
-
-  switch (FsInformationClass)
+    /* Set Top Level IRP if not set */
+    if (IoGetTopLevelIrp() == NULL)
     {
-    case FileFsVolumeInformation:
-      RC = FsdGetFsVolumeInformation(IrpContext->DeviceObject,
-                                    SystemBuffer,
-                                    &BufferLength);
-      break;
+        IoSetTopLevelIrp(Irp);
+        TopLevel = TRUE;
+    }
 
-    case FileFsAttributeInformation:
-      RC = FsdGetFsAttributeInformation(IrpContext->DeviceObject->DeviceExtension,
-                                       SystemBuffer,
-                                       &BufferLength);
-      break;
+    /* Build an irp context */
+    IrpContext = FatBuildIrpContext(Irp, CanWait);
 
-    case FileFsSizeInformation:
-      RC = FsdGetFsSizeInformation(IrpContext->DeviceObject,
-                                  SystemBuffer,
-                                  &BufferLength);
-      break;
+    /* Call the request handler */
+    Status = FatiQueryVolumeInfo(IrpContext, Irp);
 
-    case FileFsDeviceInformation:
-      RC = FsdGetFsDeviceInformation(SystemBuffer,
-                                    &BufferLength);
-      break;
+    /* Restore top level Irp */
+    if (TopLevel)
+        IoSetTopLevelIrp(NULL);
 
-    default:
-      RC = STATUS_NOT_SUPPORTED;
-    }
+    /* Leave FsRtl critical region */
+    FsRtlExitFileSystem();
 
-  ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
-  IrpContext->Irp->IoStatus.Status = RC;
-  if (NT_SUCCESS(RC))
-    IrpContext->Irp->IoStatus.Information =
-      IrpContext->Stack->Parameters.QueryVolume.Length - BufferLength;
-  else
-    IrpContext->Irp->IoStatus.Information = 0;
-  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
-  VfatFreeIrpContext(IrpContext);
-
-  return RC;
+    return Status;
 }
 
-
-NTSTATUS VfatSetVolumeInformation(PVFAT_IRP_CONTEXT IrpContext)
-/*
- * FUNCTION: Set the specified volume information
- */
+NTSTATUS
+NTAPI
+FatSetVolumeInfo(PDEVICE_OBJECT DeviceObject, PIRP Irp)
 {
-  FS_INFORMATION_CLASS FsInformationClass;
-  NTSTATUS Status = STATUS_SUCCESS;
-  PVOID SystemBuffer;
-  ULONG BufferLength;
-  PIO_STACK_LOCATION Stack = IrpContext->Stack;
-
-  /* PRECONDITION */
-  ASSERT(IrpContext);
-
-  DPRINT ("VfatSetVolumeInformation(IrpContext %p)\n", IrpContext);
-
-  if (!ExAcquireResourceExclusiveLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource,
-                                      (BOOLEAN)(IrpContext->Flags & IRPCONTEXT_CANWAIT)))
-  {
-     return VfatQueueRequest (IrpContext);
-  }
+    DPRINT1("FatSetVolumeInfo()\n");
+    return STATUS_NOT_IMPLEMENTED;
+}
 
-  FsInformationClass = Stack->Parameters.SetVolume.FsInformationClass;
-  BufferLength = Stack->Parameters.SetVolume.Length;
-  SystemBuffer = IrpContext->Irp->AssociatedIrp.SystemBuffer;
+VOID
+NTAPI
+FatReadStreamFile(PVCB Vcb,
+                  ULONGLONG ByteOffset,
+                  ULONG ByteSize,
+                  PBCB *Bcb,
+                  PVOID *Buffer)
+{
+    LARGE_INTEGER Offset;
 
-  DPRINT ("FsInformationClass %d\n", FsInformationClass);
-  DPRINT ("BufferLength %d\n", BufferLength);
-  DPRINT ("SystemBuffer %p\n", SystemBuffer);
+    Offset.QuadPart = ByteOffset;
 
-  switch(FsInformationClass)
+    if (!CcMapData(Vcb->StreamFileObject,
+                   &Offset,
+                   ByteSize,
+                   TRUE, // FIXME: CanWait
+                   Bcb,
+                   Buffer))
     {
-    case FileFsLabelInformation:
-      Status = FsdSetFsLabelInformation(IrpContext->DeviceObject,
-                                       SystemBuffer);
-      break;
-
-    default:
-      Status = STATUS_NOT_SUPPORTED;
+        ASSERT(FALSE);
     }
-
-  ExReleaseResourceLite(&((PDEVICE_EXTENSION)IrpContext->DeviceObject->DeviceExtension)->DirResource);
-  IrpContext->Irp->IoStatus.Status = Status;
-  IrpContext->Irp->IoStatus.Information = 0;
-  IoCompleteRequest(IrpContext->Irp, IO_NO_INCREMENT);
-  VfatFreeIrpContext(IrpContext);
-
-  return(Status);
 }
 
 /* EOF */