/* * @implemented */ NTSTATUS NTAPI FsRtlFastUnlockAll(IN PFILE_LOCK FileLock, IN PFILE_OBJECT FileObject, IN PEPROCESS Process, IN PVOID Context OPTIONAL) { PLIST_ENTRY ListEntry; PCOMBINED_LOCK_ELEMENT Entry; PLOCK_INFORMATION InternalInfo = FileLock->LockInformation; DPRINT("FsRtlFastUnlockAll(%wZ)\n", &FileObject->FileName); // XXX Synchronize somehow if (!FileLock->LockInformation) { DPRINT("Not locked %wZ\n", &FileObject->FileName); return STATUS_RANGE_NOT_LOCKED; // no locks } for (ListEntry = InternalInfo->SharedLocks.Flink; ListEntry != &InternalInfo->SharedLocks;) { LARGE_INTEGER Length; PLOCK_SHARED_RANGE Range = CONTAINING_RECORD(ListEntry, LOCK_SHARED_RANGE, Entry); Length.QuadPart = Range->End.QuadPart - Range->Start.QuadPart; ListEntry = ListEntry->Flink; if (Range->ProcessId != Process->UniqueProcessId) continue; FsRtlFastUnlockSingle (FileLock, FileObject, &Range->Start, &Length, Range->ProcessId, Range->Key, Context, TRUE); } for (Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, TRUE); Entry; Entry = RtlEnumerateGenericTable(&InternalInfo->RangeTable, FALSE)) { LARGE_INTEGER Length; // We'll take the first one to be the list head, and free the others first... Length.QuadPart = Entry->Exclusive.FileLock.EndingByte.QuadPart - Entry->Exclusive.FileLock.StartingByte.QuadPart; FsRtlFastUnlockSingle (FileLock, Entry->Exclusive.FileLock.FileObject, &Entry->Exclusive.FileLock.StartingByte, &Length, Entry->Exclusive.FileLock.ProcessId, Entry->Exclusive.FileLock.Key, Context, TRUE); } DPRINT("Done %wZ\n", &FileObject->FileName); return STATUS_SUCCESS; }
BOOLEAN FatFastUnlockSingle ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock single call. Arguments: FileObject - Supplies the file object used in this operation FileOffset - Supplies the file offset used in this operation Length - Supplies the length used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation Status - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results; PVCB Vcb; PFCB Fcb; PCCB Ccb; DebugTrace(+1, Dbg, "FatFastUnlockSingle\n", 0); IoStatus->Information = 0; // // Decode the type of file object we're being asked to process and make sure // it is only a user file open // if (FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb ) != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; DebugTrace(-1, Dbg, "FatFastUnlockSingle -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; } // // Acquire exclusive access to the Fcb this operation can always wait // FsRtlEnterFileSystem(); try { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( &(Fcb)->Specific.Fcb.Oplock )) { try_return( Results = FALSE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request. The call will always succeed. // Results = TRUE; IoStatus->Status = FsRtlFastUnlockSingle( &Fcb->Specific.Fcb.FileLock, FileObject, FileOffset, Length, ProcessId, Key, NULL, FALSE ); // // Set the flag indicating if Fast I/O is possible // Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); try_exit: NOTHING; } finally { DebugUnwind( FatFastUnlockSingle ); // // Release the Fcb, and return to our caller // FsRtlExitFileSystem(); DebugTrace(-1, Dbg, "FatFastUnlockSingle -> %08lx\n", Results); } return Results; }
/* * @implemented */ NTSTATUS NTAPI FsRtlProcessFileLock(IN PFILE_LOCK FileLock, IN PIRP Irp, IN PVOID Context OPTIONAL) { PIO_STACK_LOCATION IoStackLocation; NTSTATUS Status; IO_STATUS_BLOCK IoStatusBlock; /* Get the I/O Stack location */ IoStackLocation = IoGetCurrentIrpStackLocation(Irp); ASSERT(IoStackLocation->MajorFunction == IRP_MJ_LOCK_CONTROL); /* Clear the I/O status block and check what function this is */ IoStatusBlock.Information = 0; switch(IoStackLocation->MinorFunction) { /* A lock */ case IRP_MN_LOCK: /* Call the private lock routine */ FsRtlPrivateLock(FileLock, IoStackLocation->FileObject, &IoStackLocation-> Parameters.LockControl.ByteOffset, IoStackLocation->Parameters.LockControl.Length, IoGetRequestorProcess(Irp), IoStackLocation->Parameters.LockControl.Key, IoStackLocation->Flags & SL_FAIL_IMMEDIATELY, IoStackLocation->Flags & SL_EXCLUSIVE_LOCK, &IoStatusBlock, Irp, Context, FALSE); break; /* A single unlock */ case IRP_MN_UNLOCK_SINGLE: /* Call fast unlock */ IoStatusBlock.Status = FsRtlFastUnlockSingle(FileLock, IoStackLocation->FileObject, &IoStackLocation->Parameters.LockControl. ByteOffset, IoStackLocation->Parameters.LockControl. Length, IoGetRequestorProcess(Irp), IoStackLocation->Parameters.LockControl. Key, Context, FALSE); /* Complete the IRP */ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatusBlock.Status, &Status, NULL); break; /* Total unlock */ case IRP_MN_UNLOCK_ALL: /* Do a fast unlock */ IoStatusBlock.Status = FsRtlFastUnlockAll(FileLock, IoStackLocation-> FileObject, IoGetRequestorProcess(Irp), Context); /* Complete the IRP */ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatusBlock.Status, &Status, NULL); break; /* Unlock by key */ case IRP_MN_UNLOCK_ALL_BY_KEY: /* Do it */ IoStatusBlock.Status = FsRtlFastUnlockAllByKey(FileLock, IoStackLocation->FileObject, IoGetRequestorProcess(Irp), IoStackLocation->Parameters. LockControl.Key, Context); /* Complete the IRP */ FsRtlCompleteLockIrpReal(FileLock->CompleteLockIrpRoutine, Context, Irp, IoStatusBlock.Status, &Status, NULL); break; /* Invalid request */ default: /* Complete it */ FsRtlCompleteRequest(Irp, STATUS_INVALID_DEVICE_REQUEST); IoStatusBlock.Status = STATUS_INVALID_DEVICE_REQUEST; break; } /* Return the status */ return IoStatusBlock.Status; }
BOOLEAN CdFastUnlockSingle ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock single call. Arguments: FileObject - Supplies the file object used in this operation FileOffset - Supplies the file offset used in this operation Length - Supplies the length used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation Status - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results = FALSE; TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PAGED_CODE(); IoStatus->Information = 0; // // Decode the type of file object we're being asked to process and // make sure that is is only a user file open. // TypeOfOpen = CdFastDecodeFileObject( FileObject, &Fcb ); if (TypeOfOpen != UserFileOpen) { IoStatus->Status = STATUS_INVALID_PARAMETER; return TRUE; } // // Only deal with 'good' Fcb's. // if (!CdVerifyFcbOperation( NULL, Fcb )) { return FALSE; } // // If there is no lock then return immediately. // if (Fcb->FileLock == NULL) { IoStatus->Status = STATUS_RANGE_NOT_LOCKED; return TRUE; } FsRtlEnterFileSystem(); try { // // We check whether we can proceed based on the state of the file oplocks. // if ((Fcb->Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Fcb->Oplock )) { try_return( NOTHING ); } // // If we don't have a file lock, then get one now. // if ((Fcb->FileLock == NULL) && !CdCreateFileLock( NULL, Fcb, FALSE )) { try_return( NOTHING ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request. The call will always succeed. // Results = TRUE; IoStatus->Status = FsRtlFastUnlockSingle( Fcb->FileLock, FileObject, FileOffset, Length, ProcessId, Key, NULL, FALSE ); // // Set the flag indicating if Fast I/O is possible. We are // only concerned if there are no longer any filelocks on this // file. // if (!FsRtlAreThereCurrentFileLocks( Fcb->FileLock ) && (Fcb->IsFastIoPossible != FastIoIsPossible)) { CdLockFcb( IrpContext, Fcb ); Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); CdUnlockFcb( IrpContext, Fcb ); } try_exit: NOTHING; } finally { FsRtlExitFileSystem(); } return Results; }
BOOLEAN NtfsFastUnlockSingle ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock single call. Arguments: FileObject - Supplies the file object used in this operation FileOffset - Supplies the file offset used in this operation Length - Supplies the length used in this operation ProcessId - Supplies the process ID used in this operation Key - Supplies the key used in this operation Status - Receives the Status if this operation is successful Return Value: BOOLEAN - TRUE if this operation completed and FALSE if caller needs to take the long route. --*/ { BOOLEAN Results; PFCB Fcb; PSCB Scb; BOOLEAN ResourceAcquired = FALSE; UNREFERENCED_PARAMETER( DeviceObject ); PAGED_CODE(); DebugTrace( +1, Dbg, ("NtfsFastUnlockSingle\n") ); IoStatus->Information = 0; // // Decode the type of file object we're being asked to process and // make sure that is is only a user file open. // if ((Scb = NtfsFastDecodeUserFileOpen( FileObject )) == NULL) { IoStatus->Status = STATUS_INVALID_PARAMETER; DebugTrace( -1, Dbg, ("NtfsFastUnlockSingle -> TRUE (STATUS_INVALID_PARAMETER)\n") ); return TRUE; } Fcb = Scb->Fcb; // // Acquire exclusive access to the Fcb this operation can always wait // FsRtlEnterFileSystem(); if (Scb->ScbType.Data.FileLock == NULL) { (VOID) ExAcquireResourceExclusive( Fcb->Resource, TRUE ); ResourceAcquired = TRUE; } else { //(VOID) ExAcquireResourceShared( Fcb->Resource, TRUE ); } try { // // We check whether we can proceed based on the state of the file oplocks. // if ((Scb->ScbType.Data.Oplock != NULL) && !FsRtlOplockIsFastIoPossible( &Scb->ScbType.Data.Oplock )) { try_return( Results = FALSE ); } // // If we don't have a file lock, then get one now. // if (Scb->ScbType.Data.FileLock == NULL && !NtfsCreateFileLock( Scb, FALSE )) { try_return( Results = FALSE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request. The call will always succeed. // Results = TRUE; IoStatus->Status = FsRtlFastUnlockSingle( Scb->ScbType.Data.FileLock, FileObject, FileOffset, Length, ProcessId, Key, NULL, FALSE ); // // Set the flag indicating if Fast I/O is possible. We are // only concerned if there are no longer any filelocks on this // file. // if (!FsRtlAreThereCurrentFileLocks( Scb->ScbType.Data.FileLock ) && (Scb->Header.IsFastIoPossible != FastIoIsPossible)) { NtfsAcquireFsrtlHeader( Scb ); Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb ); NtfsReleaseFsrtlHeader( Scb ); } try_exit: NOTHING; } finally { DebugUnwind( NtfsFastUnlockSingle ); // // Release the Fcb, and return to our caller // if (ResourceAcquired) { ExReleaseResource( Fcb->Resource ); } FsRtlExitFileSystem(); DebugTrace( -1, Dbg, ("NtfsFastUnlockSingle -> %08lx\n", Results) ); } return Results; }
BOOLEAN Ext2FastIoUnlockSingle ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN PEPROCESS Process, IN ULONG Key, OUT PIO_STATUS_BLOCK IoStatus, IN PDEVICE_OBJECT DeviceObject ) { BOOLEAN Status = FALSE; PEXT2_FCB Fcb; __try { FsRtlEnterFileSystem(); __try { if (IsExt2FsDevice(DeviceObject)) { IoStatus->Status = STATUS_INVALID_DEVICE_REQUEST; __leave; } Fcb = (PEXT2_FCB) FileObject->FsContext; if (Fcb == NULL || Fcb->Identifier.Type == EXT2VCB) { DbgBreak(); IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } ASSERT((Fcb->Identifier.Type == EXT2FCB) && (Fcb->Identifier.Size == sizeof(EXT2_FCB))); if (IsDirectory(Fcb)) { DbgBreak(); IoStatus->Status = STATUS_INVALID_PARAMETER; __leave; } #if EXT2_DEBUG DEBUG(DL_INF, ( "Ext2FastIoUnlockSingle: %s %s %wZ\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_UNLOCK_SINGLE", &Fcb->Mcb->FullName )); DEBUG(DL_INF, ( "Ext2FastIoUnlockSingle: Offset: %I64xh Length: %I64xh Key: %u\n", FileOffset->QuadPart, Length->QuadPart, Key )); #endif if (!FsRtlOplockIsFastIoPossible(&Fcb->Oplock)) { __leave; } IoStatus->Status = FsRtlFastUnlockSingle( &Fcb->FileLockAnchor, FileObject, FileOffset, Length, Process, Key, NULL, FALSE); IoStatus->Information = 0; Status = TRUE; Fcb->Header.IsFastIoPossible = Ext2IsFastIoPossible(Fcb); } __except (EXCEPTION_EXECUTE_HANDLER) { IoStatus->Status = GetExceptionCode(); } } __finally { FsRtlExitFileSystem(); } #if EXT2_DEBUG if (Status == FALSE) { DEBUG(DL_ERR, ( "Ext2FastIoUnlockSingle: %s %s *** Status: FALSE ***\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_UNLOCK_SINGLE" )); } else if (IoStatus->Status != STATUS_SUCCESS) { DEBUG(DL_ERR, ( "Ext2FastIoUnlockSingle: %s %s *** Status: %s (%#x) ***\n", (PUCHAR) Process + ProcessNameOffset, "FASTIO_UNLOCK_SINGLE", Ext2NtStatusToString(IoStatus->Status), IoStatus->Status )); } #endif return Status; }