1 /*
2  * COPYRIGHT:        See COPYRIGHT.TXT
3  * PROJECT:          Ext2 File System Driver for WinNT/2K/XP
4  * FILE:             shutdown.c
5  * PROGRAMMER:       Matt Wu <mattwu@163.com>
6  * HOMEPAGE:         http://www.ext2fsd.com
7  * UPDATE HISTORY:
8  */
9 
10 /* INCLUDES *****************************************************************/
11 
12 #include "ext2fs.h"
13 
14 /* GLOBALS ***************************************************************/
15 
16 extern PEXT2_GLOBAL Ext2Global;
17 
18 /* DEFINITIONS *************************************************************/
19 
20 #ifdef ALLOC_PRAGMA
21 #pragma alloc_text(PAGE, Ext2ShutDown)
22 #endif
23 
24 NTSTATUS
Ext2ShutDown(IN PEXT2_IRP_CONTEXT IrpContext)25 Ext2ShutDown (IN PEXT2_IRP_CONTEXT IrpContext)
26 {
27     NTSTATUS                Status;
28 
29     PIRP                    Irp;
30 
31     PEXT2_VCB               Vcb;
32     PLIST_ENTRY             ListEntry;
33 
34     BOOLEAN                 GlobalResourceAcquired = FALSE;
35 
36     _SEH2_TRY {
37 
38         Status = STATUS_SUCCESS;
39 
40         ASSERT(IrpContext);
41         ASSERT((IrpContext->Identifier.Type == EXT2ICX) &&
42                (IrpContext->Identifier.Size == sizeof(EXT2_IRP_CONTEXT)));
43 
44         Irp = IrpContext->Irp;
45 
46         if (!ExAcquireResourceExclusiveLite(
47                     &Ext2Global->Resource,
48                     IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) )) {
49             Status = STATUS_PENDING;
50             _SEH2_LEAVE;
51         }
52 
53         GlobalResourceAcquired = TRUE;
54 
55         for (ListEntry = Ext2Global->VcbList.Flink;
56                 ListEntry != &(Ext2Global->VcbList);
57                 ListEntry = ListEntry->Flink ) {
58 
59             Vcb = CONTAINING_RECORD(ListEntry, EXT2_VCB, Next);
60 
61             if (ExAcquireResourceExclusiveLite(
62                         &Vcb->MainResource,
63                         TRUE )) {
64 
65                 if (IsMounted(Vcb)) {
66 
67                     /* update mount count */
68                     Vcb->SuperBlock->s_mnt_count++;
69                     if (Vcb->SuperBlock->s_mnt_count >
70                             Vcb->SuperBlock->s_max_mnt_count ) {
71                         Vcb->SuperBlock->s_mnt_count =
72                             Vcb->SuperBlock->s_max_mnt_count;
73                     }
74                     Ext2SaveSuper(IrpContext, Vcb);
75 
76                     /* flush dirty cache for all files */
77                     Status = Ext2FlushFiles(IrpContext, Vcb, TRUE);
78                     if (!NT_SUCCESS(Status)) {
79                         DbgBreak();
80                     }
81 
82                     /* flush volume stream's cache to disk */
83                     Status = Ext2FlushVolume(IrpContext, Vcb, TRUE);
84 
85                     if (!NT_SUCCESS(Status) && Status != STATUS_MEDIA_WRITE_PROTECTED) {
86                         DbgBreak();
87                     }
88 
89                     /* send shutdown request to underlying disk */
90                     Ext2DiskShutDown(Vcb);
91                 }
92 
93                 ExReleaseResourceLite(&Vcb->MainResource);
94             }
95         }
96 
97         /*
98                 IoUnregisterFileSystem(Ext2Global->DiskdevObject);
99                 IoUnregisterFileSystem(Ext2Global->CdromdevObject);
100         */
101 
102     } _SEH2_FINALLY {
103 
104         if (GlobalResourceAcquired) {
105             ExReleaseResourceLite(&Ext2Global->Resource);
106         }
107 
108         if (!IrpContext->ExceptionInProgress) {
109             if (Status == STATUS_PENDING) {
110                 Ext2QueueRequest(IrpContext);
111             } else {
112                 Ext2CompleteIrpContext(IrpContext, Status);
113             }
114         }
115     } _SEH2_END;
116 
117     return Status;
118 }