NTSTATUS VfatFlush( PVFAT_IRP_CONTEXT IrpContext) { NTSTATUS Status; PVFATFCB Fcb; /* This request is not allowed on the main device object. */ if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) { IrpContext->Irp->IoStatus.Information = 0; return STATUS_INVALID_DEVICE_REQUEST; } Fcb = (PVFATFCB)IrpContext->FileObject->FsContext; ASSERT(Fcb); if (BooleanFlagOn(Fcb->Flags, FCB_IS_VOLUME)) { ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE); Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb); ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); } else { ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); Status = VfatFlushFile(IrpContext->DeviceExt, Fcb); ExReleaseResourceLite (&Fcb->MainResource); } IrpContext->Irp->IoStatus.Information = 0; return Status; }
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; }
NTSTATUS VfatFlush( PVFAT_IRP_CONTEXT IrpContext) { NTSTATUS Status; PVFATFCB Fcb; /* This request is not allowed on the main device object. */ if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) { Status = STATUS_INVALID_DEVICE_REQUEST; goto ByeBye; } Fcb = (PVFATFCB)IrpContext->FileObject->FsContext; ASSERT(Fcb); if (Fcb->Flags & FCB_IS_VOLUME) { ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, TRUE); Status = VfatFlushVolume(IrpContext->DeviceExt, Fcb); ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); } else { ExAcquireResourceExclusiveLite(&Fcb->MainResource, TRUE); Status = VfatFlushFile(IrpContext->DeviceExt, Fcb); ExReleaseResourceLite (&Fcb->MainResource); } ByeBye: IrpContext->Irp->IoStatus.Status = Status; IrpContext->Irp->IoStatus.Information = 0; IoCompleteRequest (IrpContext->Irp, IO_NO_INCREMENT); VfatFreeIrpContext(IrpContext); return Status; }
NTSTATUS NTAPI VfatShutdown(PDEVICE_OBJECT DeviceObject, PIRP Irp) { NTSTATUS Status; PLIST_ENTRY ListEntry; PDEVICE_EXTENSION DeviceExt; ULONG eocMark; DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp); FsRtlEnterFileSystem(); /* FIXME: block new mount requests */ if (DeviceObject == VfatGlobalData->DeviceObject) { Irp->IoStatus.Status = STATUS_SUCCESS; ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE); ListEntry = VfatGlobalData->VolumeListHead.Flink; while (ListEntry != &VfatGlobalData->VolumeListHead) { DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry); ListEntry = ListEntry->Flink; ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE); if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY) { /* set clean shutdown bit */ Status = GetNextCluster(DeviceExt, 1, &eocMark); if (NT_SUCCESS(Status)) { eocMark |= DeviceExt->CleanShutBitMask; if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark))) DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY; } } Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb); if (NT_SUCCESS(Status)) { Status = VfatDiskShutDown(DeviceExt); if (!NT_SUCCESS(Status)) DPRINT1("VfatDiskShutDown failed, status = %x\n", Status); } else { DPRINT1("VfatFlushVolume failed, status = %x\n", Status); } ExReleaseResourceLite(&DeviceExt->DirResource); /* FIXME: Unmount the logical volume */ if (!NT_SUCCESS(Status)) Irp->IoStatus.Status = Status; } ExReleaseResourceLite(&VfatGlobalData->VolumeListLock); /* FIXME: Free all global acquired resources */ Status = Irp->IoStatus.Status; } else { Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; Status = STATUS_INVALID_DEVICE_REQUEST; } Irp->IoStatus.Information = 0; IoCompleteRequest(Irp, IO_NO_INCREMENT); FsRtlExitFileSystem(); return(Status); }