Something went wrong. Try again.
Reactos
Something went wrong. Try again.
18 kB · 770 lines
C
at master
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771/*++
Copyright (c) 1989-2000 Microsoft Corporation
Module Name:
LockCtrl.c
Abstract:
This module implements the Lock Control routines for Fat called by the dispatch driver.
--*/
#include "fatprocs.h"
//// The local debug trace level//
#define Dbg (DEBUG_TRACE_LOCKCTRL)
#ifdef ALLOC_PRAGMA#pragma alloc_text(PAGE, FatCommonLockControl)#pragma alloc_text(PAGE, FatFastLock)#pragma alloc_text(PAGE, FatFastUnlockAll)#pragma alloc_text(PAGE, FatFastUnlockAllByKey)#pragma alloc_text(PAGE, FatFastUnlockSingle)#pragma alloc_text(PAGE, FatFsdLockControl)#endif
_Function_class_(IRP_MJ_LOCK_CONTROL)_Function_class_(DRIVER_DISPATCH)NTSTATUSNTAPIFatFsdLockControl ( _In_ PVOLUME_DEVICE_OBJECT VolumeDeviceObject, _Inout_ PIRP Irp )
/*++
Routine Description:
This routine implements the FSD part of Lock control operations
Arguments:
VolumeDeviceObject - Supplies the volume device object where the file exists
Irp - Supplies the Irp being processed
Return Value:
NTSTATUS - The FSD status for the IRP
--*/
{ NTSTATUS Status; PIRP_CONTEXT IrpContext = NULL;
BOOLEAN TopLevel;
PAGED_CODE();
DebugTrace(+1, Dbg, "FatFsdLockControl\n", 0);
// // Call the common Lock Control routine, with blocking allowed if // synchronous //
FsRtlEnterFileSystem();
TopLevel = FatIsIrpTopLevel( Irp );
_SEH2_TRY {
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
Status = FatCommonLockControl( IrpContext, Irp );
} _SEH2_EXCEPT(FatExceptionFilter( IrpContext, _SEH2_GetExceptionInformation() )) {
// // We had some trouble trying to perform the requested // operation, so we'll abort the I/O request with // the error status that we get back from the // execption code //
Status = FatProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() ); } _SEH2_END;
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
FsRtlExitFileSystem();
// // And return to our caller //
DebugTrace(-1, Dbg, "FatFsdLockControl -> %08lx\n", Status);
UNREFERENCED_PARAMETER( VolumeDeviceObject );
return Status;}
_Function_class_(FAST_IO_LOCK)BOOLEANNTAPIFatFastLock ( IN PFILE_OBJECT FileObject, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, PEPROCESS ProcessId, ULONG Key, BOOLEAN FailImmediately, 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; PVCB Vcb; PFCB Fcb; PCCB Ccb;
PAGED_CODE(); UNREFERENCED_PARAMETER( DeviceObject );
DebugTrace(+1, Dbg, "FatFastLock\n", 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; IoStatus->Information = 0;
DebugTrace(-1, Dbg, "FatFastLock -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; }
// // Acquire shared access to the Fcb //
FsRtlEnterFileSystem(); ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
_SEH2_TRY {
// // We check whether we can proceed // based on the state of the file oplocks. //
if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb) )) {
try_return( Results = FALSE ); }
// // Now call the FsRtl routine to do the actual processing of the // Lock request //
#ifdef _MSC_VER#pragma prefast( suppress:28159, "prefast indicates this API is obsolete but it is ok for fastfat to continue using it" )#endif Results = FsRtlFastLock( &Fcb->Specific.Fcb.FileLock, FileObject, FileOffset, Length, ProcessId, Key, FailImmediately, ExclusiveLock, IoStatus, NULL, FALSE );
if (Results) {
// // Set the flag indicating if Fast I/O is possible //
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb ); }
try_exit: NOTHING; } _SEH2_FINALLY {
DebugUnwind( FatFastLock );
// // Release the Fcb, and return to our caller //
ExReleaseResourceLite( Fcb->Header.Resource ); FsRtlExitFileSystem();
DebugTrace(-1, Dbg, "FatFastLock -> %08lx\n", Results); } _SEH2_END;
return Results;}
_Function_class_(FAST_IO_UNLOCK_SINGLE)BOOLEANNTAPIFatFastUnlockSingle ( 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; PVCB Vcb; PFCB Fcb; PCCB Ccb;
PAGED_CODE(); UNREFERENCED_PARAMETER( DeviceObject );
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();
_SEH2_TRY {
// // We check whether we can proceed based on the state of the file oplocks. //
if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb) )) {
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; } _SEH2_FINALLY {
DebugUnwind( FatFastUnlockSingle );
// // Release the Fcb, and return to our caller //
FsRtlExitFileSystem();
DebugTrace(-1, Dbg, "FatFastUnlockSingle -> %08lx\n", Results); } _SEH2_END;
return Results;}
_Function_class_(FAST_IO_UNLOCK_ALL)BOOLEANNTAPIFatFastUnlockAll ( IN PFILE_OBJECT FileObject, 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; PVCB Vcb; PFCB Fcb; PCCB Ccb;
PAGED_CODE(); UNREFERENCED_PARAMETER( DeviceObject );
DebugTrace(+1, Dbg, "FatFastUnlockAll\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, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; }
// // Acquire exclusive access to the Fcb this operation can always wait //
FsRtlEnterFileSystem();
(VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
_SEH2_TRY {
// // We check whether we can proceed based on the state of the file oplocks. //
if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb) )) {
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 = FsRtlFastUnlockAll( &Fcb->Specific.Fcb.FileLock, FileObject, ProcessId, NULL );
// // Set the flag indicating if Fast I/O is possible //
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
try_exit: NOTHING; } _SEH2_FINALLY {
DebugUnwind( FatFastUnlockAll );
// // Release the Fcb, and return to our caller //
ExReleaseResourceLite( (Fcb)->Header.Resource );
FsRtlExitFileSystem();
DebugTrace(-1, Dbg, "FatFastUnlockAll -> %08lx\n", Results); } _SEH2_END;
return Results;}
_Function_class_(FAST_IO_UNLOCK_ALL_BY_KEY)BOOLEANNTAPIFatFastUnlockAllByKey ( IN PFILE_OBJECT FileObject, PVOID 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 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; PVCB Vcb; PFCB Fcb; PCCB Ccb;
PAGED_CODE(); UNREFERENCED_PARAMETER( DeviceObject );
DebugTrace(+1, Dbg, "FatFastUnlockAllByKey\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, "FatFastUnlockAll -> TRUE (STATUS_INVALID_PARAMETER)\n", 0); return TRUE; }
// // Acquire exclusive access to the Fcb this operation can always wait //
FsRtlEnterFileSystem();
(VOID) ExAcquireResourceSharedLite( Fcb->Header.Resource, TRUE );
_SEH2_TRY {
// // We check whether we can proceed based on the state of the file oplocks. //
if (!FsRtlOplockIsFastIoPossible( FatGetFcbOplock(Fcb) )) {
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 = FsRtlFastUnlockAllByKey( &Fcb->Specific.Fcb.FileLock, FileObject, ProcessId, Key, NULL );
// // Set the flag indicating if Fast I/O is possible //
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
try_exit: NOTHING; } _SEH2_FINALLY {
DebugUnwind( FatFastUnlockAllByKey );
// // Release the Fcb, and return to our caller //
ExReleaseResourceLite( (Fcb)->Header.Resource );
FsRtlExitFileSystem();
DebugTrace(-1, Dbg, "FatFastUnlockAllByKey -> %08lx\n", Results); } _SEH2_END;
return Results;}
_Requires_lock_held_(_Global_critical_region_)NTSTATUSFatCommonLockControl ( IN PIRP_CONTEXT IrpContext, IN PIRP Irp )
/*++
Routine Description:
This is the common routine for doing Lock control operations 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 = STATUS_SUCCESS; PIO_STACK_LOCATION IrpSp;
TYPE_OF_OPEN TypeOfOpen;
PVCB Vcb; PFCB Fcb; PCCB Ccb;
BOOLEAN OplockPostIrp = FALSE;
PAGED_CODE();
// // Get a pointer to the current Irp stack location //
IrpSp = IoGetCurrentIrpStackLocation( Irp );
DebugTrace(+1, Dbg, "FatCommonLockControl\n", 0); DebugTrace( 0, Dbg, "Irp = %p\n", Irp); DebugTrace( 0, Dbg, "MinorFunction = %08lx\n", IrpSp->MinorFunction);
// // Decode the type of file object we're being asked to process //
TypeOfOpen = FatDecodeFileObject( IrpSp->FileObject, &Vcb, &Fcb, &Ccb );
// // If the file is not a user file open then we reject the request // as an invalid parameter //
if (TypeOfOpen != UserFileOpen) {
FatCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
DebugTrace(-1, Dbg, "FatCommonLockControl -> STATUS_INVALID_PARAMETER\n", 0); return STATUS_INVALID_PARAMETER; }
// // Acquire exclusive access to the Fcb and enqueue the Irp if we didn't // get access //
if (!FatAcquireSharedFcb( IrpContext, Fcb )) {
Status = FatFsdPostRequest( IrpContext, Irp );
DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status); return Status; }
_SEH2_TRY {
// // We check whether we can proceed // based on the state of the file oplocks. //
#if (NTDDI_VERSION >= NTDDI_WIN8)
if (((IRP_MN_LOCK == IrpSp->MinorFunction) && ((ULONGLONG)IrpSp->Parameters.LockControl.ByteOffset.QuadPart < (ULONGLONG)Fcb->Header.AllocationSize.QuadPart)) || ((IRP_MN_LOCK != IrpSp->MinorFunction) && FsRtlAreThereWaitingFileLocks( &Fcb->Specific.Fcb.FileLock ))) {
// // Check whether we can proceed based on the state of file oplocks if doing // an operation that interferes with oplocks. Those operations are: // // 1. Lock a range within the file's AllocationSize. // 2. Unlock a range when there are waiting locks on the file. This one // is not guaranteed to interfere with oplocks, but it could, as // unlocking this range might cause a waiting lock to be granted // within AllocationSize! //
#endif Status = FsRtlCheckOplock( FatGetFcbOplock(Fcb), Irp, IrpContext, FatOplockComplete, NULL );
#if (NTDDI_VERSION >= NTDDI_WIN8) }#endif
if (Status != STATUS_SUCCESS) {
OplockPostIrp = TRUE; try_return( NOTHING ); }
// // Now call the FsRtl routine to do the actual processing of the // Lock request //
Status = FsRtlProcessFileLock( &Fcb->Specific.Fcb.FileLock, Irp, NULL );
// // Set the flag indicating if Fast I/O is possible //
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
try_exit: NOTHING; } _SEH2_FINALLY {
DebugUnwind( FatCommonLockControl );
// // Only if this is not an abnormal termination do we delete the // irp context //
if (!_SEH2_AbnormalTermination() && !OplockPostIrp) {
FatCompleteRequest( IrpContext, FatNull, 0 ); }
// // Release the Fcb, and return to our caller //
FatReleaseFcb( IrpContext, Fcb );
DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status); } _SEH2_END;
return Status;}