https://git.reactos.org/?p=reactos.git;a=commitdiff;h=5472c1db82570a1ecd928…
commit 5472c1db82570a1ecd928c8c617320ee12ebfe15
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Fri Sep 28 23:34:28 2018 +0200
Commit: Pierre Schweitzer <pierre(a)reactos.org>
CommitDate: Fri Sep 28 23:34:28 2018 +0200
[NTOSKRNL] Unlock file if required on last process handle close
---
ntoskrnl/io/iomgr/file.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 65 insertions(+), 2 deletions(-)
diff --git a/ntoskrnl/io/iomgr/file.c b/ntoskrnl/io/iomgr/file.c
index 15504adaca..8e3b626cdf 100644
--- a/ntoskrnl/io/iomgr/file.c
+++ b/ntoskrnl/io/iomgr/file.c
@@ -1938,6 +1938,7 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
NTSTATUS Status;
PDEVICE_OBJECT DeviceObject;
KIRQL OldIrql;
+ IO_STATUS_BLOCK IoStatusBlock;
IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody);
/* If this isn't the last handle for the current process, quit */
@@ -1946,8 +1947,70 @@ IopCloseFile(IN PEPROCESS Process OPTIONAL,
/* Check if the file is locked and has more then one handle opened */
if ((FileObject->LockOperation) && (SystemHandleCount != 1))
{
- DPRINT1("We need to unlock this file!\n");
- ASSERT(FALSE);
+ /* Check if this is a direct open or not */
+ if (BooleanFlagOn(FileObject->Flags, FO_DIRECT_DEVICE_OPEN))
+ {
+ /* Get the attached device */
+ DeviceObject = IoGetAttachedDevice(FileObject->DeviceObject);
+ }
+ else
+ {
+ /* Get the FO's device */
+ DeviceObject = IoGetRelatedDeviceObject(FileObject);
+ }
+
+ /* Check if this is a sync FO and lock it */
+ if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+ {
+ IopLockFileObject(FileObject);
+ }
+
+ /* Go the FastIO path if possible, otherwise fall back to IRP */
+ if (DeviceObject->DriverObject->FastIoDispatch == NULL ||
+ DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll == NULL ||
+ !DeviceObject->DriverObject->FastIoDispatch->FastIoUnlockAll(FileObject, PsGetCurrentProcess(), &IoStatusBlock, DeviceObject))
+ {
+ /* Clear and set up Events */
+ KeClearEvent(&FileObject->Event);
+ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
+
+ /* Allocate an IRP */
+ Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize);
+
+ /* Set it up */
+ Irp->UserEvent = &Event;
+ Irp->UserIosb = &Irp->IoStatus;
+ Irp->Tail.Overlay.Thread = PsGetCurrentThread();
+ Irp->Tail.Overlay.OriginalFileObject = FileObject;
+ Irp->RequestorMode = KernelMode;
+ Irp->Flags = IRP_SYNCHRONOUS_API;
+ Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL;
+
+ /* Set up Stack Pointer Data */
+ StackPtr = IoGetNextIrpStackLocation(Irp);
+ StackPtr->MajorFunction = IRP_MJ_LOCK_CONTROL;
+ StackPtr->MinorFunction = IRP_MN_UNLOCK_ALL;
+ StackPtr->FileObject = FileObject;
+
+ /* Queue the IRP */
+ IopQueueIrpToThread(Irp);
+
+ /* Call the FS Driver */
+ Status = IoCallDriver(DeviceObject, Irp);
+ if (Status == STATUS_PENDING)
+ {
+ /* Wait for completion */
+ KeWaitForSingleObject(&Event, UserRequest, KernelMode, FALSE, NULL);
+ }
+
+ /* IO will unqueue & free for us */
+ }
+
+ /* Release the lock if we were holding it */
+ if (BooleanFlagOn(FileObject->Flags, FO_SYNCHRONOUS_IO))
+ {
+ IopUnlockFileObject(FileObject);
+ }
}
/* Make sure this is the last handle */