+ 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;
+}