/*++ Copyright (c) 1989-2000 Microsoft Corporation Module Name: LockCtrl.c Abstract: This module implements the Lock Control routines for Cdfs called by the Fsd/Fsp dispatch driver. --*/ #include "cdprocs.h" // // The Bug check file id for this module // #define BugCheckFileId (CDFS_BUG_CHECK_LOCKCTRL) #ifdef ALLOC_PRAGMA #pragma alloc_text(PAGE, CdCommonLockControl) #pragma alloc_text(PAGE, CdFastLock) #pragma alloc_text(PAGE, CdFastUnlockAll) #pragma alloc_text(PAGE, CdFastUnlockAllByKey) #pragma alloc_text(PAGE, CdFastUnlockSingle) #endif NTSTATUS CdCommonLockControl ( _Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp ) /*++ Routine Description: This is the common routine for Lock Control called by both the fsd and fsp threads. Arguments: Irp - Supplies the Irp to process Return Value: NTSTATUS - The return status for the operation --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp ); TYPE_OF_OPEN TypeOfOpen; PFCB Fcb; PCCB Ccb; PAGED_CODE(); // // Extract and decode the type of file object we're being asked to process // TypeOfOpen = CdDecodeFileObject( IrpContext, IrpSp->FileObject, &Fcb, &Ccb ); // // If the file is not a user file open then we reject the request // as an invalid parameter // if (TypeOfOpen != UserFileOpen) { CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER ); return STATUS_INVALID_PARAMETER; } // // We check whether we can proceed based on the state of the file oplocks. // This call might post the irp for us. // Status = FsRtlCheckOplock( CdGetFcbOplock(Fcb), Irp, IrpContext, (PVOID)CdOplockComplete,/* ReactOS Change: GCC "assignment from incompatible pointer type" */ NULL ); // // If we don't get success then the oplock package completed the request. // if (Status != STATUS_SUCCESS) { return Status; } // // Verify the Fcb. // CdVerifyFcbOperation( IrpContext, Fcb ); // // If we don't have a file lock, then get one now. // if (Fcb->FileLock == NULL) { CdCreateFileLock( IrpContext, Fcb, TRUE ); } // // Now call the FsRtl routine to do the actual processing of the // Lock request // Status = FsRtlProcessFileLock( Fcb->FileLock, Irp, NULL ); // // Set the flag indicating if Fast I/O is possible // CdLockFcb( IrpContext, Fcb ); Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); CdUnlockFcb( IrpContext, Fcb ); // // Complete the request. // CdCompleteRequest( IrpContext, NULL, Status ); return Status; } BOOLEAN NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ CdFastLock ( _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER FileOffset, _In_ PLARGE_INTEGER Length, _In_ PEPROCESS ProcessId, _In_ ULONG Key, _In_ BOOLEAN FailImmediately, _In_ BOOLEAN ExclusiveLock, _Out_ PIO_STATUS_BLOCK IoStatus, _In_ PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast lock 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 FailImmediately - Indicates if the request should fail immediately if the lock cannot be granted. ExclusiveLock - Indicates if this is a request for an exclusive or shared lock IoStatus - 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; PFCB Fcb; TYPE_OF_OPEN TypeOfOpen; PAGED_CODE(); UNREFERENCED_PARAMETER( DeviceObject ); ASSERT_FILE_OBJECT( FileObject ); 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; } FsRtlEnterFileSystem(); // // Use a try-finally to facilitate cleanup. // _SEH2_TRY { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 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 perform the lock request. // #ifdef _MSC_VER #pragma prefast(suppress: 28159, "prefast thinks this is an obsolete routine, but it is ok for CDFS to use it") #endif if ((Results = FsRtlFastLock( Fcb->FileLock, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, NULL, FALSE )) != FALSE) { // // Set the flag indicating if Fast I/O is questionable. We // only change this flag if the current state is possible. // Retest again after synchronizing on the header. // if (Fcb->IsFastIoPossible == FastIoIsPossible) { CdLockFcb( NULL, Fcb ); Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); CdUnlockFcb( NULL, Fcb ); } } try_exit: NOTHING; } _SEH2_FINALLY { FsRtlExitFileSystem(); } _SEH2_END; return Results; } BOOLEAN NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ CdFastUnlockSingle ( _In_ PFILE_OBJECT FileObject, _In_ PLARGE_INTEGER FileOffset, _In_ PLARGE_INTEGER Length, _In_ PEPROCESS ProcessId, _In_ 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(); UNREFERENCED_PARAMETER( DeviceObject ); 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(); _SEH2_TRY { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 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; } _SEH2_FINALLY { FsRtlExitFileSystem(); } _SEH2_END; return Results; } BOOLEAN NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ CdFastUnlockAll ( _In_ PFILE_OBJECT FileObject, _In_ PEPROCESS ProcessId, _Out_ PIO_STATUS_BLOCK IoStatus, _In_ PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock all call. Arguments: FileObject - Supplies the file object used in this operation ProcessId - Supplies the process ID 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(); UNREFERENCED_PARAMETER( DeviceObject ); 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(); _SEH2_TRY { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 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 = FsRtlFastUnlockAll( Fcb->FileLock, FileObject, ProcessId, NULL ); // // Set the flag indicating if Fast I/O is possible // CdLockFcb( IrpContext, Fcb ); Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); CdUnlockFcb( IrpContext, Fcb ); try_exit: NOTHING; } _SEH2_FINALLY { FsRtlExitFileSystem(); } _SEH2_END; return Results; } BOOLEAN NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */ CdFastUnlockAllByKey ( _In_ PFILE_OBJECT FileObject, _In_ PVOID ProcessId, _In_ ULONG Key, _Out_ PIO_STATUS_BLOCK IoStatus, _In_ PDEVICE_OBJECT DeviceObject ) /*++ Routine Description: This is a call back routine for doing the fast unlock all by key call. Arguments: FileObject - Supplies the file object 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(); UNREFERENCED_PARAMETER( DeviceObject ); 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(); _SEH2_TRY { // // We check whether we can proceed based on the state of the file oplocks. // if (!FsRtlOplockIsFastIoPossible( CdGetFcbOplock(Fcb) )) { 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 = FsRtlFastUnlockAllByKey( Fcb->FileLock, FileObject, ProcessId, Key, NULL ); // // Set the flag indicating if Fast I/O is possible // CdLockFcb( IrpContext, Fcb ); Fcb->IsFastIoPossible = CdIsFastIoPossible( Fcb ); CdUnlockFcb( IrpContext, Fcb ); try_exit: NOTHING; } _SEH2_FINALLY { FsRtlExitFileSystem(); } _SEH2_END; return Results; }