#include <ddk/ntddk.h>
#include <wchar.h>
+#include <ntos.h>
+
#define NDEBUG
#include <debug.h>
(DeviceExt->FatInfo.BytesPerCluster % PAGE_SIZE) != 0)
{
DbgPrint("(%s:%d) Invalid cluster size\n", __FILE__, __LINE__);
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
else if (DeviceExt->FatInfo.BytesPerCluster < PAGE_SIZE &&
(PAGE_SIZE % DeviceExt->FatInfo.BytesPerCluster) != 0)
{
DbgPrint("(%s:%d) Invalid cluster size2\n", __FILE__, __LINE__);
- KeBugCheck(0);
+ KEBUGCHECK(0);
}
return(STATUS_SUCCESS);
PVFATFCB Fcb = NULL;
PVFATFCB VolumeFcb = NULL;
PVFATCCB Ccb = NULL;
- LARGE_INTEGER timeout;
+ PDEVICE_OBJECT DeviceToMount;
DPRINT("VfatMount(IrpContext %x)\n", IrpContext);
goto ByeBye;
}
- Status = VfatHasFileSystem (IrpContext->Stack->Parameters.MountVolume.DeviceObject, &RecognizedFS, NULL);
+ DeviceToMount = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
+
+ Status = VfatHasFileSystem (DeviceToMount, &RecognizedFS, NULL);
if (!NT_SUCCESS(Status))
{
goto ByeBye;
RtlZeroMemory(DeviceExt, sizeof(DEVICE_EXTENSION));
/* use same vpb as device disk */
- DeviceObject->Vpb = IrpContext->Stack->Parameters.MountVolume.DeviceObject->Vpb;
- Status = VfatMountDevice(DeviceExt, IrpContext->Stack->Parameters.MountVolume.DeviceObject);
+ DeviceObject->Vpb = DeviceToMount->Vpb;
+ Status = VfatMountDevice(DeviceExt, DeviceToMount);
if (!NT_SUCCESS(Status))
{
/* FIXME: delete device object */
}
#endif
- DeviceExt->StorageDevice = IrpContext->Stack->Parameters.MountVolume.DeviceObject;
+ DeviceExt->StorageDevice = DeviceToMount;
DeviceExt->StorageDevice->Vpb->DeviceObject = DeviceObject;
DeviceExt->StorageDevice->Vpb->RealDevice = DeviceExt->StorageDevice;
DeviceExt->StorageDevice->Vpb->Flags |= VPB_MOUNTED;
DeviceExt->FATFileObject->Flags = DeviceExt->FATFileObject->Flags | FO_FCB_IS_VALID | FO_DIRECT_CACHE_PAGING_READ;
DeviceExt->FATFileObject->FsContext = Fcb;
DeviceExt->FATFileObject->FsContext2 = Ccb;
- DeviceExt->FATFileObject->SectionObjectPointers = &Fcb->SectionObjectPointers;
+ DeviceExt->FATFileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
DeviceExt->FATFileObject->PrivateCacheMap = NULL;
DeviceExt->FATFileObject->Vpb = DeviceObject->Vpb;
Fcb->FileObject = DeviceExt->FATFileObject;
static NTSTATUS
VfatVerify (PVFAT_IRP_CONTEXT IrpContext)
/*
- * FUNCTION: Mount the filesystem
+ * FUNCTION: Verify the filesystem
*/
{
+ PDEVICE_OBJECT DeviceToVerify;
+ NTSTATUS Status;
+
DPRINT("VfatVerify(IrpContext %x)\n", IrpContext);
- assert(IrpContext);
+ DeviceToVerify = IrpContext->Stack->Parameters.VerifyVolume.DeviceObject;
+ Status = VfatBlockDeviceIoControl(DeviceToVerify,
+ IOCTL_DISK_CHECK_VERIFY,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status))
+ {
+ DPRINT1("VfatBlockDeviceIoControl() failed (Status %lx)\n", Status);
+
+ /* FIXME: Compare volume label */
+
+ DPRINT1(" returning STATUS_WRONG_VOLUME\n");
+
+ return STATUS_WRONG_VOLUME;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+
+static NTSTATUS
+VfatGetVolumeBitmap(PVFAT_IRP_CONTEXT IrpContext)
+{
+ DPRINT("VfatGetVolumeBitmap (IrpContext %x)\n", IrpContext);
+
+ return STATUS_INVALID_DEVICE_REQUEST;
+}
+
+
+static NTSTATUS
+VfatGetRetrievalPointers(PVFAT_IRP_CONTEXT IrpContext)
+{
+ PIO_STACK_LOCATION Stack;
+ LARGE_INTEGER Vcn;
+ PGET_RETRIEVAL_DESCRIPTOR RetrievalPointers;
+ PFILE_OBJECT FileObject;
+ ULONG MaxExtentCount;
+ PVFATFCB Fcb;
+ PDEVICE_EXTENSION DeviceExt;
+ ULONG FirstCluster;
+ ULONG CurrentCluster;
+ ULONG LastCluster;
+ NTSTATUS Status;
+
+ DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext);
+
+ DeviceExt = IrpContext->DeviceExt;
+ FileObject = IrpContext->FileObject;
+ Stack = IrpContext->Stack;
+ if (Stack->Parameters.DeviceIoControl.InputBufferLength < sizeof(LARGE_INTEGER) ||
+ Stack->Parameters.DeviceIoControl.Type3InputBuffer == NULL)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ if (IrpContext->Irp->UserBuffer == NULL ||
+ Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR))
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+
+ Fcb = FileObject->FsContext;
+
+ ExAcquireResourceSharedLite(&Fcb->MainResource, TRUE);
+
+ Vcn = *(PLARGE_INTEGER)Stack->Parameters.DeviceIoControl.Type3InputBuffer;
+ RetrievalPointers = IrpContext->Irp->UserBuffer;
+
+ MaxExtentCount = ((Stack->Parameters.DeviceIoControl.OutputBufferLength - sizeof(GET_RETRIEVAL_DESCRIPTOR)) / sizeof(MAPPING_PAIR));
+
+
+ if (Vcn.QuadPart >= Fcb->RFCB.AllocationSize.QuadPart / DeviceExt->FatInfo.BytesPerCluster)
+ {
+ Status = STATUS_INVALID_PARAMETER;
+ goto ByeBye;
+ }
+
+ CurrentCluster = FirstCluster = vfatDirEntryGetFirstCluster(DeviceExt, &Fcb->entry);
+ Status = OffsetToCluster(DeviceExt, FirstCluster,
+ Vcn.u.LowPart * DeviceExt->FatInfo.BytesPerCluster,
+ &CurrentCluster, FALSE);
+ if (!NT_SUCCESS(Status))
+ {
+ goto ByeBye;
+ }
+
+ RetrievalPointers->StartVcn = Vcn.QuadPart;
+ RetrievalPointers->NumberOfPairs = 0;
+ RetrievalPointers->Pair[0].Lcn = CurrentCluster - 2;
+ LastCluster = 0;
+ while (CurrentCluster != 0xffffffff && RetrievalPointers->NumberOfPairs < MaxExtentCount)
+ {
+
+ LastCluster = CurrentCluster;
+ Status = NextCluster(DeviceExt, CurrentCluster, &CurrentCluster, FALSE);
+ Vcn.QuadPart++;
+ if (!NT_SUCCESS(Status))
+ {
+ goto ByeBye;
+ }
+
+ if (LastCluster + 1 != CurrentCluster)
+ {
+ RetrievalPointers->Pair[RetrievalPointers->NumberOfPairs].Vcn = Vcn.QuadPart;
+ RetrievalPointers->NumberOfPairs++;
+ if (RetrievalPointers->NumberOfPairs < MaxExtentCount)
+ {
+ RetrievalPointers->Pair[RetrievalPointers->NumberOfPairs].Lcn = CurrentCluster - 2;
+ }
+ }
+ }
+
+ IrpContext->Irp->IoStatus.Information = sizeof(GET_RETRIEVAL_DESCRIPTOR) + sizeof(MAPPING_PAIR) * RetrievalPointers->NumberOfPairs;
+ Status = STATUS_SUCCESS;
+
+ByeBye:
+ ExReleaseResourceLite(&Fcb->MainResource);
+
+ return Status;
+}
- return(STATUS_INVALID_DEVICE_REQUEST);
+static NTSTATUS
+VfatMoveFile(PVFAT_IRP_CONTEXT IrpContext)
+{
+ DPRINT("VfatMoveFile(IrpContext %x)\n", IrpContext);
+
+ return STATUS_INVALID_DEVICE_REQUEST;
}
+static NTSTATUS
+VfatRosQueryLcnMapping(PVFAT_IRP_CONTEXT IrpContext)
+{
+ PDEVICE_EXTENSION DeviceExt;
+ PROS_QUERY_LCN_MAPPING LcnQuery;
+ PIO_STACK_LOCATION Stack;
+
+ DPRINT("VfatGetRetrievalPointers(IrpContext %x)\n", IrpContext);
+
+ DeviceExt = IrpContext->DeviceExt;
+ Stack = IrpContext->Stack;
+ if (IrpContext->Irp->AssociatedIrp.SystemBuffer == NULL ||
+ Stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ROS_QUERY_LCN_MAPPING))
+ {
+ return STATUS_BUFFER_TOO_SMALL;
+ }
+ LcnQuery = (PROS_QUERY_LCN_MAPPING)(IrpContext->Irp->AssociatedIrp.SystemBuffer);
+ LcnQuery->LcnDiskOffset.QuadPart = DeviceExt->FatInfo.dataStart * DeviceExt->FatInfo.BytesPerSector;
+ IrpContext->Irp->IoStatus.Information = sizeof(ROS_QUERY_LCN_MAPPING);
+ return(STATUS_SUCCESS);
+}
NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext)
/*
DPRINT("VfatFileSystemControl(IrpContext %x)\n", IrpContext);
assert (IrpContext);
+ assert (IrpContext->Irp);
+ assert (IrpContext->Stack);
+
+ IrpContext->Irp->IoStatus.Information = 0;
switch (IrpContext->MinorFunction)
{
case IRP_MN_USER_FS_REQUEST:
- DPRINT("VFAT FSC: IRP_MN_USER_FS_REQUEST\n");
- Status = STATUS_INVALID_DEVICE_REQUEST;
+ switch(IrpContext->Stack->Parameters.DeviceIoControl.IoControlCode)
+ {
+ case FSCTL_GET_VOLUME_BITMAP:
+ Status = VfatGetVolumeBitmap(IrpContext);
+ break;
+ case FSCTL_GET_RETRIEVAL_POINTERS:
+ Status = VfatGetRetrievalPointers(IrpContext);
+ break;
+ case FSCTL_MOVE_FILE:
+ Status = VfatMoveFile(IrpContext);
+ break;
+ case FSCTL_ROS_QUERY_LCN_MAPPING:
+ Status = VfatRosQueryLcnMapping(IrpContext);
+ break;
+ default:
+ Status = STATUS_INVALID_DEVICE_REQUEST;
+ }
break;
case IRP_MN_MOUNT_VOLUME:
}
IrpContext->Irp->IoStatus.Status = Status;
- IrpContext->Irp->IoStatus.Information = 0;
IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT);
VfatFreeIrpContext(IrpContext);