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 
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             /* It was a clean volume mounted */
77             if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
78             {
79                 /* So, drop the dirty bit we set */
80                 if (NT_SUCCESS(SetDirtyStatus(DeviceExt, FALSE)))
81                     DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
82             }
83 
84             Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
85             if (NT_SUCCESS(Status))
86             {
87                 Status = VfatDiskShutDown(DeviceExt);
88                 if (!NT_SUCCESS(Status))
89                 {
90                     DPRINT1("VfatDiskShutDown failed, status = %x\n", Status);
91                 }
92             }
93             else
94             {
95                 DPRINT1("VfatFlushVolume failed, status = %x\n", Status);
96             }
97             ExReleaseResourceLite(&DeviceExt->DirResource);
98 
99             /* FIXME: Unmount the logical volume */
100 
101             if (!NT_SUCCESS(Status))
102                 Irp->IoStatus.Status = Status;
103         }
104         ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
105 
106         /* FIXME: Free all global acquired resources */
107 
108         Status = Irp->IoStatus.Status;
109     }
110     else
111     {
112         Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
113         Status = STATUS_INVALID_DEVICE_REQUEST;
114     }
115 
116     Irp->IoStatus.Information = 0;
117     IoCompleteRequest(Irp, IO_NO_INCREMENT);
118 
119     FsRtlExitFileSystem();
120 
121     return Status;
122 }
123 
124 /* EOF */
125