2 * FFS File System Driver for Windows
8 * Lee Jae-Hong, http://www.pyrasis.com
19 extern PFFS_GLOBAL FFSGlobal
;
24 #pragma alloc_text(PAGE, FFSClose)
25 #pragma alloc_text(PAGE, FFSQueueCloseRequest)
26 #pragma alloc_text(PAGE, FFSDeQueueCloseRequest)
30 __drv_mustHoldCriticalRegion
33 IN PFFS_IRP_CONTEXT IrpContext
)
35 PDEVICE_OBJECT DeviceObject
;
36 NTSTATUS Status
= STATUS_SUCCESS
;
38 BOOLEAN VcbResourceAcquired
= FALSE
;
39 PFILE_OBJECT FileObject
;
41 BOOLEAN FcbResourceAcquired
= FALSE
;
43 BOOLEAN FreeVcb
= FALSE
;
49 ASSERT(IrpContext
!= NULL
);
51 ASSERT((IrpContext
->Identifier
.Type
== FFSICX
) &&
52 (IrpContext
->Identifier
.Size
== sizeof(FFS_IRP_CONTEXT
)));
54 DeviceObject
= IrpContext
->DeviceObject
;
56 if (DeviceObject
== FFSGlobal
->DeviceObject
)
58 Status
= STATUS_SUCCESS
;
62 Vcb
= (PFFS_VCB
) DeviceObject
->DeviceExtension
;
66 ASSERT((Vcb
->Identifier
.Type
== FFSVCB
) &&
67 (Vcb
->Identifier
.Size
== sizeof(FFS_VCB
)));
69 ASSERT(IsMounted(Vcb
));
71 if (!ExAcquireResourceExclusiveLite(
73 IrpContext
->IsSynchronous
))
75 FFSPrint((DBG_INFO
, "FFSClose: PENDING ... Vcb: %xh/%xh\n",
76 Vcb
->OpenFileHandleCount
, Vcb
->ReferenceCount
));
78 Status
= STATUS_PENDING
;
82 VcbResourceAcquired
= TRUE
;
84 FileObject
= IrpContext
->FileObject
;
86 if (IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_DELAY_CLOSE
))
88 Fcb
= IrpContext
->Fcb
;
89 Ccb
= IrpContext
->Ccb
;
93 Fcb
= (PFFS_FCB
)FileObject
->FsContext
;
97 Status
= STATUS_SUCCESS
;
103 Ccb
= (PFFS_CCB
)FileObject
->FsContext2
;
106 if (Fcb
->Identifier
.Type
== FFSVCB
)
108 Vcb
->ReferenceCount
--;
110 if (!Vcb
->ReferenceCount
&& FlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
))
120 FileObject
->FsContext2
= Ccb
= NULL
;
124 Status
= STATUS_SUCCESS
;
129 if (Fcb
->Identifier
.Type
!= FFSFCB
|| Fcb
->Identifier
.Size
!= sizeof(FFS_FCB
))
132 FFSPrint((DBG_ERROR
, "FFSClose: Strange IRP_MJ_CLOSE by system!\n"));
133 ExAcquireResourceExclusiveLite(
134 &FFSGlobal
->CountResource
,
137 FFSGlobal
->IRPCloseCount
++;
139 ExReleaseResourceForThreadLite(
140 &FFSGlobal
->CountResource
,
141 ExGetCurrentResourceThread());
146 ASSERT((Fcb
->Identifier
.Type
== FFSFCB
) &&
147 (Fcb
->Identifier
.Size
== sizeof(FFS_FCB
)));
150 if ((!IsFlagOn(Vcb->Flags, VCB_READ_ONLY)) &&
151 (!IsFlagOn(Fcb->Flags, FCB_PAGE_FILE)))
154 if (!ExAcquireResourceExclusiveLite(
156 IrpContext
->IsSynchronous
))
158 Status
= STATUS_PENDING
;
162 FcbResourceAcquired
= TRUE
;
167 Status
= STATUS_SUCCESS
;
171 ASSERT((Ccb
->Identifier
.Type
== FFSCCB
) &&
172 (Ccb
->Identifier
.Size
== sizeof(FFS_CCB
)));
174 Fcb
->ReferenceCount
--;
175 Vcb
->ReferenceCount
--;
177 if (!Vcb
->ReferenceCount
&& IsFlagOn(Vcb
->Flags
, VCB_DISMOUNT_PENDING
))
182 FFSPrint((DBG_INFO
, "FFSClose: OpenHandleCount: %u ReferenceCount: %u %s\n",
183 Fcb
->OpenHandleCount
, Fcb
->ReferenceCount
, Fcb
->AnsiFileName
.Buffer
));
191 FileObject
->FsContext2
= Ccb
= NULL
;
195 if (!Fcb
->ReferenceCount
)
198 // Remove Fcb from Vcb->FcbList ...
201 RemoveEntryList(&Fcb
->Next
);
205 FcbResourceAcquired
= FALSE
;
208 Status
= STATUS_SUCCESS
;
213 if (FcbResourceAcquired
)
215 ExReleaseResourceForThreadLite(
217 ExGetCurrentResourceThread());
220 if (VcbResourceAcquired
)
222 ExReleaseResourceForThreadLite(
224 ExGetCurrentResourceThread());
227 if (!IrpContext
->ExceptionInProgress
)
229 if (Status
== STATUS_PENDING
)
231 FFSQueueCloseRequest(IrpContext
);
234 Status = STATUS_SUCCESS;
236 if (IrpContext->Irp != NULL)
238 IrpContext->Irp->IoStatus.Status = Status;
242 (BOOLEAN)!IsFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_REQUEUED),
244 (NT_SUCCESS(Status) ? IO_DISK_INCREMENT : IO_NO_INCREMENT));
246 IrpContext->Irp = NULL;
253 FFSCompleteIrpContext(IrpContext
, Status
);
257 ExAcquireResourceExclusiveLite(
258 &FFSGlobal
->Resource
, TRUE
);
260 FFSClearVpbFlag(Vcb
->Vpb
, VPB_MOUNTED
);
264 ExReleaseResourceForThreadLite(
265 &FFSGlobal
->Resource
,
266 ExGetCurrentResourceThread());
279 FFSQueueCloseRequest(
280 IN PFFS_IRP_CONTEXT IrpContext
)
286 ASSERT((IrpContext
->Identifier
.Type
== FFSICX
) &&
287 (IrpContext
->Identifier
.Size
== sizeof(FFS_IRP_CONTEXT
)));
289 if (!IsFlagOn(IrpContext
->Flags
, IRP_CONTEXT_FLAG_DELAY_CLOSE
))
291 SetFlag(IrpContext
->Flags
, IRP_CONTEXT_FLAG_DELAY_CLOSE
);
293 IrpContext
->Fcb
= (PFFS_FCB
)IrpContext
->FileObject
->FsContext
;
294 IrpContext
->Ccb
= (PFFS_CCB
)IrpContext
->FileObject
->FsContext2
;
296 IrpContext
->FileObject
= NULL
;
299 // IsSynchronous means we can block (so we don't requeue it)
300 IrpContext
->IsSynchronous
= TRUE
;
302 ExInitializeWorkItem(
303 &IrpContext
->WorkQueueItem
,
304 FFSDeQueueCloseRequest
,
307 ExQueueWorkItem(&IrpContext
->WorkQueueItem
, CriticalWorkQueue
);
312 FFSDeQueueCloseRequest(
315 PFFS_IRP_CONTEXT IrpContext
;
319 IrpContext
= (PFFS_IRP_CONTEXT
) Context
;
323 ASSERT((IrpContext
->Identifier
.Type
== FFSICX
) &&
324 (IrpContext
->Identifier
.Size
== sizeof(FFS_IRP_CONTEXT
)));
330 FsRtlEnterFileSystem();
331 FFSClose(IrpContext
);
333 _SEH2_EXCEPT (FFSExceptionFilter(IrpContext
, _SEH2_GetExceptionInformation()))
335 FFSExceptionHandler(IrpContext
);
340 FsRtlExitFileSystem();