[FFS]
[reactos.git] / reactos / drivers / filesystems / ffs / src / cleanup.c
1 /*
2 * FFS File System Driver for Windows
3 *
4 * cleanup.c
5 *
6 * 2004.5.6 ~
7 *
8 * Lee Jae-Hong, http://www.pyrasis.com
9 *
10 * See License.txt
11 *
12 */
13
14 #include "ntifs.h"
15 #include "ffsdrv.h"
16
17 /* Globals */
18
19 extern PFFS_GLOBAL FFSGlobal;
20
21 /* Definitions */
22
23 #ifdef ALLOC_PRAGMA
24 #pragma alloc_text(PAGE, FFSCleanup)
25 #endif
26
27
28 __drv_mustHoldCriticalRegion
29 NTSTATUS
30 FFSCleanup(
31 IN PFFS_IRP_CONTEXT IrpContext)
32 {
33 PDEVICE_OBJECT DeviceObject;
34 NTSTATUS Status = STATUS_SUCCESS;
35 PFFS_VCB Vcb = 0;
36 BOOLEAN VcbResourceAcquired = FALSE;
37 PFILE_OBJECT FileObject;
38 PFFS_FCB Fcb = 0;
39 BOOLEAN FcbResourceAcquired = FALSE;
40 BOOLEAN FcbPagingIoAcquired = FALSE;
41 PFFS_CCB Ccb;
42 PIRP Irp;
43
44 PAGED_CODE();
45
46 _SEH2_TRY
47 {
48 ASSERT(IrpContext != NULL);
49
50 ASSERT((IrpContext->Identifier.Type == FFSICX) &&
51 (IrpContext->Identifier.Size == sizeof(FFS_IRP_CONTEXT)));
52
53 DeviceObject = IrpContext->DeviceObject;
54
55 if (DeviceObject == FFSGlobal->DeviceObject)
56 {
57 Status = STATUS_SUCCESS;
58 _SEH2_LEAVE;
59 }
60
61 Vcb = (PFFS_VCB)DeviceObject->DeviceExtension;
62
63 ASSERT(Vcb != NULL);
64
65 ASSERT((Vcb->Identifier.Type == FFSVCB) &&
66 (Vcb->Identifier.Size == sizeof(FFS_VCB)));
67
68 if (!IsFlagOn(Vcb->Flags, VCB_INITIALIZED))
69 {
70 Status = STATUS_SUCCESS;
71 _SEH2_LEAVE;
72 }
73
74 #ifdef _MSC_VER
75 #pragma prefast( suppress: 28137, "by design" )
76 #endif
77 if (!ExAcquireResourceExclusiveLite(
78 &Vcb->MainResource,
79 IrpContext->IsSynchronous))
80 {
81 Status = STATUS_PENDING;
82 _SEH2_LEAVE;
83 }
84
85 VcbResourceAcquired = TRUE;
86
87 FileObject = IrpContext->FileObject;
88
89 Fcb = (PFFS_FCB)FileObject->FsContext;
90
91 if (!Fcb)
92 {
93 Status = STATUS_SUCCESS;
94 _SEH2_LEAVE;
95 }
96
97 if (Fcb->Identifier.Type == FFSVCB)
98 {
99 if (IsFlagOn(Vcb->Flags, VCB_VOLUME_LOCKED) &&
100 (Vcb->LockFile == FileObject))
101 {
102 ClearFlag(Vcb->Flags, VCB_VOLUME_LOCKED);
103 Vcb->LockFile = NULL;
104
105 FFSClearVpbFlag(Vcb->Vpb, VPB_LOCKED);
106 }
107
108 Vcb->OpenHandleCount--;
109
110 if (!Vcb->OpenHandleCount)
111 {
112 IoRemoveShareAccess(FileObject, &Vcb->ShareAccess);
113 }
114
115 Status = STATUS_SUCCESS;
116 _SEH2_LEAVE;
117 }
118
119 ASSERT((Fcb->Identifier.Type == FFSFCB) &&
120 (Fcb->Identifier.Size == sizeof(FFS_FCB)));
121
122 /*
123 if (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
124 !IsFlagOn(Fcb->Flags, FCB_PAGE_FILE))
125 */
126 {
127 #ifdef _MSC_VER
128 #pragma prefast( suppress: 28137, "by design" )
129 #endif
130 if (!ExAcquireResourceExclusiveLite(
131 &Fcb->MainResource,
132 IrpContext->IsSynchronous))
133 {
134 Status = STATUS_PENDING;
135 _SEH2_LEAVE;
136 }
137
138 FcbResourceAcquired = TRUE;
139 }
140
141 Ccb = (PFFS_CCB)FileObject->FsContext2;
142
143 if (!Ccb)
144 {
145 Status = STATUS_SUCCESS;
146 _SEH2_LEAVE;
147 }
148
149 if (IsFlagOn(FileObject->Flags, FO_CLEANUP_COMPLETE))
150 {
151 if (IsFlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
152 IsFlagOn(Vcb->Flags, VCB_FLOPPY_DISK) &&
153 !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
154 {
155 Status = FFSFlushFile(Fcb);
156 }
157
158 _SEH2_LEAVE;
159 }
160
161 ASSERT((Ccb->Identifier.Type == FFSCCB) &&
162 (Ccb->Identifier.Size == sizeof(FFS_CCB)));
163 Irp = IrpContext->Irp;
164
165 Fcb->OpenHandleCount--;
166
167 if (!IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
168 {
169 Fcb->NonCachedOpenCount--;
170 }
171
172 Vcb->OpenFileHandleCount--;
173
174 if (IsFlagOn(Fcb->Flags, FCB_DELETE_ON_CLOSE))
175 {
176 SetFlag(Fcb->Flags, FCB_DELETE_PENDING);
177
178 if (IsDirectory(Fcb))
179 {
180 FsRtlNotifyFullChangeDirectory(
181 Vcb->NotifySync,
182 &Vcb->NotifyList,
183 Fcb,
184 NULL,
185 FALSE,
186 FALSE,
187 0,
188 NULL,
189 NULL,
190 NULL);
191 }
192 }
193
194 if (IsDirectory(Fcb))
195 {
196 FsRtlNotifyCleanup(
197 Vcb->NotifySync,
198 &Vcb->NotifyList,
199 Ccb);
200 }
201 else
202 {
203 //
204 // Drop any byte range locks this process may have on the file.
205 //
206 FsRtlFastUnlockAll(
207 &Fcb->FileLockAnchor,
208 FileObject,
209 IoGetRequestorProcess(Irp),
210 NULL);
211
212 //
213 // If there are no byte range locks owned by other processes on the
214 // file the fast I/O read/write functions doesn't have to check for
215 // locks so we set IsFastIoPossible to FastIoIsPossible again.
216 //
217 if (!FsRtlGetNextFileLock(&Fcb->FileLockAnchor, TRUE))
218 {
219 if (Fcb->Header.IsFastIoPossible != FastIoIsPossible)
220 {
221 FFSPrint((
222 DBG_INFO, ": %-16.16s %-31s %s\n",
223 FFSGetCurrentProcessName(),
224 "FastIoIsPossible",
225 Fcb->AnsiFileName.Buffer));
226
227 Fcb->Header.IsFastIoPossible = FastIoIsPossible;
228 }
229 }
230 }
231
232 if (IsFlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
233 (Fcb->NonCachedOpenCount != 0) &&
234 (Fcb->NonCachedOpenCount == Fcb->ReferenceCount) &&
235 (Fcb->SectionObject.DataSectionObject != NULL))
236 {
237
238 if(!IsFlagOn(Vcb->Flags, VCB_READ_ONLY) &&
239 !IsFlagOn(Vcb->Flags, VCB_WRITE_PROTECTED))
240 {
241 CcFlushCache(&Fcb->SectionObject, NULL, 0, NULL);
242 }
243
244 ExAcquireResourceExclusiveLite(&(Fcb->PagingIoResource), TRUE);
245 ExReleaseResourceLite(&(Fcb->PagingIoResource));
246
247 CcPurgeCacheSection(&Fcb->SectionObject,
248 NULL,
249 0,
250 FALSE);
251 }
252
253 #if !FFS_READ_ONLY
254 if (Fcb->OpenHandleCount == 0)
255 {
256 if (IsFlagOn(Fcb->Flags, FCB_DELETE_PENDING))
257 {
258 BOOLEAN bDeleted = FALSE;
259
260 //
261 // Have to delete this file...
262 //
263 #ifdef _MSC_VER
264 #pragma prefast( suppress: 28137, "by design" )
265 #endif
266 if (!ExAcquireResourceExclusiveLite(
267 &Fcb->PagingIoResource,
268 IrpContext->IsSynchronous))
269 {
270 Status = STATUS_PENDING;
271 _SEH2_LEAVE;
272 }
273
274 FcbPagingIoAcquired = TRUE;
275
276 bDeleted = FFSDeleteFile(IrpContext, Vcb, Fcb);
277
278 if (bDeleted)
279 {
280 if (IsDirectory(Fcb))
281 {
282 FFSNotifyReportChange(IrpContext, Vcb, Fcb,
283 FILE_NOTIFY_CHANGE_DIR_NAME,
284 FILE_ACTION_REMOVED);
285 }
286 else
287 {
288 FFSNotifyReportChange(IrpContext, Vcb, Fcb,
289 FILE_NOTIFY_CHANGE_FILE_NAME,
290 FILE_ACTION_REMOVED);
291 }
292 }
293
294 if (FcbPagingIoAcquired)
295 {
296 ExReleaseResourceForThreadLite(
297 &Fcb->PagingIoResource,
298 ExGetCurrentResourceThread());
299
300 FcbPagingIoAcquired = FALSE;
301 }
302
303 /*
304 if (bDeleted)
305 {
306 FFSPurgeFile(Fcb, FALSE);
307 }
308 */
309 }
310 }
311 #endif // !FFS_READ_ONLY
312
313 if (!IsDirectory(Fcb) && FileObject->PrivateCacheMap)
314 {
315 FFSPrint((DBG_INFO, "FFSCleanup: CcUninitializeCacheMap is called for %s.\n",
316 Fcb->AnsiFileName.Buffer));
317
318 CcUninitializeCacheMap(
319 FileObject,
320 (PLARGE_INTEGER)(&(Fcb->Header.FileSize)),
321 NULL);
322 }
323
324 if (!Fcb->OpenHandleCount)
325 {
326 IoRemoveShareAccess(FileObject, &Fcb->ShareAccess);
327 }
328
329 FFSPrint((DBG_INFO, "FFSCleanup: OpenCount: %u ReferCount: %u %s\n",
330 Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer));
331
332 Status = STATUS_SUCCESS;
333
334 if (FileObject)
335 {
336 SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);
337 }
338 }
339
340 _SEH2_FINALLY
341 {
342
343 if (FcbPagingIoAcquired)
344 {
345 ExReleaseResourceForThreadLite(
346 &Fcb->PagingIoResource,
347 ExGetCurrentResourceThread());
348 }
349
350 if (FcbResourceAcquired)
351 {
352 ExReleaseResourceForThreadLite(
353 &Fcb->MainResource,
354 ExGetCurrentResourceThread());
355 }
356
357 if (VcbResourceAcquired)
358 {
359 ExReleaseResourceForThreadLite(
360 &Vcb->MainResource,
361 ExGetCurrentResourceThread());
362 }
363
364 if (!IrpContext->ExceptionInProgress)
365 {
366 if (Status == STATUS_PENDING)
367 {
368 FFSQueueRequest(IrpContext);
369 }
370 else
371 {
372 IrpContext->Irp->IoStatus.Status = Status;
373
374 FFSCompleteIrpContext(IrpContext, Status);
375 }
376 }
377 } _SEH2_END;
378
379 return Status;
380 }