Index: file.c =================================================================== --- ntoskrnl/io/imgr/file.c (revision 72853) +++ ntoskrnl/io/imgr/file.c (working copy) @@ -1938,6 +1938,9 @@ NTSTATUS Status; PDEVICE_OBJECT DeviceObject; KIRQL OldIrql; + IO_STATUS_BLOCK IoStatusBlock; + PFAST_IO_DISPATCH FastIoDispatch; + IOTRACE(IO_FILE_DEBUG, "ObjectBody: %p\n", ObjectBody); /* If this isn't the last handle for the current process, quit */ @@ -1946,8 +1949,77 @@ /* 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 (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 (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + IopLockFileObject(FileObject); + ObReferenceObject(FileObject); + } + + FastIoDispatch = DeviceObject->DriverObject->FastIoDispatch; + if (!FastIoDispatch || + !FastIoDispatch->FastIoUnlockAll || + !FastIoDispatch->FastIoUnlockAll(FileObject, + PsGetCurrentProcess(), + &IoStatusBlock, + DeviceObject)) + { + /* Reset the events */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + KeClearEvent(&FileObject->Event); + + /* Allocate an IRP */ + Irp = IopAllocateIrpMustSucceed(DeviceObject->StackSize); + + /* Set it up */ + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + Irp->UserEvent = &Event; + Irp->UserIosb = &Irp->IoStatus; + Irp->Overlay.AsynchronousParameters.UserApcRoutine = NULL; + Irp->Tail.Overlay.OriginalFileObject = FileObject; + Irp->RequestorMode = KernelMode; + Irp->Flags = IRP_SYNCHRONOUS_API; + + /* 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 */ + ObReferenceObject(FileObject); + IopQueueIrpToThread(Irp); + + /* Call the FS Driver */ + Status = IoCallDriver(DeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for completion */ + KeWaitForSingleObject(&Event, UserRequest, + KernelMode, FALSE, NULL); + } + } + + /* Release lock and dereference */ + if (FileObject->Flags & FO_SYNCHRONOUS_IO) + { + IopUnlockFileObject(FileObject); + ObDereferenceObject(FileObject); + } + + return; } /* Make sure this is the last handle */