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