{
NTSTATUS Status;
DISK_GEOMETRY DiskGeometry;
+ ULONG MediaChangeCount = 0;
PVOLUME_DEVICE_OBJECT VolumeDevice;
+ VCB *Vcb;
+ FF_ERROR Error;
DPRINT1("FatMountVolume()\n");
/* Make sure this IRP is waitable */
ASSERT(IrpContext->Flags & IRPCONTEXT_CANWAIT);
- /* TODO: IOCTL_DISK_CHECK_VERIFY */
+ /* Request media changes count, mostly usefull for removable devices */
+ Status = FatPerformDevIoCtrl(TargetDeviceObject,
+ IOCTL_STORAGE_CHECK_VERIFY,
+ NULL,
+ 0,
+ &MediaChangeCount,
+ sizeof(ULONG),
+ TRUE);
+
+ if (!NT_SUCCESS(Status)) return Status;
+
/* TODO: Check if data-track present in case of a CD drive */
/* TODO: IOCTL_DISK_GET_PARTITION_INFO_EX */
/* Remove unmounted VCBs */
FatiCleanVcbs(IrpContext);
+ /* Acquire the global exclusive lock */
+ FatAcquireExclusiveGlobal(IrpContext);
+
/* Create a new volume device object */
Status = IoCreateDevice(FatGlobalData.DriverObject,
sizeof(VOLUME_DEVICE_OBJECT) - sizeof(DEVICE_OBJECT),
FALSE,
(PDEVICE_OBJECT *)&VolumeDevice);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status))
+ {
+ /* Release the global lock */
+ FatReleaseGlobal(IrpContext);
+
+ return Status;
+ }
/* Match alignment requirements */
if (TargetDeviceObject->AlignmentRequirement > VolumeDevice->DeviceObject.AlignmentRequirement)
sizeof(DISK_GEOMETRY),
TRUE);
- if (!NT_SUCCESS(Status)) return Status;
+ if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
- VolumeDevice->DeviceObject.SectorSize = DiskGeometry.BytesPerSector;
+ VolumeDevice->DeviceObject.SectorSize = (USHORT) DiskGeometry.BytesPerSector;
/* Signal we're done with initializing */
VolumeDevice->DeviceObject.Flags &= ~DO_DEVICE_INITIALIZING;
Vpb->DeviceObject = (PDEVICE_OBJECT)VolumeDevice;
/* Initialize VCB for this volume */
- Status = FatInitializeVcb(&VolumeDevice->Vcb, TargetDeviceObject, Vpb);
- if (!NT_SUCCESS(Status))
+ Status = FatInitializeVcb(IrpContext, &VolumeDevice->Vcb, TargetDeviceObject, Vpb);
+ if (!NT_SUCCESS(Status)) goto FatMountVolumeCleanup;
+
+ Vcb = &VolumeDevice->Vcb;
+
+ /* Initialize FullFAT library */
+ Vcb->Ioman = FF_CreateIOMAN(NULL,
+ 8192,
+ VolumeDevice->DeviceObject.SectorSize,
+ &Error);
+
+ ASSERT(Vcb->Ioman);
+
+ /* Register block device read/write functions */
+ Error = FF_RegisterBlkDevice(Vcb->Ioman,
+ VolumeDevice->DeviceObject.SectorSize,
+ (FF_WRITE_BLOCKS)FatWriteBlocks,
+ (FF_READ_BLOCKS)FatReadBlocks,
+ Vcb);
+
+ if (Error)
+ {
+ DPRINT1("Registering block device with FullFAT failed with error %d\n", Error);
+ FF_DestroyIOMAN(Vcb->Ioman);
goto FatMountVolumeCleanup;
+ }
+
+ /* Mount the volume using FullFAT */
+ if(FF_MountPartition(Vcb->Ioman, 0))
+ {
+ DPRINT1("Partition mounting failed\n");
+ FF_DestroyIOMAN(Vcb->Ioman);
+ goto FatMountVolumeCleanup;
+ }
+
+ // TODO: Read BPB and store it in Vcb->Bpb
+
+ /* Create root DCB for it */
+ FatCreateRootDcb(IrpContext, &VolumeDevice->Vcb);
+
+ /* Keep trace of media changes */
+ VolumeDevice->Vcb.MediaChangeCount = MediaChangeCount;
+
+ //ObDereferenceObject(TargetDeviceObject);
+
+ /* Release the global lock */
+ FatReleaseGlobal(IrpContext);
+
+ /* Notify about volume mount */
+ //FsRtlNotifyVolumeEvent(VolumeDevice->Vcb.StreamFileObject, FSRTL_VOLUME_MOUNT);
/* Return success */
return STATUS_SUCCESS;
/* Unwind the routine actions */
IoDeleteDevice((PDEVICE_OBJECT)VolumeDevice);
+
+ /* Release the global lock */
+ FatReleaseGlobal(IrpContext);
+
return Status;
}