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     ULONG eocMark;
59 
60     DPRINT("VfatShutdown(DeviceObject %p, Irp %p)\n",DeviceObject, Irp);
61 
62     FsRtlEnterFileSystem();
63 
64     /* FIXME: block new mount requests */
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             if (DeviceExt->VolumeFcb->Flags & VCB_CLEAR_DIRTY)
78             {
79                 /* set clean shutdown bit */
80                 Status = GetNextCluster(DeviceExt, 1, &eocMark);
81                 if (NT_SUCCESS(Status))
82                 {
83                     eocMark |= DeviceExt->CleanShutBitMask;
84                     if (NT_SUCCESS(WriteCluster(DeviceExt, 1, eocMark)))
85                         DeviceExt->VolumeFcb->Flags &= ~VCB_IS_DIRTY;
86                 }
87             }
88 
89             Status = VfatFlushVolume(DeviceExt, DeviceExt->VolumeFcb);
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             /* FIXME: Unmount the logical volume */
105 
106             if (!NT_SUCCESS(Status))
107                 Irp->IoStatus.Status = Status;
108         }
109         ExReleaseResourceLite(&VfatGlobalData->VolumeListLock);
110 
111         /* FIXME: Free all global acquired resources */
112 
113         Status = Irp->IoStatus.Status;
114     }
115     else
116     {
117         Irp->IoStatus.Status = STATUS_INVALID_DEVICE_REQUEST;
118         Status = STATUS_INVALID_DEVICE_REQUEST;
119     }
120 
121     Irp->IoStatus.Information = 0;
122     IoCompleteRequest(Irp, IO_NO_INCREMENT);
123 
124     FsRtlExitFileSystem();
125 
126     return Status;
127 }
128 
129 /* EOF */
130