X-Git-Url: http://git.jankratochvil.net/?p=reactos.git;a=blobdiff_plain;f=drivers%2Ffs%2Fvfat%2Ffsctl.c;h=67409a9d3363f92de014c9529bfbbdcebe64c208;hp=b66a377c9d17924c1661b6524290bde9e6e9f8b3;hb=HEAD;hpb=7c0db166f81fbe8c8b913d7f26048e337d383605 diff --git a/drivers/fs/vfat/fsctl.c b/drivers/fs/vfat/fsctl.c index b66a377..67409a9 100644 --- a/drivers/fs/vfat/fsctl.c +++ b/drivers/fs/vfat/fsctl.c @@ -29,6 +29,8 @@ #include #include +#include + #define NDEBUG #include @@ -185,13 +187,13 @@ VfatMountDevice(PDEVICE_EXTENSION DeviceExt, (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); @@ -211,7 +213,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) PVFATFCB Fcb = NULL; PVFATFCB VolumeFcb = NULL; PVFATCCB Ccb = NULL; - LARGE_INTEGER timeout; + PDEVICE_OBJECT DeviceToMount; DPRINT("VfatMount(IrpContext %x)\n", IrpContext); @@ -223,7 +225,9 @@ VfatMount (PVFAT_IRP_CONTEXT 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; @@ -254,8 +258,8 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) 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 */ @@ -275,7 +279,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) } #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; @@ -303,7 +307,7 @@ VfatMount (PVFAT_IRP_CONTEXT IrpContext) 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; @@ -382,16 +386,165 @@ ByeBye: 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) /* @@ -404,12 +557,31 @@ 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: @@ -427,7 +599,6 @@ NTSTATUS VfatFileSystemControl(PVFAT_IRP_CONTEXT IrpContext) } IrpContext->Irp->IoStatus.Status = Status; - IrpContext->Irp->IoStatus.Information = 0; IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); VfatFreeIrpContext(IrpContext);