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
VfatDiskShutDown(PVCB Vcb)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
VfatShutdown(PDEVICE_OBJECT DeviceObject,PIRP Irp)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