[IPHLPAPI] Implement getOwnerModUdpTable() and getOwnerModTcpTable()
[reactos.git] / drivers / filesystems / udfs / shutdown.cpp
1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*************************************************************************
7 *
8 * File: Shutdown.cpp
9 *
10 * Module: UDF File System Driver (Kernel mode execution only)
11 *
12 * Description:
13 * Contains code to handle the "shutdown notification" dispatch entry point.
14 *
15 *************************************************************************/
16
17 #include "udffs.h"
18
19 // define the file specific bug-check id
20 #define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN
21
22
23
24 /*************************************************************************
25 *
26 * Function: UDFShutdown()
27 *
28 * Description:
29 * All disk-based FSDs can expect to receive this shutdown notification
30 * request whenever the system is about to be halted gracefully. If you
31 * design and implement a network redirector, you must register explicitly
32 * for shutdown notification by invoking the IoRegisterShutdownNotification()
33 * routine from your driver entry.
34 *
35 * Note that drivers that register to receive shutdown notification get
36 * invoked BEFORE disk-based FSDs are told about the shutdown notification.
37 *
38 * Expected Interrupt Level (for execution) :
39 *
40 * IRQL_PASSIVE_LEVEL
41 *
42 * Return Value: Irrelevant.
43 *
44 *************************************************************************/
45 NTSTATUS
46 NTAPI
47 UDFShutdown(
48 PDEVICE_OBJECT DeviceObject, // the logical volume device object
49 PIRP Irp // I/O Request Packet
50 )
51 {
52 NTSTATUS RC = STATUS_SUCCESS;
53 PtrUDFIrpContext PtrIrpContext = NULL;
54 BOOLEAN AreWeTopLevel = FALSE;
55
56 UDFPrint(("UDFShutDown\n"));
57 // BrutePoint();
58
59 FsRtlEnterFileSystem();
60 ASSERT(DeviceObject);
61 ASSERT(Irp);
62
63 // set the top level context
64 AreWeTopLevel = UDFIsIrpTopLevel(Irp);
65 //ASSERT(!UDFIsFSDevObj(DeviceObject));
66
67 _SEH2_TRY {
68
69 // get an IRP context structure and issue the request
70 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
71 if(PtrIrpContext) {
72 RC = UDFCommonShutdown(PtrIrpContext, Irp);
73 } else {
74 RC = STATUS_INSUFFICIENT_RESOURCES;
75 Irp->IoStatus.Status = RC;
76 Irp->IoStatus.Information = 0;
77 // complete the IRP
78 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
79 }
80
81 } _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
82
83 RC = UDFExceptionHandler(PtrIrpContext, Irp);
84
85 UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
86 } _SEH2_END;
87
88 if (AreWeTopLevel) {
89 IoSetTopLevelIrp(NULL);
90 }
91
92 FsRtlExitFileSystem();
93
94 return(RC);
95 } // end UDFShutdown()
96
97
98 /*************************************************************************
99 *
100 * Function: UDFCommonShutdown()
101 *
102 * Description:
103 * The actual work is performed here. Basically, all we do here is
104 * internally invoke a flush on all mounted logical volumes. This, in
105 * tuen, will result in all open file streams being flushed to disk.
106 *
107 * Expected Interrupt Level (for execution) :
108 *
109 * IRQL_PASSIVE_LEVEL
110 *
111 * Return Value: Irrelevant
112 *
113 *************************************************************************/
114 NTSTATUS
115 UDFCommonShutdown(
116 PtrUDFIrpContext PtrIrpContext,
117 PIRP Irp
118 )
119 {
120 NTSTATUS RC = STATUS_SUCCESS;
121 PIO_STACK_LOCATION IrpSp = NULL;
122 PVCB Vcb;
123 PLIST_ENTRY Link;
124 PPREVENT_MEDIA_REMOVAL_USER_IN Buf = NULL;
125 LARGE_INTEGER delay;
126
127 UDFPrint(("UDFCommonShutdown\n"));
128
129 _SEH2_TRY {
130 // First, get a pointer to the current I/O stack location
131 IrpSp = IoGetCurrentIrpStackLocation(Irp);
132 ASSERT(IrpSp);
133
134 Buf = (PPREVENT_MEDIA_REMOVAL_USER_IN)MyAllocatePool__(NonPagedPool, sizeof(PREVENT_MEDIA_REMOVAL_USER_IN));
135 if(!Buf)
136 try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
137
138 // (a) Block all new "mount volume" requests by acquiring an appropriate
139 // global resource/lock.
140 // (b) Go through your linked list of mounted logical volumes and for
141 // each such volume, do the following:
142 // (i) acquire the volume resource exclusively
143 // (ii) invoke UDFFlushLogicalVolume() (internally) to flush the
144 // open data streams belonging to the volume from the system
145 // cache
146 // (iii) Invoke the physical/virtual/logical target device object
147 // on which the volume is mounted and inform this device
148 // about the shutdown request (Use IoBuildSynchronouFsdRequest()
149 // to create an IRP with MajorFunction = IRP_MJ_SHUTDOWN that you
150 // will then issue to the target device object).
151 // (iv) Wait for the completion of the shutdown processing by the target
152 // device object
153 // (v) Release the VCB resource we will have acquired in (i) above.
154
155 // Acquire GlobalDataResource
156 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
157 // Walk through all of the Vcb's attached to the global data.
158 Link = UDFGlobalData.VCBQueue.Flink;
159
160 while (Link != &(UDFGlobalData.VCBQueue)) {
161 // Get 'next' Vcb
162 Vcb = CONTAINING_RECORD( Link, VCB, NextVCB );
163 // Move to the next link now since the current Vcb may be deleted.
164 Link = Link->Flink;
165 ASSERT(Link != Link->Flink);
166
167 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN)) {
168
169 #ifdef UDF_DELAYED_CLOSE
170 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
171 UDFPrint((" UDFCommonShutdown: set UDF_VCB_FLAGS_NO_DELAYED_CLOSE\n"));
172 Vcb->VCBFlags |= UDF_VCB_FLAGS_NO_DELAYED_CLOSE;
173 UDFReleaseResource(&(Vcb->VCBResource));
174 #endif //UDF_DELAYED_CLOSE
175
176 // Note: UDFCloseAllDelayed() doesn't acquire DelayedCloseResource if
177 // GlobalDataResource is already acquired. Thus for now we should
178 // release GlobalDataResource and re-acquire it later.
179 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
180 if(Vcb->RootDirFCB && Vcb->RootDirFCB->FileInfo) {
181 UDFPrint((" UDFCommonShutdown: UDFCloseAllSystemDelayedInDir\n"));
182 RC = UDFCloseAllSystemDelayedInDir(Vcb, Vcb->RootDirFCB->FileInfo);
183 ASSERT(OS_SUCCESS(RC));
184 }
185
186 #ifdef UDF_DELAYED_CLOSE
187 UDFCloseAllDelayed(Vcb);
188 // UDFReleaseResource(&(UDFGlobalData.DelayedCloseResource));
189 #endif //UDF_DELAYED_CLOSE
190
191 // re-acquire GlobalDataResource
192 UDFAcquireResourceExclusive(&(UDFGlobalData.GlobalDataResource), TRUE);
193
194 // disable Eject Waiter
195 UDFStopEjectWaiter(Vcb);
196 // Acquire Vcb resource
197 UDFAcquireResourceExclusive(&(Vcb->VCBResource), TRUE);
198
199 ASSERT(!Vcb->OverflowQueueCount);
200
201 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_SHUTDOWN)) {
202
203 UDFDoDismountSequence(Vcb, Buf, FALSE);
204 if(Vcb->VCBFlags & UDF_VCB_FLAGS_REMOVABLE_MEDIA) {
205 // let drive flush all data before reset
206 delay.QuadPart = -10000000; // 1 sec
207 KeDelayExecutionThread(KernelMode, FALSE, &delay);
208 }
209 Vcb->VCBFlags |= (UDF_VCB_FLAGS_SHUTDOWN |
210 UDF_VCB_FLAGS_VOLUME_READ_ONLY);
211 }
212
213 UDFReleaseResource(&(Vcb->VCBResource));
214 }
215 }
216 // Once we have processed all the mounted logical volumes, we can release
217 // all acquired global resources and leave (in peace :-)
218 UDFReleaseResource( &(UDFGlobalData.GlobalDataResource) );
219 RC = STATUS_SUCCESS;
220
221 try_exit: NOTHING;
222
223 } _SEH2_FINALLY {
224
225 if(Buf) MyFreePool__(Buf);
226 if(!_SEH2_AbnormalTermination()) {
227 Irp->IoStatus.Status = RC;
228 Irp->IoStatus.Information = 0;
229 // Free up the Irp Context
230 UDFReleaseIrpContext(PtrIrpContext);
231 // complete the IRP
232 IoCompleteRequest(Irp, IO_DISK_INCREMENT);
233 }
234
235 } _SEH2_END; // end of "__finally" processing
236
237 return(RC);
238 } // end UDFCommonShutdown()