Git conversion: Make reactos the root directory, move rosapps, rostests, wallpapers...
[reactos.git] / drivers / filesystems / reiserfs / src / close.c
1 /*
2 * COPYRIGHT: GNU GENERAL PUBLIC LICENSE VERSION 2
3 * PROJECT: ReiserFs file system driver for Windows NT/2000/XP/Vista.
4 * FILE: close.c
5 * PURPOSE:
6 * PROGRAMMER: Mark Piper, Matt Wu, Bo Brantén.
7 * HOMEPAGE:
8 * UPDATE HISTORY:
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include "rfsd.h"
14
15 /* GLOBALS ***************************************************************/
16
17 extern PRFSD_GLOBAL RfsdGlobal;
18
19 /* DEFINITIONS *************************************************************/
20
21 #ifdef ALLOC_PRAGMA
22 #pragma alloc_text(PAGE, RfsdClose)
23 #pragma alloc_text(PAGE, RfsdQueueCloseRequest)
24 #pragma alloc_text(PAGE, RfsdDeQueueCloseRequest)
25 #endif
26
27 __drv_mustHoldCriticalRegion
28 NTSTATUS
29 RfsdClose (IN PRFSD_IRP_CONTEXT IrpContext)
30 {
31 PDEVICE_OBJECT DeviceObject;
32 NTSTATUS Status = STATUS_SUCCESS;
33 PRFSD_VCB Vcb = 0;
34 BOOLEAN VcbResourceAcquired = FALSE;
35 PFILE_OBJECT FileObject;
36 PRFSD_FCB Fcb = 0;
37 BOOLEAN FcbResourceAcquired = FALSE;
38 PRFSD_CCB Ccb;
39 BOOLEAN FreeVcb = FALSE;
40
41 PAGED_CODE();
42
43 _SEH2_TRY
44 {
45 ASSERT(IrpContext != NULL);
46
47 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
48 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
49
50 DeviceObject = IrpContext->DeviceObject;
51
52 if (DeviceObject == RfsdGlobal->DeviceObject)
53 {
54 Status = STATUS_SUCCESS;
55 _SEH2_LEAVE;
56 }
57
58 Vcb = (PRFSD_VCB) DeviceObject->DeviceExtension;
59
60 ASSERT(Vcb != NULL);
61
62 ASSERT((Vcb->Identifier.Type == RFSDVCB) &&
63 (Vcb->Identifier.Size == sizeof(RFSD_VCB)));
64
65 ASSERT(IsMounted(Vcb));
66
67 #ifdef _MSC_VER
68 #pragma prefast( suppress: 28137, "by design" )
69 #endif
70 if (!ExAcquireResourceExclusiveLite(
71 &Vcb->MainResource,
72 IrpContext->IsSynchronous )) {
73 RfsdPrint((DBG_INFO, "RfsdClose: PENDING ... Vcb: %xh/%xh\n",
74 Vcb->OpenFileHandleCount, Vcb->ReferenceCount));
75
76 Status = STATUS_PENDING;
77 _SEH2_LEAVE;
78 }
79
80 VcbResourceAcquired = TRUE;
81
82 FileObject = IrpContext->FileObject;
83
84 if (IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
85 Fcb = IrpContext->Fcb;
86 Ccb = IrpContext->Ccb;
87 } else {
88 Fcb = (PRFSD_FCB) FileObject->FsContext;
89
90 if (!Fcb)
91 {
92 Status = STATUS_SUCCESS;
93 _SEH2_LEAVE;
94 }
95
96 ASSERT(Fcb != NULL);
97
98 Ccb = (PRFSD_CCB) FileObject->FsContext2;
99 }
100
101 if (Fcb->Identifier.Type == RFSDVCB) {
102
103 Vcb->ReferenceCount--;
104
105 if (!Vcb->ReferenceCount && FlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING))
106 {
107 FreeVcb = TRUE;
108 }
109
110 if (Ccb) {
111 RfsdFreeCcb(Ccb);
112
113 if (FileObject) {
114 FileObject->FsContext2 = Ccb = NULL;
115 }
116 }
117
118 Status = STATUS_SUCCESS;
119
120 _SEH2_LEAVE;
121 }
122
123 if (Fcb->Identifier.Type != RFSDFCB || Fcb->Identifier.Size != sizeof(RFSD_FCB)) {
124
125 #if DBG
126 RfsdPrint((DBG_ERROR, "RfsdClose: Strange IRP_MJ_CLOSE by system!\n"));
127 ExAcquireResourceExclusiveLite(
128 &RfsdGlobal->CountResource,
129 TRUE );
130
131 RfsdGlobal->IRPCloseCount++;
132
133 ExReleaseResourceForThreadLite(
134 &RfsdGlobal->CountResource,
135 ExGetCurrentResourceThread() );
136 #endif
137 _SEH2_LEAVE;
138 }
139
140 ASSERT((Fcb->Identifier.Type == RFSDFCB) &&
141 (Fcb->Identifier.Size == sizeof(RFSD_FCB)));
142
143 /*
144 if ( (!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) &&
145 (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)) )
146 */
147 {
148 #ifdef _MSC_VER
149 #pragma prefast( suppress: 28137, "by design" )
150 #endif
151 if (!ExAcquireResourceExclusiveLite(
152 &Fcb->MainResource,
153 IrpContext->IsSynchronous )) {
154 Status = STATUS_PENDING;
155 _SEH2_LEAVE;
156 }
157
158 FcbResourceAcquired = TRUE;
159 }
160
161 if (!Ccb) {
162 Status = STATUS_SUCCESS;
163 _SEH2_LEAVE;
164 }
165
166 ASSERT((Ccb->Identifier.Type == RFSDCCB) &&
167 (Ccb->Identifier.Size == sizeof(RFSD_CCB)));
168
169 Fcb->ReferenceCount--;
170 Vcb->ReferenceCount--;
171
172 if (!Vcb->ReferenceCount && IsFlagOn(Vcb->Flags, VCB_DISMOUNT_PENDING)) {
173 FreeVcb = TRUE;
174 }
175
176 RfsdPrint((DBG_INFO, "RfsdClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
177 Fcb->OpenHandleCount, Fcb->ReferenceCount, Fcb->AnsiFileName.Buffer ));
178
179 if (Ccb) {
180
181 RfsdFreeCcb(Ccb);
182
183 if (FileObject) {
184 FileObject->FsContext2 = Ccb = NULL;
185 }
186 }
187
188 if (!Fcb->ReferenceCount) {
189 //
190 // Remove Fcb from Vcb->FcbList ...
191 //
192
193 RemoveEntryList(&Fcb->Next);
194
195 RfsdFreeFcb(Fcb);
196
197 FcbResourceAcquired = FALSE;
198 }
199
200 Status = STATUS_SUCCESS;
201
202 } _SEH2_FINALLY {
203
204 if (FcbResourceAcquired) {
205 ExReleaseResourceForThreadLite(
206 &Fcb->MainResource,
207 ExGetCurrentResourceThread() );
208 }
209
210 if (VcbResourceAcquired) {
211 ExReleaseResourceForThreadLite(
212 &Vcb->MainResource,
213 ExGetCurrentResourceThread() );
214 }
215
216 if (!IrpContext->ExceptionInProgress) {
217 if (Status == STATUS_PENDING) {
218
219 RfsdQueueCloseRequest(IrpContext);
220 /*
221
222 Status = STATUS_SUCCESS;
223
224 if (IrpContext->Irp != NULL)
225 {
226 IrpContext->Irp->IoStatus.Status = Status;
227
228 RfsdCompleteRequest(
229 IrpContext->Irp,
230 !IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
231 (CCHAR)
232 (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT)
233 );
234
235 IrpContext->Irp = NULL;
236 }
237 */
238 } else {
239
240 RfsdCompleteIrpContext(IrpContext, Status);
241
242 if (FreeVcb) {
243
244 ExAcquireResourceExclusiveLite(
245 &RfsdGlobal->Resource, TRUE );
246
247 RfsdClearVpbFlag(Vcb->Vpb, VPB_MOUNTED);
248
249 RfsdRemoveVcb(Vcb);
250
251 ExReleaseResourceForThreadLite(
252 &RfsdGlobal->Resource,
253 ExGetCurrentResourceThread() );
254
255 RfsdFreeVcb(Vcb);
256 }
257 }
258 }
259 } _SEH2_END;
260
261 return Status;
262 }
263
264 VOID
265 RfsdQueueCloseRequest (IN PRFSD_IRP_CONTEXT IrpContext)
266 {
267 PAGED_CODE();
268
269 ASSERT(IrpContext);
270
271 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
272 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
273
274 if (!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE)) {
275 SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_DELAY_CLOSE);
276
277 IrpContext->Fcb = (PRFSD_FCB) IrpContext->FileObject->FsContext;
278 IrpContext->Ccb = (PRFSD_CCB) IrpContext->FileObject->FsContext2;
279
280 IrpContext->FileObject = NULL;
281 }
282
283 // IsSynchronous means we can block (so we don't requeue it)
284 IrpContext->IsSynchronous = TRUE;
285
286 ExInitializeWorkItem(
287 &IrpContext->WorkQueueItem,
288 RfsdDeQueueCloseRequest,
289 IrpContext);
290
291 ExQueueWorkItem(&IrpContext->WorkQueueItem, CriticalWorkQueue);
292 }
293
294 VOID NTAPI
295 RfsdDeQueueCloseRequest (IN PVOID Context)
296 {
297 PRFSD_IRP_CONTEXT IrpContext;
298
299 PAGED_CODE();
300
301 IrpContext = (PRFSD_IRP_CONTEXT) Context;
302
303 ASSERT(IrpContext);
304
305 ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
306 (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
307
308 _SEH2_TRY {
309
310 _SEH2_TRY {
311
312 FsRtlEnterFileSystem();
313 RfsdClose(IrpContext);
314
315 } _SEH2_EXCEPT (RfsdExceptionFilter(IrpContext, _SEH2_GetExceptionInformation())) {
316
317 RfsdExceptionHandler(IrpContext);
318 } _SEH2_END;
319
320 } _SEH2_FINALLY {
321
322 FsRtlExitFileSystem();
323 } _SEH2_END;
324 }