return Status;
}
- PartitionInfoIsValid = TRUE;
DPRINT("Partition Information:\n");
DPRINT("StartingOffset %I64x\n", PartitionInfo.StartingOffset.QuadPart / 512);
DPRINT("PartitionLength %I64x\n", PartitionInfo.PartitionLength.QuadPart / 512);
PartitionInfo.PartitionType == PARTITION_FAT32_XINT13 ||
PartitionInfo.PartitionType == PARTITION_XINT13)
{
+ PartitionInfoIsValid = TRUE;
*RecognizedFS = TRUE;
}
}
PartitionInfo.PartitionLength.QuadPart > 0)
{
/* This is possible a removable media formated as super floppy */
+ PartitionInfoIsValid = TRUE;
*RecognizedFS = TRUE;
}
}
goto ByeBye;
}
- DeviceObject->Flags = DeviceObject->Flags | DO_DIRECT_IO;
- DeviceExt = (PVOID) DeviceObject->DeviceExtension;
+ DeviceExt = DeviceObject->DeviceExtension;
RtlZeroMemory(DeviceExt, ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)) + sizeof(HASHENTRY*) * HashTableSize);
DeviceExt->FcbHashTable = (HASHENTRY**)((ULONG_PTR)DeviceExt + ROUND_UP(sizeof(DEVICE_EXTENSION), sizeof(ULONG)));
DeviceExt->HashTableSize = HashTableSize;
+ DeviceExt->VolumeDevice = DeviceObject;
/* use same vpb as device disk */
DeviceObject->Vpb = Vpb;
/* Initialize this resource early ... it's used in VfatCleanup */
ExInitializeResourceLite(&DeviceExt->DirResource);
+ DeviceExt->IoVPB = DeviceObject->Vpb;
+ DeviceExt->SpareVPB = ExAllocatePoolWithTag(NonPagedPool, sizeof(VPB), TAG_VFAT);
+ if (DeviceExt->SpareVPB == NULL)
+ {
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ goto ByeBye;
+ }
+
DeviceExt->FATFileObject = IoCreateStreamFileObject(NULL, DeviceExt->StorageDevice);
Fcb = vfatNewFCB(DeviceExt, &NameU);
if (Fcb == NULL)
Fcb->RFCB.ValidDataLength = Fcb->RFCB.FileSize;
Fcb->RFCB.AllocationSize = Fcb->RFCB.FileSize;
- CcInitializeCacheMap(DeviceExt->FATFileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- TRUE,
- &VfatGlobalData->CacheMgrCallbacks,
- Fcb);
+ _SEH2_TRY
+ {
+ CcInitializeCacheMap(DeviceExt->FATFileObject,
+ (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+ TRUE,
+ &VfatGlobalData->CacheMgrCallbacks,
+ Fcb);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ Status = _SEH2_GetExceptionCode();
+ goto ByeBye;
+ }
+ _SEH2_END;
DeviceExt->LastAvailableCluster = 2;
ExInitializeResourceLite(&DeviceExt->FatResource);
VolumeFcb->Flags |= VCB_IS_DIRTY;
FsRtlNotifyVolumeEvent(DeviceExt->FATFileObject, FSRTL_VOLUME_MOUNT);
+ FsRtlNotifyInitializeSync(&DeviceExt->NotifySync);
+ InitializeListHead(&DeviceExt->NotifyList);
+
+ DPRINT("Mount success\n");
Status = STATUS_SUCCESS;
/* Cleanup */
if (DeviceExt && DeviceExt->FATFileObject)
ObDereferenceObject (DeviceExt->FATFileObject);
+ if (DeviceExt && DeviceExt->SpareVPB)
+ ExFreePoolWithTag(DeviceExt->SpareVPB, TAG_VFAT);
if (Fcb)
vfatDestroyFCB(Fcb);
if (Ccb)
vfatDestroyCCB(Ccb);
if (DeviceObject)
IoDeleteDevice(DeviceObject);
- if (VolumeFcb)
- vfatDestroyFCB(VolumeFcb);
}
return Status;
return Status;
}
+static
+NTSTATUS
+VfatLockOrUnlockVolume(
+ PVFAT_IRP_CONTEXT IrpContext,
+ BOOLEAN Lock)
+{
+ PFILE_OBJECT FileObject;
+ PDEVICE_EXTENSION DeviceExt;
+ PVFATFCB Fcb;
+
+ DPRINT("VfatLockOrUnlockVolume(%p, %d)\n", IrpContext, Lock);
+
+ DeviceExt = IrpContext->DeviceExt;
+ FileObject = IrpContext->FileObject;
+ Fcb = FileObject->FsContext;
+
+ /* Only allow locking with the volume open */
+ if (!(Fcb->Flags & FCB_IS_VOLUME))
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Bail out if it's already in the demanded state */
+ if (((DeviceExt->Flags & VCB_VOLUME_LOCKED) && Lock) ||
+ (!(DeviceExt->Flags & VCB_VOLUME_LOCKED) && !Lock))
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Deny locking if we're not alone */
+ if (Lock && DeviceExt->OpenHandleCount != 1)
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Finally, proceed */
+ if (Lock)
+ {
+ DeviceExt->Flags |= VCB_VOLUME_LOCKED;
+ }
+ else
+ {
+ DeviceExt->Flags &= ~VCB_VOLUME_LOCKED;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static
+NTSTATUS
+VfatDismountVolume(
+ PVFAT_IRP_CONTEXT IrpContext)
+{
+ PDEVICE_EXTENSION DeviceExt;
+ PLIST_ENTRY NextEntry;
+ PVFATFCB Fcb;
+ PFILE_OBJECT FileObject;
+
+ DPRINT("VfatDismountVolume(%p)\n", IrpContext);
+
+ DeviceExt = IrpContext->DeviceExt;
+ FileObject = IrpContext->FileObject;
+
+ /* We HAVE to be locked. Windows also allows dismount with no lock
+ * but we're here mainly for 1st stage, so KISS
+ */
+ if (!(DeviceExt->Flags & VCB_VOLUME_LOCKED))
+ {
+ return STATUS_ACCESS_DENIED;
+ }
+
+ /* Race condition? */
+ if (DeviceExt->Flags & VCB_DISMOUNT_PENDING)
+ {
+ return STATUS_VOLUME_DISMOUNTED;
+ }
+
+ /* Notify we'll dismount. Pass that point there's no reason we fail */
+ FsRtlNotifyVolumeEvent(IrpContext->Stack->FileObject, FSRTL_VOLUME_DISMOUNT);
+
+ ExAcquireResourceExclusiveLite(&DeviceExt->FatResource, TRUE);
+
+ /* Flush volume & files */
+ VfatFlushVolume(DeviceExt, (PVFATFCB)FileObject->FsContext);
+
+ /* Rebrowse the FCB in order to free them now */
+ while (!IsListEmpty(&DeviceExt->FcbListHead))
+ {
+ NextEntry = RemoveHeadList(&DeviceExt->FcbListHead);
+ Fcb = CONTAINING_RECORD(NextEntry, VFATFCB, FcbListEntry);
+ vfatDestroyFCB(Fcb);
+ }
+
+ /* Mark we're being dismounted */
+ DeviceExt->Flags |= VCB_DISMOUNT_PENDING;
+
+ ExReleaseResourceLite(&DeviceExt->FatResource);
+
+ /* Release a few resources and quit, we're done */
+ ExDeleteResourceLite(&DeviceExt->DirResource);
+ ExDeleteResourceLite(&DeviceExt->FatResource);
+ ObDereferenceObject(DeviceExt->FATFileObject);
+
+ return STATUS_SUCCESS;
+}
+
/*
* FUNCTION: File system control
*/
Status = VfatMarkVolumeDirty(IrpContext);
break;
+ case FSCTL_LOCK_VOLUME:
+ Status = VfatLockOrUnlockVolume(IrpContext, TRUE);
+ break;
+
+ case FSCTL_UNLOCK_VOLUME:
+ Status = VfatLockOrUnlockVolume(IrpContext, FALSE);
+ break;
+
+ case FSCTL_DISMOUNT_VOLUME:
+ Status = VfatDismountVolume(IrpContext);
+ break;
+
default:
Status = STATUS_INVALID_DEVICE_REQUEST;
}