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             vfatReportChange(DeviceExt,
128                              pFcb,
129                              (vfatFCBIsDirectory(pFcb) ?
130                               FILE_NOTIFY_CHANGE_DIR_NAME : FILE_NOTIFY_CHANGE_FILE_NAME),
131                              FILE_ACTION_REMOVED);
132         }
133 
134         if (pFcb->OpenHandleCount != 0)
135         {
136             IoRemoveShareAccess(FileObject, &pFcb->FCBShareAccess);
137         }
138 
139         FileObject->Flags |= FO_CLEANUP_COMPLETE;
140 
141         ExReleaseResourceLite(&pFcb->PagingIoResource);
142         ExReleaseResourceLite(&pFcb->MainResource);
143     }
144 
145 #ifdef ENABLE_SWAPOUT
146     if (IsVolume && BooleanFlagOn(DeviceExt->Flags, VCB_DISMOUNT_PENDING))
147     {
148         VfatCheckForDismount(DeviceExt, FALSE);
149     }
150 #endif
151 
152     return STATUS_SUCCESS;
153 }
154 
155 /*
156  * FUNCTION: Cleans up after a file has been closed.
157  */
158 NTSTATUS
159 VfatCleanup(
160     PVFAT_IRP_CONTEXT IrpContext)
161 {
162     NTSTATUS Status;
163 
164     DPRINT("VfatCleanup(DeviceObject %p, Irp %p)\n", IrpContext->DeviceObject, IrpContext->Irp);
165 
166     if (IrpContext->DeviceObject == VfatGlobalData->DeviceObject)
167     {
168         IrpContext->Irp->IoStatus.Information = 0;
169         return STATUS_SUCCESS;
170     }
171 
172     if (!ExAcquireResourceExclusiveLite(&IrpContext->DeviceExt->DirResource,
173                                         BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
174     {
175         return VfatMarkIrpContextForQueue(IrpContext);
176     }
177 
178     Status = VfatCleanupFile(IrpContext);
179 
180     ExReleaseResourceLite(&IrpContext->DeviceExt->DirResource);
181 
182     if (Status == STATUS_PENDING)
183     {
184         return VfatMarkIrpContextForQueue(IrpContext);
185     }
186 
187     IrpContext->Irp->IoStatus.Information = 0;
188     return Status;
189 }
190 
191 /* EOF */
192