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         DeviceExt->OpenHandleCount--;
45 
46         if (pFcb->OpenHandleCount != 0)
47         {
48             IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess);
49         }
50     }
51     else
52     {
53         if(!ExAcquireResourceExclusiveLite(&pFcb->MainResource,
54                                            BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
55         {
56             return STATUS_PENDING;
57         }
58         if(!ExAcquireResourceExclusiveLite(&pFcb->PagingIoResource,
59                                            BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
60         {
61             ExReleaseResourceLite(&pFcb->MainResource);
62             return STATUS_PENDING;
63         }
64 
65         pCcb = FileObject->FsContext2;
66         if (BooleanFlagOn(pCcb->Flags, CCB_DELETE_ON_CLOSE))
67         {
68             pFcb->Flags |= FCB_DELETE_PENDING;
69         }
70 
71         /* Notify about the cleanup */
72         FsRtlNotifyCleanup(IrpContext->DeviceExt->NotifySync,
73                            &(IrpContext->DeviceExt->NotifyList),
74                            FileObject->FsContext2);
75 
76         pFcb->OpenHandleCount--;
77         DeviceExt->OpenHandleCount--;
78 
79         if (!vfatFCBIsDirectory(pFcb) &&
80             FsRtlAreThereCurrentFileLocks(&pFcb->FileLock))
81         {
82             /* remove all locks this process have on this file */
83             FsRtlFastUnlockAll(&pFcb->FileLock,
84                                FileObject,
85                                IoGetRequestorProcess(IrpContext->Irp),
86                                NULL);
87         }
88 
89         if (BooleanFlagOn(pFcb->Flags, FCB_IS_DIRTY))
90         {
91             VfatUpdateEntry (pFcb, vfatVolumeIsFatX(DeviceExt));
92         }
93 
94         if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) &&
95             pFcb->OpenHandleCount == 0)
96         {
97             if (vfatFCBIsDirectory(pFcb) &&
98                 !VfatIsDirectoryEmpty(DeviceExt, pFcb))
99             {
100                 pFcb->Flags &= ~FCB_DELETE_PENDING;
101             }
102             else
103             {
104                 PFILE_OBJECT tmpFileObject;
105                 tmpFileObject = pFcb->FileObject;
106                 if (tmpFileObject != NULL)
107                 {
108                     pFcb->FileObject = NULL;
109                     CcUninitializeCacheMap(tmpFileObject, NULL, NULL);
110                     ObDereferenceObject(tmpFileObject);
111                 }
112 
113                 pFcb->RFCB.ValidDataLength.QuadPart = 0;
114                 pFcb->RFCB.FileSize.QuadPart = 0;
115                 pFcb->RFCB.AllocationSize.QuadPart = 0;
116             }
117         }
118 
119         /* Uninitialize the cache (should be done even if caching was never initialized) */
120         CcUninitializeCacheMap(FileObject, &pFcb->RFCB.FileSize, NULL);
121 
122         if (BooleanFlagOn(pFcb->Flags, FCB_DELETE_PENDING) &&
123             pFcb->OpenHandleCount == 0)
124         {
125             VfatDelEntry(DeviceExt, pFcb, NULL);
126 
127             FsRtlNotifyFullReportChange(DeviceExt->NotifySync,
128                                         &(DeviceExt->NotifyList),
129                                         (PSTRING)&pFcb->PathNameU,
130                                         pFcb->PathNameU.Length - pFcb->LongNameU.Length,
131                                         NULL,
132                                         NULL,
133                                         vfatFCBIsDirectory(pFcb) ?
134                                         FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME,
135                                         FILE_ACTION_REMOVED,
136                                         NULL);
137         }
138 
139         if (pFcb->OpenHandleCount != 0)
140         {
141             IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess);
142         }
143 
144         FileObject->Flags |= FO_CLEANUP_COMPLETE;
145 
146         ExReleaseResourceLite(&pFcb->PagingIoResource);
147         ExReleaseResourceLite(&pFcb->MainResource);
148     }
149 
150 #ifdef ENABLE_SWAPOUT
151     if (IsVolume && BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
152     {
153         VfatCheckForDismount(DeviceExt, FALSE);
154     }
155 #endif
156 
157     return STATUS_SUCCESS;
158 }
159 
160 /*
161  * FUNCTION: Cleans up after a file has been closed.
162  */
163 NTSTATUS
164 VfatCleanup(
165     PVFAT_IRP_CONTEXT IrpContext)
166 {
167     NTSTATUS Status;
168 
169     DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
170 
171     if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
172     {
173         IrpContext->Irp->IoStatus.Information = 0;
174         return STATUS_SUCCESS;
175     }
176 
177     if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource,
178                                         BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
179     {
180         return VfatMarkIrpContextForQueue(IrpContext);
181     }
182 
183     Status = VfatCleanupFile(IrpContext);
184 
185     ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
186 
187     if (Status == STATUS_PENDING)
188     {
189         return VfatMarkIrpContextForQueue(IrpContext);
190     }
191 
192     IrpContext->Irp->IoStatus.Information = 0;
193     return Status;
194 }
195 
196 /* EOF */
197