/*
- * 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 */