You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
719 lines
17 KiB
719 lines
17 KiB
/*++
|
|
|
|
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.
|
|
|
|
// @@BEGIN_DDKSPLIT
|
|
|
|
Author:
|
|
|
|
Gary Kimura [GaryKi] 28-Dec-1989
|
|
|
|
Revision History:
|
|
|
|
// @@END_DDKSPLIT
|
|
|
|
--*/
|
|
|
|
#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
|
|
|
|
|
|
NTSTATUS
|
|
FatFsdLockControl (
|
|
IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject,
|
|
IN 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;
|
|
|
|
DebugTrace(+1, Dbg, "FatFsdLockControl\n", 0);
|
|
|
|
//
|
|
// Call the common Lock Control routine, with blocking allowed if
|
|
// synchronous
|
|
//
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
TopLevel = FatIsIrpTopLevel( Irp );
|
|
|
|
try {
|
|
|
|
IrpContext = FatCreateIrpContext( Irp, CanFsdWait( Irp ) );
|
|
|
|
Status = FatCommonLockControl( IrpContext, Irp );
|
|
|
|
} except(FatExceptionFilter( IrpContext, 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, GetExceptionCode() );
|
|
}
|
|
|
|
if (TopLevel) { IoSetTopLevelIrp( NULL ); }
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
//
|
|
// And return to our caller
|
|
//
|
|
|
|
DebugTrace(-1, Dbg, "FatFsdLockControl -> %08lx\n", Status);
|
|
|
|
UNREFERENCED_PARAMETER( VolumeDeviceObject );
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
FatFastLock (
|
|
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;
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PCCB Ccb;
|
|
|
|
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 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
|
|
//
|
|
|
|
if (Results = FsRtlFastLock( &Fcb->Specific.Fcb.FileLock,
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
FailImmediately,
|
|
ExclusiveLock,
|
|
IoStatus,
|
|
NULL,
|
|
FALSE )) {
|
|
|
|
//
|
|
// Set the flag indicating if Fast I/O is possible
|
|
//
|
|
|
|
Fcb->Header.IsFastIoPossible = FatIsFastIoPossible( Fcb );
|
|
}
|
|
|
|
try_exit: NOTHING;
|
|
} finally {
|
|
|
|
DebugUnwind( FatFastLock );
|
|
|
|
//
|
|
// Release the Fcb, and return to our caller
|
|
//
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
DebugTrace(-1, Dbg, "FatFastLock -> %08lx\n", Results);
|
|
}
|
|
|
|
return Results;
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
FatFastUnlockAll (
|
|
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;
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PCCB Ccb;
|
|
|
|
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 );
|
|
|
|
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 = 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;
|
|
} finally {
|
|
|
|
DebugUnwind( FatFastUnlockAll );
|
|
|
|
//
|
|
// Release the Fcb, and return to our caller
|
|
//
|
|
|
|
ExReleaseResourceLite( (Fcb)->Header.Resource );
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
DebugTrace(-1, Dbg, "FatFastUnlockAll -> %08lx\n", Results);
|
|
}
|
|
|
|
return Results;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
FatFastUnlockAllByKey (
|
|
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;
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PCCB Ccb;
|
|
|
|
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 );
|
|
|
|
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 = 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;
|
|
} finally {
|
|
|
|
DebugUnwind( FatFastUnlockAllByKey );
|
|
|
|
//
|
|
// Release the Fcb, and return to our caller
|
|
//
|
|
|
|
ExReleaseResourceLite( (Fcb)->Header.Resource );
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
DebugTrace(-1, Dbg, "FatFastUnlockAllByKey -> %08lx\n", Results);
|
|
}
|
|
|
|
return Results;
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
FatCommonLockControl (
|
|
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;
|
|
PIO_STACK_LOCATION IrpSp;
|
|
|
|
TYPE_OF_OPEN TypeOfOpen;
|
|
|
|
PVCB Vcb;
|
|
PFCB Fcb;
|
|
PCCB Ccb;
|
|
|
|
BOOLEAN OplockPostIrp = FALSE;
|
|
|
|
//
|
|
// Get a pointer to the current Irp stack location
|
|
//
|
|
|
|
IrpSp = IoGetCurrentIrpStackLocation( Irp );
|
|
|
|
DebugTrace(+1, Dbg, "FatCommonLockControl\n", 0);
|
|
DebugTrace( 0, Dbg, "Irp = %08lx\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;
|
|
}
|
|
|
|
try {
|
|
|
|
//
|
|
// We check whether we can proceed
|
|
// based on the state of the file oplocks.
|
|
//
|
|
|
|
Status = FsRtlCheckOplock( &Fcb->Specific.Fcb.Oplock,
|
|
Irp,
|
|
IrpContext,
|
|
FatOplockComplete,
|
|
NULL );
|
|
|
|
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;
|
|
} finally {
|
|
|
|
DebugUnwind( FatCommonLockControl );
|
|
|
|
//
|
|
// Only if this is not an abnormal termination do we delete the
|
|
// irp context
|
|
//
|
|
|
|
if (!AbnormalTermination() && !OplockPostIrp) {
|
|
|
|
FatCompleteRequest( IrpContext, FatNull, 0 );
|
|
}
|
|
|
|
//
|
|
// Release the Fcb, and return to our caller
|
|
//
|
|
|
|
FatReleaseFcb( IrpContext, Fcb );
|
|
|
|
DebugTrace(-1, Dbg, "FatCommonLockControl -> %08lx\n", Status);
|
|
}
|
|
|
|
return Status;
|
|
}
|