1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * FILE: drivers/fs/vfat/cleanup.c 5 * PURPOSE: VFAT Filesystem 6 * PROGRAMMER: Jason Filby (jasonfilby@yahoo.com) 7 */ 8 9 /* INCLUDES *****************************************************************/ 10 11 #include "vfat.h" 12 13 #define NDEBUG 14 #include <debug.h> 15 16 /* FUNCTIONS ****************************************************************/ 17 18 /* 19 * FUNCTION: Cleans up after a file has been closed. 20 */ 21 static 22 NTSTATUS 23 VfatCleanupFile( 24 PVFAT_IRP_CONTEXT IrpContext) 25 { 26 PVFATFCB pFcb; 27 PVFATCCB pCcb; 28 BOOLEAN IsVolume; 29 PDEVICE_EXTENSION DeviceExt = IrpContext->DeviceExt; 30 PFILE_OBJECT FileObject = IrpContext->FileObject; 31 32 DPRINT("VfatCleanupFile(DeviceExt %p, FileObject %p)\n", 33 IrpContext->DeviceExt, FileObject); 34 35 /* FIXME: handle file/directory deletion here */ 36 pFcb = (PVFATFCB)FileObject->FsContext; 37 if (!pFcb) 38 return STATUS_SUCCESS; 39 40 IsVolume = BooleanFlagOn(pFcb->Flags, FCB_IS_VOLUME); 41 if (IsVolume) 42 { 43 pFcb->OpenHandleCount--; 44 45 if (pFcb->OpenHandleCount != 0) 46 { 47 IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess); 48 } 49 } 50 else 51 { 52 if(!ExAcquireResourceExclusiveLite(&pFcb->MainResource, 53 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 54 { 55 return STATUS_PENDING; 56 } 57 if(!ExAcquireResourceExclusiveLite(&pFcb->PagingIoResource, 58 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 59 { 60 ExReleaseResourceLite(&pFcb->MainResource); 61 return STATUS_PENDING; 62 } 63 64 pCcb = FileObject->FsContext2; 65 if (BooleanFlagOn(pCcb->Flags, CCB_DELETE_ON_CLOSE)) 66 { 67 pFcb->Flags |= FCB_DELETE_PENDING; 68 } 69 70 /* Notify about the cleanup */ 71 FsRtlNotifyCleanup(IrpContext->DeviceExt->NotifySync, 72 &(IrpContext->DeviceExt->NotifyList), 73 FileObject->FsContext2); 74 75 pFcb->OpenHandleCount--; 76 DeviceExt->OpenHandleCount--; 77 78 if (!vfatFCBIsDirectory(pFcb) && 79 FsRtlAreThereCurrentFileLocks(&pFcb->FileLock)) 80 { 81 /* remove all locks this process have on this file */ 82 FsRtlFastUnlockAll(&pFcb->FileLock, 83 FileObject, 84 IoGetRequestorProcess(IrpContext->Irp), 85 NULL); 86 } 87 88 if (BooleanFlagOn(pFcb->Flags, FCB_IS_DIRTY)) 89 { 90 VfatUpdateEntry (pFcb, vfatVolumeIsFatX(DeviceExt)); 91 } 92 93 if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) && 94 pFcb->OpenHandleCount == 0) 95 { 96 if (vfatFCBIsDirectory(pFcb) && 97 !VfatIsDirectoryEmpty(DeviceExt, pFcb)) 98 { 99 pFcb->Flags &= ~FCB_DELETE_PENDING; 100 } 101 else 102 { 103 PFILE_OBJECT tmpFileObject; 104 tmpFileObject = pFcb->FileObject; 105 if (tmpFileObject != NULL) 106 { 107 pFcb->FileObject = NULL; 108 CcUninitializeCacheMap(tmpFileObject, NULL, NULL); 109 ObDereferenceObject(tmpFileObject); 110 } 111 112 pFcb->RFCB.ValidDataLength.QuadPart = 0; 113 pFcb->RFCB.FileSize.QuadPart = 0; 114 pFcb->RFCB.AllocationSize.QuadPart = 0; 115 } 116 } 117 118 /* Uninitialize the cache (should be done even if caching was never initialized) */ 119 CcUninitializeCacheMap(FileObject, &pFcb->RFCB.FileSize, NULL); 120 121 if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) && 122 pFcb->OpenHandleCount == 0) 123 { 124 VfatDelEntry(DeviceExt, pFcb, NULL); 125 126 FsRtlNotifyFullReportChange(DeviceExt->NotifySync, 127 &(DeviceExt->NotifyList), 128 (PSTRING)&pFcb->PathNameU, 129 pFcb->PathNameU.Length - pFcb->LongNameU.Length, 130 NULL, 131 NULL, 132 vfatFCBIsDirectory(pFcb) ? 133 FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME, 134 FILE_ACTION_REMOVED, 135 NULL); 136 } 137 138 if (pFcb->OpenHandleCount != 0) 139 { 140 IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess); 141 } 142 143 FileObject->Flags |= FO_CLEANUP_COMPLETE; 144 145 ExReleaseResourceLite(&pFcb->PagingIoResource); 146 ExReleaseResourceLite(&pFcb->MainResource); 147 } 148 149 #ifdef ENABLE_SWAPOUT 150 if (IsVolume && BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING)) 151 { 152 VfatCheckForDismount(DeviceExt, FALSE); 153 } 154 #endif 155 156 return STATUS_SUCCESS; 157 } 158 159 /* 160 * FUNCTION: Cleans up after a file has been closed. 161 */ 162 NTSTATUS 163 VfatCleanup( 164 PVFAT_IRP_CONTEXT IrpContext) 165 { 166 NTSTATUS Status; 167 168 DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp); 169 170 if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject) 171 { 172 IrpContext->Irp->IoStatus.Information = 0; 173 return STATUS_SUCCESS; 174 } 175 176 if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource, 177 BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT))) 178 { 179 return VfatMarkIrpContextForQueue(IrpContext); 180 } 181 182 Status = VfatCleanupFile(IrpContext); 183 184 ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource); 185 186 if (Status == STATUS_PENDING) 187 { 188 return VfatMarkIrpContextForQueue(IrpContext); 189 } 190 191 IrpContext->Irp->IoStatus.Information = 0; 192 return Status; 193 } 194 195 /* EOF */ 196