1 /* 2 * PROJECT: VFAT Filesystem 3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) 4 * PURPOSE: Shutdown handlers 5 * COPYRIGHT: Copyright 2000-2013 Eric Kohl <eric.kohl@reactos.org> 6 */ 7 8 /* INCLUDES *****************************************************************/ 9 10 #include "vfat.h" 11 12 #define NDEBUG 13 #include <debug.h> 14 15 /* FUNCTIONS ****************************************************************/ 16 17 static 18 NTSTATUS 19 VfatDiskShutDown( 20 PVCB Vcb) 21 { 22 PIRP Irp; 23 KEVENT Event; 24 NTSTATUS Status; 25 IO_STATUS_BLOCK IoStatus; 26 27 KeInitializeEvent(&Event, NotificationEvent, FALSE); 28 Irp = IoBuildSynchronousFsdRequest(IRP_MJ_SHUTDOWN, Vcb->StorageDevice, 29 NULL, 0, NULL, &Event, &IoStatus); 30 if (Irp) 31 { 32 Status = IoCallDriver(Vcb->StorageDevice, Irp); 33 if (Status == STATUS_PENDING) 34 { 35 KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); 36 Status = IoStatus.Status; 37 } 38 } 39 else 40 { 41 Status = STATUS_INSUFFICIENT_RESOURCES; 42 } 43 44 return Status; 45 } 46 47 48 NTSTATUS 49 NTAPI 50 VfatShutdown( 51 PDEVICE_OBJECT DeviceObject, 52 PIRP Irp) 53 { 54 NTSTATUS Status; 55 PLIST_ENTRY ListEntry; 56 PDEVICE_EXTENSION DeviceExt; 57 58 DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp); 59 60 FsRtlEnterFileSystem(); 61 62 /* FIXME: block new mount requests */ 63 VfatGlobalData->ShutdownStarted = TRUE; 64 65 if (DeviceObject == VfatGlobalData->DeviceObject) 66 { 67 Irp->IoStatus.Status = STATUS_SUCCESS; 68 ExAcquireResourceExclusiveLite(&VfatGlobalData->VolumeListLock, TRUE); 69 ListEntry = VfatGlobalData->VolumeListHead.Flink; 70 while (ListEntry != &VfatGlobalData->VolumeListHead) 71 { 72 DeviceExt = CONTAINING_RECORD(ListEntry, VCB, VolumeListEntry); 73 ListEntry = ListEntry->Flink; 74 75 ExAcquireResourceExclusiveLite(&DeviceExt->DirResource, TRUE); 76 77 /* Flush volume & files */ 78 Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb); 79 80 /* We're performing a clean shutdown */ 81 if (BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_CLEAR_DIRTY) && 82 BooleanFlagOn(DeviceExt->VolumeFcb->Flags, VCB_IS_DIRTY)) 83 { 84 /* Drop the dirty bit */ 85 if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE))) 86 DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY; 87 } 88 89 if (NT_SUCCESS(Status)) 90 { 91 Status = VfatDiskShutDown(DeviceExt); 92 if (!NT_SUCCESS(Status)) 93 { 94 DPRINT1("VfatDiskShutDown failed, status = %x\n", Status); 95 } 96 } 97 else 98 { 99 DPRINT1("VfatFlushVolume failed, status = %x\n", Status); 100 } 101 ExReleaseResourceLite(&DeviceExt->DirResource); 102 103 /* Unmount the logical volume */ 104 #ifdef ENABLE_SWAPOUT 105 VfatCheckForDismount(DeviceExt, FALSE); 106 #endif 107 108 if (!NT_SUCCESS(Status)) 109 Irp->IoStatus.Status = Status; 110 } 111 ExReleaseResourceLite(&VfatGlobalData->VolumeListLock); 112 113 /* FIXME: Free all global acquired resources */ 114 115 Status = Irp->IoStatus.Status; 116 } 117 else 118 { 119 Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST; 120 Status = STATUS_INVALID_DEVICE_REQUEST; 121 } 122 123 Irp->IoStatus.Information = 0; 124 IoCompleteRequest(Irp, IO_NO_INCREMENT); 125 126 FsRtlExitFileSystem(); 127 128 return Status; 129 } 130 131 /* EOF */ 132