mirror of
https://github.com/reactos/reactos.git
synced 2024-11-01 04:11:30 +00:00
566 lines
16 KiB
C++
566 lines
16 KiB
C++
////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
|
|
// All rights reserved
|
|
// This file was released under the GPLv2 on June 2015.
|
|
////////////////////////////////////////////////////////////////////
|
|
/*************************************************************************
|
|
*
|
|
* File: LockCtrl.cpp.cpp
|
|
*
|
|
* Module: UDF File System Driver (Kernel mode execution only)
|
|
*
|
|
* Description:
|
|
* Contains code to handle the "byte-range locking" dispatch entry point.
|
|
*
|
|
*************************************************************************/
|
|
|
|
#include "udffs.h"
|
|
|
|
// define the file specific bug-check id
|
|
#define UDF_BUG_CHECK_ID UDF_FILE_SHUTDOWN
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* Function: UDFLockControl()
|
|
*
|
|
* Description:
|
|
*
|
|
* Expected Interrupt Level (for execution) :
|
|
*
|
|
* IRQL_PASSIVE_LEVEL
|
|
*
|
|
* Return Value: Irrelevant.
|
|
*
|
|
*************************************************************************/
|
|
NTSTATUS
|
|
NTAPI
|
|
UDFLockControl(
|
|
IN PDEVICE_OBJECT DeviceObject, // the logical volume device object
|
|
IN PIRP Irp) // I/O Request Packet
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
PtrUDFIrpContext PtrIrpContext = NULL;
|
|
BOOLEAN AreWeTopLevel = FALSE;
|
|
|
|
UDFPrint(("UDFLockControl\n"));
|
|
// BrutePoint();
|
|
|
|
FsRtlEnterFileSystem();
|
|
ASSERT(DeviceObject);
|
|
ASSERT(Irp);
|
|
|
|
// set the top level context
|
|
AreWeTopLevel = UDFIsIrpTopLevel(Irp);
|
|
// Call the common Lock Control routine, with blocking allowed if
|
|
// synchronous
|
|
_SEH2_TRY {
|
|
|
|
// get an IRP context structure and issue the request
|
|
PtrIrpContext = UDFAllocateIrpContext(Irp, DeviceObject);
|
|
if(PtrIrpContext) {
|
|
RC = UDFCommonLockControl(PtrIrpContext, Irp);
|
|
} else {
|
|
RC = STATUS_INSUFFICIENT_RESOURCES;
|
|
Irp->IoStatus.Status = RC;
|
|
Irp->IoStatus.Information = 0;
|
|
// complete the IRP
|
|
IoCompleteRequest(Irp, IO_DISK_INCREMENT);
|
|
}
|
|
|
|
} _SEH2_EXCEPT(UDFExceptionFilter(PtrIrpContext, _SEH2_GetExceptionInformation())) {
|
|
|
|
RC = UDFExceptionHandler(PtrIrpContext, Irp);
|
|
|
|
UDFLogEvent(UDF_ERROR_INTERNAL_ERROR, RC);
|
|
} _SEH2_END;
|
|
|
|
if (AreWeTopLevel) {
|
|
IoSetTopLevelIrp(NULL);
|
|
}
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
return(RC);
|
|
} // end UDFLockControl()
|
|
|
|
|
|
/*************************************************************************
|
|
*
|
|
* Function: UDFCommonLockControl()
|
|
*
|
|
* Description:
|
|
* This is the common routine for doing Lock control operations called
|
|
* by both the fsd and fsp threads
|
|
*
|
|
* Expected Interrupt Level (for execution) :
|
|
*
|
|
* IRQL_PASSIVE_LEVEL
|
|
*
|
|
* Return Value: Irrelevant
|
|
*
|
|
*************************************************************************/
|
|
NTSTATUS
|
|
NTAPI
|
|
UDFCommonLockControl(
|
|
IN PtrUDFIrpContext PtrIrpContext,
|
|
IN PIRP Irp)
|
|
{
|
|
NTSTATUS RC = STATUS_SUCCESS;
|
|
PIO_STACK_LOCATION IrpSp = NULL;
|
|
//IO_STATUS_BLOCK LocalIoStatus;
|
|
// BOOLEAN CompleteRequest = FALSE;
|
|
BOOLEAN PostRequest = FALSE;
|
|
BOOLEAN CanWait = FALSE;
|
|
PtrUDFNTRequiredFCB NtReqFcb = NULL;
|
|
BOOLEAN AcquiredFCB = FALSE;
|
|
PFILE_OBJECT FileObject = NULL;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
|
|
UDFPrint(("UDFCommonLockControl\n"));
|
|
|
|
_SEH2_TRY {
|
|
// First, get a pointer to the current I/O stack location.
|
|
IrpSp = IoGetCurrentIrpStackLocation(Irp);
|
|
ASSERT(IrpSp);
|
|
|
|
FileObject = IrpSp->FileObject;
|
|
ASSERT(FileObject);
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
// Validate the sent-in FCB
|
|
if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
|
|
(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
|
|
|
|
// CompleteRequest = TRUE;
|
|
try_return(RC = STATUS_INVALID_PARAMETER);
|
|
}
|
|
|
|
NtReqFcb = Fcb->NTRequiredFCB;
|
|
CanWait = ((PtrIrpContext->IrpContextFlags & UDF_IRP_CONTEXT_CAN_BLOCK) ? TRUE : FALSE);
|
|
|
|
// Acquire the FCB resource shared
|
|
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
|
if (!UDFAcquireResourceExclusive(&(NtReqFcb->MainResource), CanWait)) {
|
|
PostRequest = TRUE;
|
|
try_return(RC = STATUS_PENDING);
|
|
}
|
|
AcquiredFCB = TRUE;
|
|
|
|
RC = FsRtlProcessFileLock(&(NtReqFcb->FileLock), Irp, NULL);
|
|
// CompleteRequest = TRUE;
|
|
|
|
try_exit: NOTHING;
|
|
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the FCB resources if acquired.
|
|
if (AcquiredFCB) {
|
|
UDF_CHECK_PAGING_IO_RESOURCE(NtReqFcb);
|
|
UDFReleaseResource(&(NtReqFcb->MainResource));
|
|
AcquiredFCB = FALSE;
|
|
}
|
|
if (PostRequest) {
|
|
// Perform appropriate post related processing here
|
|
RC = UDFPostRequest(PtrIrpContext, Irp);
|
|
} else
|
|
if(!_SEH2_AbnormalTermination()) {
|
|
// Simply free up the IrpContext since the IRP has been queued or
|
|
// Completed by FsRtlProcessFileLock
|
|
UDFReleaseIrpContext(PtrIrpContext);
|
|
}
|
|
} _SEH2_END; // end of "__finally" processing
|
|
|
|
return(RC);
|
|
} // end UDFCommonLockControl()
|
|
|
|
|
|
/*
|
|
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
|
|
NTAPI
|
|
UDFFastLock (
|
|
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
|
|
)
|
|
{
|
|
BOOLEAN Results = FALSE;
|
|
|
|
// BOOLEAN AcquiredFCB = FALSE;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
|
|
UDFPrint(("UDFFastLock\n"));
|
|
// Decode the type of file object we're being asked to process and make
|
|
// sure it is only a user file open.
|
|
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
// Validate the sent-in FCB
|
|
if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
|
|
(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
|
|
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
IoStatus->Information = 0;
|
|
return TRUE;
|
|
}
|
|
|
|
// Acquire exclusive access to the Fcb this operation can always wait
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
// BUGBUG: kenr
|
|
// (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE );
|
|
|
|
_SEH2_TRY {
|
|
|
|
// We check whether we can proceed
|
|
// based on the state of the file oplocks.
|
|
|
|
// Now call the FsRtl routine to do the actual processing of the
|
|
// Lock request
|
|
if ((Results = FsRtlFastLock( &(Fcb->NTRequiredFCB->FileLock),
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
FailImmediately,
|
|
ExclusiveLock,
|
|
IoStatus,
|
|
NULL,
|
|
FALSE ))) {
|
|
|
|
// Set the flag indicating if Fast I/O is possible
|
|
Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb);
|
|
}
|
|
|
|
//try_exit: NOTHING;
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the Fcb, and return to our caller
|
|
|
|
// BUGBUG: kenr
|
|
// UDFReleaseResource( (Fcb)->Header.Resource );
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
} _SEH2_END;
|
|
|
|
return Results;
|
|
} // end UDFFastLock()
|
|
|
|
|
|
/*
|
|
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
|
|
NTAPI
|
|
UDFFastUnlockSingle(
|
|
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
|
|
)
|
|
|
|
{
|
|
BOOLEAN Results = FALSE;
|
|
|
|
// BOOLEAN AcquiredFCB = FALSE;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
|
|
UDFPrint(("UDFFastUnlockSingle\n"));
|
|
// Decode the type of file object we're being asked to process and make
|
|
// sure it is only a user file open.
|
|
|
|
IoStatus->Information = 0;
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
// Validate the sent-in FCB
|
|
if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
|
|
(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
|
|
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return TRUE;
|
|
}
|
|
|
|
// Acquire exclusive access to the Fcb this operation can always wait
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
// BUGBUG: kenr
|
|
// (VOID) ExAcquireResourceShared( Fcb->Header.Resource, TRUE );
|
|
|
|
_SEH2_TRY {
|
|
|
|
// We check whether we can proceed
|
|
// based on the state of the file oplocks.
|
|
|
|
// Now call the FsRtl routine to do the actual processing of the
|
|
// Lock request
|
|
Results = TRUE;
|
|
IoStatus->Status = FsRtlFastUnlockSingle( &(Fcb->NTRequiredFCB->FileLock),
|
|
FileObject,
|
|
FileOffset,
|
|
Length,
|
|
ProcessId,
|
|
Key,
|
|
NULL,
|
|
FALSE );
|
|
// Set the flag indicating if Fast I/O is possible
|
|
Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible(Fcb);
|
|
|
|
//try_exit: NOTHING;
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the Fcb, and return to our caller
|
|
|
|
// BUGBUG: kenr
|
|
// UDFReleaseResource( (Fcb)->Header.Resource );
|
|
|
|
FsRtlExitFileSystem();
|
|
|
|
} _SEH2_END;
|
|
|
|
return Results;
|
|
} // end UDFFastUnlockSingle()
|
|
|
|
|
|
/*
|
|
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
|
|
NTAPI
|
|
UDFFastUnlockAll(
|
|
IN PFILE_OBJECT FileObject,
|
|
PEPROCESS ProcessId,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
|
|
{
|
|
BOOLEAN Results = FALSE;
|
|
|
|
// BOOLEAN AcquiredFCB = FALSE;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
|
|
UDFPrint(("UDFFastUnlockAll\n"));
|
|
|
|
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.
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
// Validate the sent-in FCB
|
|
if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
|
|
(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
|
|
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return TRUE;
|
|
}
|
|
|
|
// Acquire shared access to the Fcb this operation can always wait
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB);
|
|
UDFAcquireResourceShared( &(Fcb->NTRequiredFCB->MainResource),TRUE );
|
|
|
|
_SEH2_TRY {
|
|
|
|
// We check whether we can proceed
|
|
// based on the state of the file oplocks.
|
|
|
|
// Now call the FsRtl routine to do the actual processing of the
|
|
// Lock request
|
|
Results = TRUE;
|
|
IoStatus->Status = FsRtlFastUnlockAll( &(Fcb->NTRequiredFCB->FileLock),
|
|
FileObject,
|
|
ProcessId,
|
|
NULL );
|
|
|
|
// Set the flag indicating if Fast I/O is questionable
|
|
|
|
Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible( Fcb );
|
|
|
|
//try_exit: NOTHING;
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the Fcb, and return to our caller
|
|
|
|
UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB);
|
|
UDFReleaseResource(&(Fcb->NTRequiredFCB->MainResource));
|
|
FsRtlExitFileSystem();
|
|
|
|
} _SEH2_END;
|
|
|
|
return Results;
|
|
} // end UDFFastUnlockAll()
|
|
|
|
|
|
/*
|
|
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
|
|
NTAPI
|
|
UDFFastUnlockAllByKey(
|
|
IN PFILE_OBJECT FileObject,
|
|
PEPROCESS ProcessId,
|
|
ULONG Key,
|
|
OUT PIO_STATUS_BLOCK IoStatus,
|
|
IN PDEVICE_OBJECT DeviceObject
|
|
)
|
|
|
|
{
|
|
BOOLEAN Results = FALSE;
|
|
|
|
// BOOLEAN AcquiredFCB = FALSE;
|
|
PtrUDFFCB Fcb = NULL;
|
|
PtrUDFCCB Ccb = NULL;
|
|
|
|
UDFPrint(("UDFFastUnlockAllByKey\n"));
|
|
|
|
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.
|
|
|
|
// Get the FCB and CCB pointers.
|
|
Ccb = (PtrUDFCCB)(FileObject->FsContext2);
|
|
ASSERT(Ccb);
|
|
Fcb = Ccb->Fcb;
|
|
ASSERT(Fcb);
|
|
// Validate the sent-in FCB
|
|
if ( (Fcb->NodeIdentifier.NodeType == UDF_NODE_TYPE_VCB) ||
|
|
(Fcb->FCBFlags & UDF_FCB_DIRECTORY)) {
|
|
|
|
IoStatus->Status = STATUS_INVALID_PARAMETER;
|
|
return TRUE;
|
|
}
|
|
|
|
// Acquire shared access to the Fcb this operation can always wait
|
|
|
|
FsRtlEnterFileSystem();
|
|
|
|
UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB);
|
|
UDFAcquireResourceShared( &(Fcb->NTRequiredFCB->MainResource),TRUE );
|
|
|
|
_SEH2_TRY {
|
|
|
|
// We check whether we can proceed
|
|
// based on the state of the file oplocks.
|
|
|
|
// Now call the FsRtl routine to do the actual processing of the
|
|
// Lock request
|
|
Results = TRUE;
|
|
IoStatus->Status = FsRtlFastUnlockAllByKey( &(Fcb->NTRequiredFCB->FileLock),
|
|
FileObject,
|
|
ProcessId,
|
|
Key,
|
|
NULL );
|
|
|
|
// Set the flag indicating if Fast I/O is possible
|
|
|
|
Fcb->NTRequiredFCB->CommonFCBHeader.IsFastIoPossible = UDFIsFastIoPossible( Fcb );
|
|
|
|
//try_exit: NOTHING;
|
|
} _SEH2_FINALLY {
|
|
|
|
// Release the Fcb, and return to our caller
|
|
|
|
UDF_CHECK_PAGING_IO_RESOURCE(Fcb->NTRequiredFCB);
|
|
UDFReleaseResource(&(Fcb->NTRequiredFCB->MainResource));
|
|
FsRtlExitFileSystem();
|
|
|
|
} _SEH2_END;
|
|
|
|
return Results;
|
|
} // end UDFFastUnlockAllByKey()
|