ReactOS 0.4.16-dev-125-g798ea90
cleanup.cpp
Go to the documentation of this file.
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.
6/*
7
8 Module name: Cleanup.cpp
9
10 Abstract:
11
12 Contains code to handle the "Cleanup" dispatch entry point.
13
14 Environment:
15
16 Kernel mode only
17*/
18
19#include "udffs.h"
20
21// define the file specific bug-check id
22#define UDF_BUG_CHECK_ID UDF_FILE_CLEANUP
23
24
25/*************************************************************************
26*
27* Function: UDFCleanup()
28*
29* Description:
30* The I/O Manager will invoke this routine to handle a cleanup
31* request
32*
33* Expected Interrupt Level (for execution) :
34*
35* IRQL_PASSIVE_LEVEL (invocation at higher IRQL will cause execution
36* to be deferred to a worker thread context)
37*
38* Return Value: STATUS_SUCCESS
39*
40*************************************************************************/
44 PDEVICE_OBJECT DeviceObject, // the logical volume device object
45 PIRP Irp // I/O Request Packet
46 )
47{
49 PtrUDFIrpContext PtrIrpContext = NULL;
50 BOOLEAN AreWeTopLevel = FALSE;
51
52 TmPrint(("UDFCleanup\n"));
53
56 ASSERT(Irp);
57
58 // If we were called with our file system device object instead of a
59 // volume device object, just complete this request with STATUS_SUCCESS
60 if (UDFIsFSDevObj(DeviceObject)) {
61 // this is a cleanup of the FSD itself
62 Irp->IoStatus.Status = RC;
63 Irp->IoStatus.Information = 0;
64
66 UDFPrint(("Deregister Autoformat\n"));
68 }
69
72 return(RC);
73 }
74
75 // set the top level context
76 AreWeTopLevel = UDFIsIrpTopLevel(Irp);
77
78 _SEH2_TRY {
79
80 // get an IRP context structure and issue the request
81 PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
82 if(PtrIrpContext) {
83 RC = UDFCommonCleanup(PtrIrpContext, Irp);
84 } else {
86 Irp->IoStatus.Status = RC;
87 Irp->IoStatus.Information = 0;
88 // complete the IRP
90 }
91
93
94 RC = UDFExceptionHandler(PtrIrpContext, Irp);
95
97 } _SEH2_END;
98
99 if (AreWeTopLevel) {
101 }
102
104
105 return(RC);
106} // end UDFCleanup()
107
108/*************************************************************************
109*
110* Function: UDFCommonCleanup()
111*
112* Description:
113* The actual work is performed here. This routine may be invoked in one'
114* of the two possible contexts:
115* (a) in the context of a system worker thread
116* (b) in the context of the original caller
117*
118* Expected Interrupt Level (for execution) :
119*
120* IRQL_PASSIVE_LEVEL
121*
122* Return Value: Does not matter!
123*
124*************************************************************************/
127 PtrUDFIrpContext PtrIrpContext,
128 PIRP Irp)
129{
132 NTSTATUS RC2;
137 PVCB Vcb = NULL;
139 ULONG lc = 0;
140 BOOLEAN AcquiredVcb = FALSE;
141 BOOLEAN AcquiredFCB = FALSE;
142 BOOLEAN AcquiredParentFCB = FALSE;
143
144// BOOLEAN CompleteIrp = TRUE;
145// BOOLEAN PostRequest = FALSE;
146 BOOLEAN ChangeTime = FALSE;
147#ifdef UDF_DBG
148 BOOLEAN CanWait = FALSE;
149#endif // UDF_DBG
150 BOOLEAN ForcedCleanUp = FALSE;
151
152 PUDF_FILE_INFO NextFileInfo = NULL;
153#ifdef UDF_DBG
154 UNICODE_STRING CurName;
155 PDIR_INDEX_HDR DirNdx;
156#endif // UDF_DBG
157// PUDF_DATALOC_INFO Dloc;
158
159 TmPrint(("UDFCommonCleanup\n"));
160
161// BrutePoint();
162
163 _SEH2_TRY {
164 // First, get a pointer to the current I/O stack location
167
169
170 // Get the FCB and CCB pointers
171 Ccb = (PtrUDFCCB)(FileObject->FsContext2);
172 ASSERT(Ccb);
173 Fcb = Ccb->Fcb;
174 ASSERT(Fcb);
175
176 Vcb = (PVCB)(PtrIrpContext->TargetDeviceObject->DeviceExtension);
177 ASSERT(Vcb);
178 ASSERT(Vcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB);
179// Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
180#ifdef UDF_DBG
181 CanWait = (PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE;
182 AdPrint((" %s\n", CanWait ? "Wt" : "nw"));
183 ASSERT(CanWait);
184#endif // UDF_DBG
185 UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
186 AcquiredVcb = TRUE;
187 // Steps we shall take at this point are:
188 // (a) Acquire the file (FCB) exclusively
189 // (b) Flush file data to disk
190 // (c) Talk to the FSRTL package (if we use it) about pending oplocks.
191 // (d) Notify the FSRTL package for use with pending notification IRPs
192 // (e) Unlock byte-range locks (if any were acquired by process)
193 // (f) Update time stamp values (e.g. fast-IO had been performed)
194 // (g) Inform the Cache Manager to uninitialize Cache Maps ...
195 // and other similar stuff.
196 // BrutePoint();
197 NtReqFcb = Fcb->NTRequiredFCB;
198
199 if (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) {
200 AdPrint(("Cleaning up Volume\n"));
201 AdPrint(("UDF: OpenHandleCount: %x\n",Fcb->OpenHandleCount));
202
204 UDFInterlockedDecrement((PLONG)&(Vcb->VCBHandleCount));
205 if(FileObject->Flags & FO_CACHE_SUPPORTED) {
206 // we've cached close
207 UDFInterlockedDecrement((PLONG)&(Fcb->CachedOpenHandleCount));
208 }
209 ASSERT(Fcb->OpenHandleCount <= (Fcb->ReferenceCount-1));
210
211 // If this handle had write access, and actually wrote something,
212 // flush the device buffers, and then set the verify bit now
213 // just to be safe (in case there is no dismount).
214 if( FileObject->WriteAccess &&
215 (FileObject->Flags & FO_FILE_MODIFIED)) {
216
217 Vcb->Vpb->RealDevice->Flags |= DO_VERIFY_VOLUME;
218 }
219 // User may decide to close locked volume without call to unlock proc
220 // So, handle this situation properly & unlock it now...
221 if (FileObject == Vcb->VolumeLockFileObject) {
222 Vcb->VolumeLockFileObject = NULL;
223 Vcb->VolumeLockPID = -1;
224 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_VOLUME_LOCKED;
225 Vcb->Vpb->Flags &= ~VPB_LOCKED;
227 }
228
229 MmPrint((" CcUninitializeCacheMap()\n"));
231 // reset device
232 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) &&
233 (Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER)) {
234 // this call doesn't modify data buffer
235 // it just requires its presence
236 UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, TRUE);
237 }
238 // We must clean up the share access at this time, since we may not
239 // get a Close call for awhile if the file was mapped through this
240 // File Object.
241 IoRemoveShareAccess( FileObject, &(NtReqFcb->FCBShareAccess) );
242
244 }
245// BrutePoint();
246#ifdef UDF_DBG
247 DirNdx = UDFGetDirIndexByFileInfo(Fcb->FileInfo);
248 if(DirNdx) {
249 CurName.Buffer = UDFDirIndex(DirNdx, Fcb->FileInfo->Index)->FName.Buffer;
250 if(CurName.Buffer) {
251 AdPrint(("Cleaning up file: %ws %8.8x\n", CurName.Buffer, FileObject));
252 } else {
253 AdPrint(("Cleaning up file: ??? \n"));
254 }
255 }
256#endif //UDF_DBG
257 AdPrint(("UDF: OpenHandleCount: %x\n",Fcb->OpenHandleCount));
258 // Acquire parent object
259 if(Fcb->FileInfo->ParentFile) {
260 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB);
261 UDFAcquireResourceExclusive(&(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB->MainResource),TRUE);
262 } else {
263 UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
264 }
265 AcquiredParentFCB = TRUE;
266 // Acquire current object
268 UDFAcquireResourceExclusive(&(NtReqFcb->MainResource),TRUE);
269 AcquiredFCB = TRUE;
270 // dereference object
272 UDFInterlockedDecrement((PLONG)&(Vcb->VCBHandleCount));
273 if(FileObject->Flags & FO_CACHE_SUPPORTED) {
274 // we've cached close
275 UDFInterlockedDecrement((PLONG)&(Fcb->CachedOpenHandleCount));
276 }
277 ASSERT(Fcb->OpenHandleCount <= (Fcb->ReferenceCount-1));
278 // check if Ccb being cleaned up has DeleteOnClose flag set
279#ifndef UDF_READ_ONLY_BUILD
280 if(Ccb->CCBFlags & UDF_CCB_DELETE_ON_CLOSE) {
281 AdPrint((" DeleteOnClose\n"));
282 // Ok, now we'll become 'delete on close'...
283 ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
284 Fcb->FCBFlags |= UDF_FCB_DELETE_ON_CLOSE;
285 FileObject->DeletePending = TRUE;
286 // Report this to the dir notify package for a directory.
287 if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
288 FsRtlNotifyFullChangeDirectory( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP),
290 0, NULL, NULL, NULL );
291 }
292 }
293#endif //UDF_READ_ONLY_BUILD
294
295 if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
296 // Unlock all outstanding file locks.
297 FsRtlFastUnlockAll(&(NtReqFcb->FileLock),
300 NULL);
301 }
302 // get Link count
303 lc = UDFGetFileLinkCount(Fcb->FileInfo);
304
305#ifndef UDF_READ_ONLY_BUILD
306 if( (Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) &&
307 !(Fcb->OpenHandleCount)) {
308 // This can be useful for Streams, those were brutally deleted
309 // (together with parent object)
310 ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
311 FileObject->DeletePending = TRUE;
312
313 // we should mark all streams of the file being deleted
314 // for deletion too, if there are no more Links to
315 // main data stream
316 if((lc <= 1) &&
317 !UDFIsSDirDeleted(Fcb->FileInfo->Dloc->SDirInfo)) {
318 RC = UDFMarkStreamsForDeletion(Vcb, Fcb, TRUE); // Delete
319 }
320 // we can release these resources 'cause UDF_FCB_DELETE_ON_CLOSE
321 // flag is already set & the file can't be opened
323 UDFReleaseResource(&(NtReqFcb->MainResource));
324 AcquiredFCB = FALSE;
325 if(Fcb->FileInfo->ParentFile) {
327 UDFReleaseResource(&(Fcb->ParentFcb->NTRequiredFCB->MainResource));
328 } else {
329 UDFReleaseResource(&(Vcb->VCBResource));
330 }
331 AcquiredParentFCB = FALSE;
332 UDFReleaseResource(&(Vcb->VCBResource));
333 AcquiredVcb = FALSE;
334
335 // Make system to issue last Close request
336 // for our Target ...
338
339#ifdef UDF_DELAYED_CLOSE
340 // remove file from our DelayedClose queue
342 ASSERT(!Fcb->IrpContextLite);
343#endif //UDF_DELAYED_CLOSE
344
345 UDFAcquireResourceShared(&(Vcb->VCBResource), TRUE);
346 AcquiredVcb = TRUE;
347 if(Fcb->FileInfo->ParentFile) {
349 UDFAcquireResourceExclusive(&(Fcb->ParentFcb->NTRequiredFCB->MainResource),TRUE);
350 } else {
351 UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
352 }
353 AcquiredParentFCB = TRUE;
355 UDFAcquireResourceExclusive(&(NtReqFcb->MainResource),TRUE);
356 AcquiredFCB = TRUE;
357
358 // we should set file sizes to zero if there are no more
359 // links to this file
360 if(lc <= 1) {
361 // Synchronize here with paging IO
362 UDFAcquireResourceExclusive(&(NtReqFcb->PagingIoResource),TRUE);
363 // set file size to zero (for system cache manager)
364// NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart =
365 NtReqFcb->CommonFCBHeader.FileSize.QuadPart =
366 NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = 0;
367 CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&(NtReqFcb->CommonFCBHeader.AllocationSize));
368
369 UDFReleaseResource(&(NtReqFcb->PagingIoResource));
370 }
371 }
372#endif //UDF_READ_ONLY_BUILD
373
374#ifdef UDF_DELAYED_CLOSE
375 if ((Fcb->ReferenceCount == 1) &&
376 /*(Fcb->NodeIdentifier.NodeType != UDF_NODE_TYPE_VCB) &&*/ // see above
377 (!(Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE)) ) {
378 Fcb->FCBFlags |= UDF_FCB_DELAY_CLOSE;
379 }
380#endif //UDF_DELAYED_CLOSE
381
382 NextFileInfo = Fcb->FileInfo;
383
384#ifndef UDF_READ_ONLY_BUILD
385 // do we need to delete it now ?
386 if( (Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) &&
387 !(Fcb->OpenHandleCount)) {
388
389 // can we do it ?
390 if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
391 ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
392 if(!UDFIsDirEmpty__(NextFileInfo)) {
393 // forget about it
394 Fcb->FCBFlags &= ~UDF_FCB_DELETE_ON_CLOSE;
395 goto DiscardDelete;
396 }
397 } else
398 if (lc <= 1) {
399 // Synchronize here with paging IO
400 BOOLEAN AcquiredPagingIo;
401 AcquiredPagingIo = UDFAcquireResourceExclusiveWithCheck(&(NtReqFcb->PagingIoResource));
402 // set file size to zero (for UdfInfo package)
403 // we should not do this for directories and linked files
404 UDFResizeFile__(Vcb, NextFileInfo, 0);
405 if(AcquiredPagingIo) {
406 UDFReleaseResource(&(NtReqFcb->PagingIoResource));
407 }
408 }
409 // mark parent object for deletion if requested
410 if((Fcb->FCBFlags & UDF_FCB_DELETE_PARENT) &&
411 Fcb->ParentFcb) {
414 }
415 // flush file. It is required by UDFUnlinkFile__()
416 RC = UDFFlushFile__(Vcb, NextFileInfo);
417 if(!NT_SUCCESS(RC)) {
418 AdPrint(("Error flushing file !!!\n"));
419 }
420 // try to unlink
421 if((RC = UDFUnlinkFile__(Vcb, NextFileInfo, TRUE)) == STATUS_CANNOT_DELETE) {
422 // If we can't delete file with Streams due to references,
423 // mark SDir & Streams
424 // for Deletion. We shall also set DELETE_PARENT flag to
425 // force Deletion of the current file later... when curently
426 // opened Streams would be cleaned up.
427
428 // WARNING! We should keep SDir & Streams if there is a
429 // link to this file
430 if(NextFileInfo->Dloc &&
431 NextFileInfo->Dloc->SDirInfo &&
432 NextFileInfo->Dloc->SDirInfo->Fcb) {
433
434 BrutePoint();
435 if(!UDFIsSDirDeleted(NextFileInfo->Dloc->SDirInfo)) {
436// RC = UDFMarkStreamsForDeletion(Vcb, Fcb, TRUE); // Delete
437//#ifdef UDF_ALLOW_PRETEND_DELETED
438 UDFPretendFileDeleted__(Vcb, Fcb->FileInfo);
439//#endif //UDF_ALLOW_PRETEND_DELETED
440 }
441 goto NotifyDelete;
442
443 } else {
444 // Getting here means that we can't delete file because of
445 // References/PemissionsDenied/Smth.Else,
446 // but not Linked+OpenedStream
447 BrutePoint();
448// RC = STATUS_SUCCESS;
449 goto DiscardDelete_1;
450 }
451 } else {
452DiscardDelete_1:
453 // We have got an ugly ERROR, or
454 // file is deleted, so forget about it
455 ASSERT(!(Fcb->FCBFlags & UDF_FCB_ROOT_DIRECTORY));
456 ForcedCleanUp = TRUE;
457 if(NT_SUCCESS(RC))
458 Fcb->FCBFlags &= ~UDF_FCB_DELETE_ON_CLOSE;
459 Fcb->FCBFlags |= UDF_FCB_DELETED;
460 RC = STATUS_SUCCESS;
461 }
462NotifyDelete:
463 // We should prevent SetEOF operations on completly
464 // deleted data streams
465 if(lc < 1) {
466 NtReqFcb->NtReqFCBFlags |= UDF_NTREQ_FCB_DELETED;
467 }
468 // Report that we have removed an entry.
469 if(UDFIsAStream(NextFileInfo)) {
470 UDFNotifyFullReportChange( Vcb, NextFileInfo,
473 } else {
474 UDFNotifyFullReportChange( Vcb, NextFileInfo,
477 }
478 } else
479 if(Fcb->FCBFlags & UDF_FCB_DELETE_ON_CLOSE) {
480DiscardDelete:
481 UDFNotifyFullReportChange( Vcb, NextFileInfo,
484 0,
486 }
487#endif //UDF_READ_ONLY_BUILD
488
489 if(Fcb->FCBFlags & UDF_FCB_DIRECTORY) {
490 // Report to the dir notify package for a directory.
491 FsRtlNotifyCleanup( Vcb->NotifyIRPMutex, &(Vcb->NextNotifyIRP), (PVOID)Ccb );
492 }
493
494 // we can't purge Cache when more than one link exists
495 if(lc > 1) {
496 ForcedCleanUp = FALSE;
497 }
498
499 if ( (FileObject->Flags & FO_CACHE_SUPPORTED) &&
500 (NtReqFcb->SectionObject.DataSectionObject) ) {
501 BOOLEAN LastNonCached = (!Fcb->CachedOpenHandleCount &&
503 // If this was the last cached open, and there are open
504 // non-cached handles, attempt a flush and purge operation
505 // to avoid cache coherency overhead from these non-cached
506 // handles later. We ignore any I/O errors from the flush.
507 // We shall not flush deleted files
508 RC = STATUS_SUCCESS;
509 if( LastNonCached
510 ||
511 (!Fcb->OpenHandleCount &&
512 !ForcedCleanUp) ) {
513
514#ifndef UDF_READ_ONLY_BUILD
515 LONGLONG OldFileSize, NewFileSize;
516
517 if( (OldFileSize = NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart) <
518 (NewFileSize = NtReqFcb->CommonFCBHeader.FileSize.QuadPart)) {
519/* UDFZeroDataEx(NtReqFcb,
520 OldFileSize,
521 NewFileSize - OldFileSize,
522 TRUE, Vcb, FileObject);*/
523
524 NtReqFcb->CommonFCBHeader.ValidDataLength.QuadPart = NewFileSize;
525 }
526#endif //UDF_READ_ONLY_BUILD
527 MmPrint((" CcFlushCache()\n"));
528 CcFlushCache( &(NtReqFcb->SectionObject), NULL, 0, &IoStatus );
529 if(!NT_SUCCESS(IoStatus.Status)) {
530 MmPrint((" CcFlushCache() error: %x\n", IoStatus.Status));
531 RC = IoStatus.Status;
532 }
533 }
534 // If file is deleted or it is last cached open, but there are
535 // some non-cached handles we should purge cache section
536 if(ForcedCleanUp || LastNonCached) {
537 if(NtReqFcb->SectionObject.DataSectionObject) {
538 MmPrint((" CcPurgeCacheSection()\n"));
539 CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );
540 }
541/* MmPrint((" CcPurgeCacheSection()\n"));
542 CcPurgeCacheSection( &(NtReqFcb->SectionObject), NULL, 0, FALSE );*/
543 }
544 // we needn't Flush here. It will be done in UDFCloseFileInfoChain()
545 }
546
547#ifndef UDF_READ_ONLY_BUILD
548 // Update FileTimes & Attrs
549 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) &&
550 !(Fcb->FCBFlags & (UDF_FCB_DELETE_ON_CLOSE |
552 UDF_FCB_DIRECTORY |
553 UDF_FCB_READ_ONLY*/)) &&
554 !UDFIsAStreamDir(NextFileInfo)) {
556 LONGLONG ASize;
558 // Check if we should set ARCHIVE bit & LastWriteTime
559 if(FileObject->Flags & FO_FILE_MODIFIED) {
560 ULONG Attr;
561 PDIR_INDEX_ITEM DirNdx;
562 DirNdx = UDFDirIndex(UDFGetDirIndexByFileInfo(NextFileInfo), NextFileInfo->Index);
563 ASSERT(DirNdx);
564 // Archive bit
565 if(!(Ccb->CCBFlags & UDF_CCB_ATTRIBUTES_SET) &&
566 (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ARCH_BIT)) {
567 Attr = UDFAttributesToNT(DirNdx, NextFileInfo->Dloc->FileEntry);
568 if(!(Attr & FILE_ATTRIBUTE_ARCHIVE))
569 UDFAttributesToUDF(DirNdx, NextFileInfo->Dloc->FileEntry, Attr | FILE_ATTRIBUTE_ARCHIVE);
570 }
571 // WriteTime
572 if(!(Ccb->CCBFlags & UDF_CCB_WRITE_TIME_SET) &&
573 (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_MODIFY_TIME)) {
574 UDFSetFileXTime(NextFileInfo, NULL, &NtTime, NULL, &NtTime);
575 NtReqFcb->LastWriteTime.QuadPart =
576 NtReqFcb->LastAccessTime.QuadPart = NtTime;
577 ChangeTime = TRUE;
578 }
579 }
580 if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
581 // Update sizes in DirIndex
582 if(!Fcb->OpenHandleCount) {
583 ASize = UDFGetFileAllocationSize(Vcb, NextFileInfo);
584// NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart;
585 UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize);
586 } else
587 if(FileObject->Flags & FO_FILE_SIZE_CHANGED) {
588 ASize = //UDFGetFileAllocationSize(Vcb, NextFileInfo);
589 NtReqFcb->CommonFCBHeader.AllocationSize.QuadPart;
590 UDFSetFileSizeInDirNdx(Vcb, NextFileInfo, &ASize);
591 }
592 }
593 // AccessTime
594 if((FileObject->Flags & FO_FILE_FAST_IO_READ) &&
595 !(Ccb->CCBFlags & UDF_CCB_ACCESS_TIME_SET) &&
596 (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ACCESS_TIME)) {
597 UDFSetFileXTime(NextFileInfo, NULL, &NtTime, NULL, NULL);
598 NtReqFcb->LastAccessTime.QuadPart = NtTime;
599// ChangeTime = TRUE;
600 }
601 // ChangeTime (AttrTime)
602 if(!(Ccb->CCBFlags & UDF_CCB_MODIFY_TIME_SET) &&
603 (Vcb->CompatFlags & UDF_VCB_IC_UPDATE_ATTR_TIME) &&
604 (ChangeTime || (Ccb->CCBFlags & (UDF_CCB_ATTRIBUTES_SET |
608 UDFSetFileXTime(NextFileInfo, NULL, NULL, &NtTime, NULL);
609 NtReqFcb->ChangeTime.QuadPart = NtTime;
610 }
611 }
612#endif //UDF_READ_ONLY_BUILD
613
614 if(!(Fcb->FCBFlags & UDF_FCB_DIRECTORY) &&
615 ForcedCleanUp) {
616 // flush system cache
617 MmPrint((" CcUninitializeCacheMap()\n"));
619 } else {
620 MmPrint((" CcUninitializeCacheMap()\n"));
622 }
623
624 // release resources now.
625 // they'll be acquired in UDFCloseFileInfoChain()
627 UDFReleaseResource(&(NtReqFcb->MainResource));
628 AcquiredFCB = FALSE;
629
630 if(Fcb->FileInfo->ParentFile) {
631 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB);
632 UDFReleaseResource(&(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB->MainResource));
633 } else {
634 UDFReleaseResource(&(Vcb->VCBResource));
635 }
636 AcquiredParentFCB = FALSE;
637 // close the chain
638 ASSERT(AcquiredVcb);
639 RC2 = UDFCloseFileInfoChain(Vcb, NextFileInfo, Ccb->TreeLength, TRUE);
640 if(NT_SUCCESS(RC))
641 RC = RC2;
642
643 Ccb->CCBFlags |= UDF_CCB_CLEANED;
644
645 // We must clean up the share access at this time, since we may not
646 // get a Close call for awhile if the file was mapped through this
647 // File Object.
648 IoRemoveShareAccess( FileObject, &(NtReqFcb->FCBShareAccess) );
649
650 NtReqFcb->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb);
651
653
654try_exit: NOTHING;
655
656 } _SEH2_FINALLY {
657
658 if(AcquiredFCB) {
660 UDFReleaseResource(&(NtReqFcb->MainResource));
661 }
662
663 if(AcquiredParentFCB) {
664 if(Fcb->FileInfo->ParentFile) {
665 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB);
666 UDFReleaseResource(&(Fcb->FileInfo->ParentFile->Fcb->NTRequiredFCB->MainResource));
667 } else {
668 UDFReleaseResource(&(Vcb->VCBResource));
669 }
670 }
671
672 if(AcquiredVcb) {
673 UDFReleaseResource(&(Vcb->VCBResource));
674 AcquiredVcb = FALSE;
675 }
676
678 // complete the IRP
679 Irp->IoStatus.Status = RC;
680 Irp->IoStatus.Information = 0;
682 // Free up the Irp Context
683 UDFReleaseIrpContext(PtrIrpContext);
684 }
685
686 } _SEH2_END; // end of "__finally" processing
687 return(RC);
688} // end UDFCommonCleanup()
689
690/*
691 This routine walks through the tree to RootDir &
692 calls UDFCloseFile__() for each file instance
693 imho, Useful feature
694 */
697 IN PVCB Vcb,
699 IN ULONG TreeLength,
700 IN BOOLEAN VcbAcquired
701 )
702{
703 PUDF_FILE_INFO ParentFI;
707 NTSTATUS RC2;
708
709 // we can't process Tree until we can acquire Vcb
710 if(!VcbAcquired)
711 UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
712
713 AdPrint(("UDFCloseFileInfoChain\n"));
714 for(; TreeLength && fi; TreeLength--) {
715
716 // close parent chain (if any)
717 // if we started path parsing not from RootDir on Create,
718 // we would never get RootDir here
720
721 // acquire parent
722 if((ParentFI = fi->ParentFile)) {
723 ParentFcb = fi->Fcb->ParentFcb;
725 ASSERT(ParentFcb->NTRequiredFCB);
728 ASSERT(ParentFcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_FCB);
729 ASSERT(ParentFcb->NTRequiredFCB->CommonFCBHeader.NodeTypeCode == UDF_NODE_TYPE_NT_REQ_FCB);
730 } else {
731 AdPrint(("Acquiring VCB...\n"));
732 UDFAcquireResourceShared(&(Vcb->VCBResource),TRUE);
733 AdPrint(("Done\n"));
734 }
735 // acquire current file/dir
736 // we must assure that no more threads try to reuse this object
737 if((Fcb = fi->Fcb)) {
738 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB);
740 ASSERT_REF(Fcb->ReferenceCount >= fi->RefCount);
741 if(!(Fcb->FCBFlags & UDF_FCB_DELETED) &&
742 (Fcb->FCBFlags & UDF_FCB_VALID))
743 UDFWriteSecurity(Vcb, Fcb, &(Fcb->NTRequiredFCB->SecurityDesc));
744 RC2 = UDFCloseFile__(Vcb,fi);
745 if(!NT_SUCCESS(RC2))
746 RC = RC2;
747 ASSERT_REF(Fcb->ReferenceCount > fi->RefCount);
748 UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB);
749 UDFReleaseResource(&(Fcb->NTRequiredFCB->MainResource));
750 } else {
751 BrutePoint();
752 RC2 = UDFCloseFile__(Vcb,fi);
753 if(!NT_SUCCESS(RC2))
754 RC = RC2;
755 }
756
757 if(ParentFI) {
759 UDFReleaseResource(&(ParentFcb->NTRequiredFCB->MainResource));
760 } else {
761 UDFReleaseResource(&(Vcb->VCBResource));
762 }
763 fi = ParentFI;
764 }
765
766 if(!VcbAcquired)
767 UDFReleaseResource(&(Vcb->VCBResource));
768
769 return RC;
770
771} // end UDFCloseFileInfoChain()
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
unsigned char BOOLEAN
VOID UDFSetFileXTime(IN PUDF_FILE_INFO FileInfo, IN LONGLONG *CrtTime, IN LONGLONG *AccTime, IN LONGLONG *AttrTime, IN LONGLONG *ChgTime)
VOID UDFAttributesToUDF(IN PDIR_INDEX_ITEM FileDirNdx, IN tag *FileEntry, IN ULONG NTAttr)
ULONG UDFAttributesToNT(IN PDIR_INDEX_ITEM FileDirNdx, IN tag *FileEntry)
LONG NTSTATUS
Definition: precomp.h:26
VOID NTAPI CcFlushCache(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, OUT OPTIONAL PIO_STATUS_BLOCK IoStatus)
Definition: cachesub.c:222
_In_ PFCB ParentFcb
Definition: cdprocs.h:736
_In_ PFCB Fcb
Definition: cdprocs.h:159
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN PFCB _In_opt_ PCCB Ccb
Definition: cdprocs.h:592
#define try_return(S)
Definition: cdprocs.h:2179
struct _VCB * PVCB
Definition: fatstruc.h:557
NTSTATUS NTAPI UDFCleanup(PDEVICE_OBJECT DeviceObject, PIRP Irp)
Definition: cleanup.cpp:43
NTSTATUS UDFCommonCleanup(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: cleanup.cpp:126
NTSTATUS UDFCloseFileInfoChain(IN PVCB Vcb, IN PUDF_FILE_INFO fi, IN ULONG TreeLength, IN BOOLEAN VcbAcquired)
Definition: cleanup.cpp:696
_In_ PIRP Irp
Definition: csq.h:116
PDIR_INDEX_HDR UDFGetDirIndexByFileInfo(IN PUDF_FILE_INFO FileInfo)
Definition: dirtree.cpp:1092
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
NTSTATUS UDFExceptionHandler(PtrUDFIrpContext PtrIrpContext, PIRP Irp)
Definition: misc.cpp:358
BOOLEAN UDFAcquireResourceExclusiveWithCheck(IN PERESOURCE Resource)
Definition: misc.cpp:2529
BOOLEAN __fastcall UDFIsIrpTopLevel(PIRP Irp)
Definition: misc.cpp:228
VOID UDFLogEvent(NTSTATUS UDFEventLogId, NTSTATUS RC)
Definition: misc.cpp:575
PtrUDFIrpContext UDFAllocateIrpContext(PIRP Irp, PDEVICE_OBJECT PtrTargetDeviceObject)
Definition: misc.cpp:985
VOID UDFReleaseIrpContext(PtrUDFIrpContext PtrIrpContext)
Definition: misc.cpp:1086
long UDFExceptionFilter(PtrUDFIrpContext PtrIrpContext, PEXCEPTION_POINTERS PtrExceptionPointers)
Definition: misc.cpp:265
#define UDFNotifyVolumeEvent(FileObject, EventCode)
Definition: env_spec.h:114
__inline VOID UDFNotifyFullReportChange(PVCB V, PUDF_FILE_INFO FI, ULONG E, ULONG A)
Definition: env_spec.h:99
#define UDFReleaseResource(Resource)
Definition: env_spec_w32.h:661
#define ValidateFileInfo(fi)
Definition: env_spec_w32.h:516
#define DO_VERIFY_VOLUME
Definition: env_spec_w32.h:393
#define UDFAcquireResourceShared(Resource, CanWait)
Definition: env_spec_w32.h:658
#define UDFAcquireResourceExclusive(Resource, CanWait)
Definition: env_spec_w32.h:656
#define MmPrint(_x_)
Definition: env_spec_w32.h:289
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
#define TmPrint(_x_)
Definition: env_spec_w32.h:290
#define UDFInterlockedDecrement(addr)
Definition: env_spec_w32.h:677
#define BrutePoint()
Definition: env_spec_w32.h:504
#define AdPrint(_x_)
Definition: env_spec_w32.h:292
#define UDF_ERROR_INTERNAL_ERROR
Definition: errmsg.h:71
FAST_IO_POSSIBLE NTAPI UDFIsFastIoPossible(IN PtrUDFFCB Fcb)
Definition: fastio.cpp:118
#define NtReqFcb
_In_ PLARGE_INTEGER NtTime
Definition: fatprocs.h:1915
NTSTATUS UDFMarkStreamsForDeletion(IN PVCB Vcb, IN PtrUDFFCB Fcb, IN BOOLEAN ForDel)
Definition: fileinfo.cpp:1137
NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL)
Definition: filelock.c:1025
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
VOID NTAPI CcSetFileSizes(IN PFILE_OBJECT FileObject, IN PCC_FILE_SIZES FileSizes)
Definition: fssup.c:356
BOOLEAN NTAPI CcUninitializeCacheMap(IN PFILE_OBJECT FileObject, IN OPTIONAL PLARGE_INTEGER TruncateSize, IN OPTIONAL PCACHE_UNINITIALIZE_EVENT UninitializeEvent)
Definition: fssup.c:286
BOOLEAN NTAPI CcPurgeCacheSection(IN PSECTION_OBJECT_POINTERS SectionObjectPointer, IN OPTIONAL PLARGE_INTEGER FileOffset, IN ULONG Length, IN BOOLEAN UninitializeCacheMaps)
Definition: fssup.c:386
#define NOTHING
Definition: input_list.c:10
#define ASSERT(a)
Definition: mode.c:44
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
#define FILE_ATTRIBUTE_ARCHIVE
Definition: nt_native.h:706
#define FSRTL_VOLUME_UNLOCK
Definition: ntifs_ex.h:443
VOID NTAPI FsRtlNotifyCleanup(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext)
Definition: notify.c:659
VOID NTAPI FsRtlNotifyFullChangeDirectory(IN PNOTIFY_SYNC NotifySync, IN PLIST_ENTRY NotifyList, IN PVOID FsContext, IN PSTRING FullDirectoryName, IN BOOLEAN WatchTree, IN BOOLEAN IgnoreBuffer, IN ULONG CompletionFilter, IN PIRP NotifyIrp, IN PCHECK_FOR_TRAVERSE_ACCESS TraverseCallback OPTIONAL, IN PSECURITY_SUBJECT_CONTEXT SubjectContext OPTIONAL)
Definition: notify.c:1487
VOID NTAPI IoRemoveShareAccess(IN PFILE_OBJECT FileObject, IN PSHARE_ACCESS ShareAccess)
Definition: file.c:3478
#define IoCompleteRequest
Definition: irp.c:1240
PEPROCESS NTAPI IoGetRequestorProcess(IN PIRP Irp)
Definition: irp.c:1782
VOID NTAPI IoSetTopLevelIrp(IN PIRP Irp)
Definition: irp.c:2000
#define Vcb
Definition: cdprocs.h:1415
OSSTATUS UDFResetDeviceDriver(IN PVCB Vcb, IN PDEVICE_OBJECT TargetDeviceObject, IN BOOLEAN Unlock)
Definition: phys_lib.cpp:4199
NTSTATUS UDFWriteSecurity(IN PVCB Vcb, IN PtrUDFFCB Fcb, IN PSECURITY_DESCRIPTOR *SecurityDesc)
Definition: secursup.cpp:796
#define UDFRemoveFromSystemDelayedQueue(Fcb)
Definition: protos.h:109
#define UDFRemoveFromDelayedQueue(Fcb)
Definition: protos.h:106
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:166
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define STATUS_CANNOT_DELETE
Definition: shellext.h:71
#define STATUS_SUCCESS
Definition: shellext.h:65
#define UDF_NODE_TYPE_NT_REQ_FCB
Definition: struct.h:57
#define UDF_FCB_VALID
Definition: struct.h:300
#define UDF_CCB_CREATE_TIME_SET
Definition: struct.h:155
#define UDF_CCB_ATTRIBUTES_SET
Definition: struct.h:157
#define UDF_IRP_CONTEXT_CAN_BLOCK
Definition: struct.h:385
#define UDF_FCB_DELETED
Definition: struct.h:314
struct _UDFContextControlBlock * PtrUDFCCB
#define UDF_CCB_ACCESS_TIME_SET
Definition: struct.h:153
#define UDF_FCB_ROOT_DIRECTORY
Definition: struct.h:304
#define UDF_CCB_CLEANED
Definition: struct.h:146
#define UDF_NTREQ_FCB_DELETED
Definition: struct.h:235
#define UDF_NODE_TYPE_FCB
Definition: struct.h:60
#define UDF_CCB_MODIFY_TIME_SET
Definition: struct.h:154
#define UDF_NODE_TYPE_VCB
Definition: struct.h:61
#define UDF_FCB_DELETE_ON_CLOSE
Definition: struct.h:309
#define UDF_FCB_DIRECTORY
Definition: struct.h:303
#define UDF_FCB_DELETE_PARENT
Definition: struct.h:319
#define UDF_FCB_DELAY_CLOSE
Definition: struct.h:313
#define UDF_CCB_WRITE_TIME_SET
Definition: struct.h:156
#define UDF_CCB_DELETE_ON_CLOSE
Definition: struct.h:162
PVOID DeviceExtension
Definition: env_spec_w32.h:418
UNICODE_STRING FName
Definition: udf_rel.h:173
struct _FCB * ParentFcb
Definition: cdstruc.h:940
LONG RefCount
Definition: ntfs.h:535
struct _FCB::@729::@732 Fcb
ULONG OpenHandleCount
Definition: ntfs.h:537
ERESOURCE MainResource
Definition: ntfs.h:528
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
PVOID AutoFormatCount
Definition: udf_common.h:629
uint32 IrpContextFlags
Definition: struct.h:364
PDEVICE_OBJECT TargetDeviceObject
Definition: struct.h:374
struct _UDF_FILE_INFO * SDirInfo
Definition: udf_rel.h:319
PUDF_DATALOC_INFO Dloc
Definition: udf_rel.h:367
struct _UDF_FILE_INFO * ParentFile
Definition: udf_rel.h:381
uint_di Index
Definition: udf_rel.h:392
Definition: cdstruc.h:498
int64_t LONGLONG
Definition: typedefs.h:68
#define NTAPI
Definition: typedefs.h:36
#define IN
Definition: typedefs.h:39
int32_t * PLONG
Definition: typedefs.h:58
uint32_t ULONG
Definition: typedefs.h:59
#define UDF_VCB_IC_UPDATE_MODIFY_TIME
Definition: udf_common.h:494
#define UDF_VCB_FLAGS_VOLUME_MOUNTED
Definition: udf_common.h:459
#define UDF_VCB_IC_UPDATE_ATTR_TIME
Definition: udf_common.h:495
#define UDF_VCB_FLAGS_VOLUME_READ_ONLY
Definition: udf_common.h:463
#define UDF_VCB_IC_UPDATE_ARCH_BIT
Definition: udf_common.h:496
#define UDF_VCB_IC_UPDATE_ACCESS_TIME
Definition: udf_common.h:493
#define UDF_VCB_FLAGS_OUR_DEVICE_DRIVER
Definition: udf_common.h:466
#define ASSERT_REF(_a_)
Definition: udf_dbg.h:267
uint16 UDFGetFileLinkCount(IN PUDF_FILE_INFO FileInfo)
Definition: udf_info.cpp:1355
OSSTATUS UDFCloseFile__(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo)
Definition: udf_info.cpp:2994
OSSTATUS UDFFlushFile__(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, IN ULONG FlushFlags)
Definition: udf_info.cpp:4119
OSSTATUS UDFUnlinkFile__(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, IN BOOLEAN FreeSpace)
Definition: udf_info.cpp:1766
void UDFSetFileSizeInDirNdx(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo, IN int64 *ASize)
Definition: udf_info.cpp:1190
OSSTATUS UDFResizeFile__(IN PVCB Vcb, IN OUT PUDF_FILE_INFO FileInfo, IN int64 NewLength)
Definition: udf_info.cpp:3468
OSSTATUS UDFPretendFileDeleted__(IN PVCB Vcb, IN PUDF_FILE_INFO FileInfo)
Definition: udf_info.cpp:5566
#define UDFIsSDirDeleted(FI)
Definition: udf_info.h:1004
#define UDFGetFileAllocationSize(Vcb, FileInfo)
Definition: udf_info.h:797
#define UDFIsDirEmpty__(fi)
Definition: udf_info.h:1070
__inline PDIR_INDEX_ITEM UDFDirIndex(IN PDIR_INDEX_HDR hDirNdx, IN uint_di i)
Definition: udf_info.h:1105
#define UDFIsAStreamDir(FI)
Definition: udf_info.h:998
#define UDFIsADirectory(FileInfo)
Definition: udf_info.h:792
#define UDFIsAStream(FI)
Definition: udf_info.h:1002
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
UDFData UDFGlobalData
Definition: udfinit.cpp:25
#define UDF_CHECK_PAGING_IO_RESOURCE(NTReqFCB)
Definition: udffs.h:260
#define UDFPrint(Args)
Definition: udffs.h:223
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
#define FILE_ACTION_MODIFIED_STREAM
#define FILE_ACTION_MODIFIED
#define IO_NO_INCREMENT
Definition: iotypes.h:598
#define FO_FILE_FAST_IO_READ
Definition: iotypes.h:1795
#define FILE_NOTIFY_CHANGE_STREAM_NAME
#define FILE_ACTION_REMOVED_STREAM
#define FILE_NOTIFY_CHANGE_LAST_ACCESS
#define FILE_NOTIFY_CHANGE_ATTRIBUTES
#define FILE_ACTION_REMOVED
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define FILE_NOTIFY_CHANGE_FILE_NAME
#define FO_CLEANUP_COMPLETE
Definition: iotypes.h:1790
* PFILE_OBJECT
Definition: iotypes.h:1998
#define FO_FILE_SIZE_CHANGED
Definition: iotypes.h:1789
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define FO_CACHE_SUPPORTED
Definition: iotypes.h:1781
#define FILE_NOTIFY_CHANGE_LAST_WRITE
#define FILE_NOTIFY_CHANGE_DIR_NAME
_In_opt_ PLARGE_INTEGER NewFileSize
Definition: mmfuncs.h:608