xref: /reactos/drivers/filesystems/cdfs/shutdown.c (revision 02e84521)
1 /*++
2 
3 Copyright (c) 1997-2006 Microsoft Corporation
4 
5 Module Name:
6 
7     Shutdown.c
8 
9 Abstract:
10 
11     This module implements the shutdown routine for CDFS called by
12     the dispatch driver.
13 
14 
15 --*/
16 
17 #include "cdprocs.h"
18 
19 //
20 //  The Bug check file id for this module
21 //
22 
23 #define BugCheckFileId                   (CDFS_BUG_CHECK_SHUTDOWN)
24 
25 #ifdef ALLOC_PRAGMA
26 #pragma alloc_text(PAGE, CdCommonShutdown)
27 #endif
28 
29 _Requires_lock_held_(_Global_critical_region_)
30 NTSTATUS
31 CdCommonShutdown (
32     _Inout_ PIRP_CONTEXT IrpContext,
33     _Inout_ PIRP Irp
34     )
35 
36 /*++
37 
38 Routine Description:
39 
40     This is the common routine for handling shutdown operation called
41     by both the fsd and fsp threads
42 
43 Arguments:
44 
45     Irp - Supplies the Irp to process
46 
47 Return Value:
48 
49     NTSTATUS - The return status for the operation
50 
51 --*/
52 
53 {
54     KEVENT Event;
55     PLIST_ENTRY Links;
56     PVCB Vcb;
57     PIRP NewIrp;
58     IO_STATUS_BLOCK Iosb;
59     BOOLEAN VcbPresent;
60     NTSTATUS Status;
61 
62     PAGED_CODE();
63 
64     //
65     //  Make sure we don't get any pop-ups.
66     //
67 
68     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS );
69 
70     //
71     //  Initialize an event for doing calls down to
72     //  our target device objects.
73     //
74 
75     KeInitializeEvent( &Event, NotificationEvent, FALSE );
76 
77     //
78     //  Indicate that shutdown has started.
79     //
80 
81     SetFlag( CdData.Flags, CD_FLAGS_SHUTDOWN );
82 
83     //
84     //  Get everyone else out of the way
85     //
86 
87     CdAcquireCdData( IrpContext );
88 
89     //
90     //  Now walk through all the mounted Vcb's and shutdown the target
91     //  device objects.
92     //
93 
94     Links = CdData.VcbQueue.Flink;
95 
96     while (Links != &CdData.VcbQueue) {
97 
98         Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks );
99 
100         //
101         //  Move to the next link now since the current Vcb may be deleted.
102         //
103 
104         Links = Links->Flink;
105 
106         //
107         //  If we have already been called before for this volume
108         //  (and yes this does happen), skip this volume as no writes
109         //  have been allowed since the first shutdown.
110         //
111 
112         if (FlagOn( Vcb->VcbState, VCB_STATE_SHUTDOWN ) ||
113             (Vcb->VcbCondition != VcbMounted)) {
114 
115             continue;
116         }
117 
118         CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
119 
120         CdPurgeVolume( IrpContext, Vcb, FALSE );
121 
122         //
123         //  Build an irp for this volume stack - our own irp is probably too small and
124         //  each stack may have a different stack size.
125         //
126 
127         NewIrp = IoBuildSynchronousFsdRequest( IRP_MJ_SHUTDOWN,
128                                                Vcb->TargetDeviceObject,
129                                                NULL,
130                                                0,
131                                                NULL,
132                                                &Event,
133                                                &Iosb );
134 
135         if (NewIrp != NULL) {
136 
137             Status = IoCallDriver( Vcb->TargetDeviceObject, NewIrp );
138 
139             if (Status == STATUS_PENDING) {
140 
141                 (VOID)KeWaitForSingleObject( &Event,
142                                              Executive,
143                                              KernelMode,
144                                              FALSE,
145                                              NULL );
146             }
147 
148             KeClearEvent( &Event );
149         }
150 
151         SetFlag( Vcb->VcbState, VCB_STATE_SHUTDOWN );
152 
153         //
154         //  Attempt to punch the volume down.
155         //
156 
157         VcbPresent = CdCheckForDismount( IrpContext, Vcb, FALSE );
158 
159         if (VcbPresent) {
160 
161             CdReleaseVcb( IrpContext, Vcb );
162         }
163     }
164 
165 
166     CdReleaseCdData( IrpContext );
167 
168     IoUnregisterFileSystem( CdData.FileSystemDeviceObject );
169     IoDeleteDevice( CdData.FileSystemDeviceObject );
170 #ifdef __REACTOS__
171     IoUnregisterFileSystem( CdData.HddFileSystemDeviceObject );
172     IoDeleteDevice( CdData.HddFileSystemDeviceObject );
173 #endif
174 
175     CdCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
176     return STATUS_SUCCESS;
177 }
178 
179 
180