示例#1
0
文件: filelock.c 项目: RPG-7/reactos
/*
 * @implemented
 */
VOID
NTAPI
FsRtlUninitializeFileLock(IN PFILE_LOCK FileLock)
{
    if (FileLock->LockInformation)
    {
        PIRP Irp;
        PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
        PCOMBINED_LOCK_ELEMENT Entry;
        PLIST_ENTRY SharedEntry;
        PLOCK_SHARED_RANGE SharedRange;
        // MSDN: this completes any remaining lock IRPs
        for (SharedEntry = InternalInfo->SharedLocks.Flink;
             SharedEntry != &InternalInfo->SharedLocks;)
        {
            SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
            SharedEntry = SharedEntry->Flink;
            RemoveEntryList(&SharedRange->Entry);
            ExFreePoolWithTag(SharedRange, TAG_RANGE);
        }
        while ((Entry = RtlGetElementGenericTable(&InternalInfo->RangeTable, 0)) != NULL)
        {
            RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
        }
        while ((Irp = IoCsqRemoveNextIrp(&InternalInfo->Csq, NULL)) != NULL)
        {
            FsRtlProcessFileLock(FileLock, Irp, NULL);
        }
        ExFreePoolWithTag(InternalInfo, TAG_FLOCK);
        FileLock->LockInformation = NULL;
    }
}
示例#2
0
NTSTATUS FspFileNodeProcessLockIrp(FSP_FILE_NODE *FileNode, PIRP Irp)
{
    PAGED_CODE();

    IoMarkIrpPending(Irp);
    FspFileNodeSetOwnerF(FileNode, FspIrpFlags(Irp), Irp);

    try
    {
        FsRtlProcessFileLock(&FileNode->FileLock, Irp, FileNode);
    }
    except (EXCEPTION_EXECUTE_HANDLER)
    {
        Irp->IoStatus.Status = GetExceptionCode();
        Irp->IoStatus.Information = 0;

        FspFileNodeCompleteLockIrp(FileNode, Irp);
    }

    return STATUS_PENDING;
}
示例#3
0
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;
}
示例#4
0
NTSTATUS
CdCommonLockControl (
    IN PIRP_CONTEXT IrpContext,
    IN 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( &Fcb->Oplock,
                               Irp,
                               IrpContext,
                               CdOplockComplete,
                               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;
}
示例#5
0
NTSTATUS
XixFsdCommonLockControl(
	IN PXIFS_IRPCONTEXT pIrpContext
	)
{
	NTSTATUS			RC = STATUS_SUCCESS;
	PIRP					pIrp = NULL;
	PIO_STACK_LOCATION	pIrpSp = NULL;
	PFILE_OBJECT		pFileObject = NULL;
	PXIFS_FCB			pFCB = NULL;
	PXIFS_CCB			pCCB = NULL;
	PXIFS_VCB			pVCB = NULL;
	TYPE_OF_OPEN		TypeOfOpen = UnopenedFileObject;

	PAGED_CODE();

	DebugTrace(DEBUG_LEVEL_CRITICAL, DEBUG_TARGET_ALL, 
					("!!!!Enter XixFsdCommonLockControl \n"));

	DebugTrace(DEBUG_LEVEL_TRACE,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB),
		("Enter XixFsdCommonLockControl\n"));




	ASSERT(pIrpContext);

	pIrp = pIrpContext->Irp;
	ASSERT(pIrp);

	pIrpSp = IoGetCurrentIrpStackLocation(pIrp);
	ASSERT(pIrpSp);

	pFileObject = pIrpSp->FileObject;
	ASSERT(pFileObject);

	TypeOfOpen = XixFsdDecodeFileObject(pFileObject, &pFCB, &pCCB);

	ASSERT_FCB(pFCB);


	if(TypeOfOpen != UserFileOpen){
		RC = STATUS_INVALID_PARAMETER;
		XixFsdCompleteRequest(pIrpContext, RC, 0);
		return RC;
	}

	if(pFCB->FCBType != FCB_TYPE_FILE) 
	{
		RC = STATUS_INVALID_PARAMETER;
		XixFsdCompleteRequest(pIrpContext, RC, 0);
		return RC;
	}

	if(pFCB->HasLock != FCB_FILE_LOCK_HAS){
		RC = STATUS_ACCESS_DENIED;
		XixFsdCompleteRequest(pIrpContext, RC, 0);
		return RC;
	}

	
	pVCB = pFCB->PtrVCB;
	ASSERT_VCB(pVCB);

	DebugTrace(DEBUG_LEVEL_TRACE|DEBUG_LEVEL_ALL,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB),
		("CALL FsRtlCheckOplock : XixFsdCommonLockControl\n"));

	RC = FsRtlCheckOplock(&pFCB->FCBOplock,
						pIrp,
						pIrpContext,
						XixFsdOplockComplete,
						NULL);

	if(!NT_SUCCESS(RC)){
		DebugTrace(DEBUG_LEVEL_TRACE|DEBUG_LEVEL_ALL,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB),
			("return PENDING FsRtlCheckOplock : XixFsdCommonLockControl\n"));
		return RC;
	}

	if(!XixFsdVerifyFcbOperation(pIrpContext, pFCB)){
		RC = STATUS_INVALID_PARAMETER;
		XixFsdCompleteRequest(pIrpContext, RC, 0);
		return RC;
	}


	try{


		if(pFCB->FCBFileLock == NULL){
			pFCB->FCBFileLock = FsRtlAllocateFileLock(NULL, NULL);

			if(!pFCB->FCBFileLock){
				RC = STATUS_INSUFFICIENT_RESOURCES;
				try_return(RC);
			}
		}


		RC = FsRtlProcessFileLock(pFCB->FCBFileLock, pIrp, NULL);

		XifsdLockFcb(pIrpContext, pFCB);
		pFCB->IsFastIoPossible = XixFsdCheckFastIoPossible(pFCB);
		XifsdUnlockFcb(pIrpContext, pFCB);
	
	}finally{
	}
	
	XixFsdCompleteRequest(pIrpContext, RC, 0);

	DebugTrace(DEBUG_LEVEL_TRACE|DEBUG_LEVEL_ALL,(DEBUG_TARGET_FILEINFO|DEBUG_TARGET_FCB),
		("Exit XixFsdCommonLockControl\n"));
	
	return RC;
	
}
示例#6
0
NTSTATUS
NtfsCommonLockControl (
    IN PIRP_CONTEXT IrpContext,
    IN 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;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;
    BOOLEAN FcbAcquired = FALSE;

    BOOLEAN OplockPostIrp;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get a pointer to the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonLockControl\n") );
    DebugTrace( 0, Dbg, ("IrpContext    = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp           = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("MinorFunction = %08lx\n", IrpSp->MinorFunction) );

    //
    //  Extract and decode the type of file object we're being asked to process
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = NtfsDecodeFileObject( IrpContext, FileObject, &Vcb, &Fcb, &Scb, &Ccb, TRUE );

    //
    //  If the file is not a user file open then we reject the request
    //  as an invalid parameter
    //

    if (TypeOfOpen != UserFileOpen) {

        NtfsCompleteRequest( &IrpContext, &Irp, STATUS_INVALID_PARAMETER );

        DebugTrace( -1, Dbg, ("NtfsCommonLockControl -> STATUS_INVALID_PARAMETER\n") );
        return STATUS_INVALID_PARAMETER;
    }

    //
    //  Acquire exclusive access to the Fcb
    //

    if (Scb->ScbType.Data.FileLock == NULL) {

        NtfsAcquireExclusiveFcb( IrpContext, Fcb, Scb, FALSE, FALSE );
        FcbAcquired = TRUE;

    } else {

        //NtfsAcquireSharedFcb( IrpContext, Fcb, Scb );
    }

    OplockPostIrp = FALSE;

    try {

        //
        //  We check whether we can proceed based on the state of the file oplocks.
        //  This call might post the irp for us.
        //

        Status = FsRtlCheckOplock( &Scb->ScbType.Data.Oplock,
                                   Irp,
                                   IrpContext,
                                   NtfsOplockComplete,
                                   NULL );

        if (Status != STATUS_SUCCESS) {

            OplockPostIrp = TRUE;
            try_return( NOTHING );
        }

        //
        //  If we don't have a file lock, then get one now.
        //

        if (Scb->ScbType.Data.FileLock == NULL) {

            NtfsCreateFileLock( Scb, TRUE );
        }

        //
        //  Now call the FsRtl routine to do the actual processing of the
        //  Lock request
        //

        Status = FsRtlProcessFileLock( Scb->ScbType.Data.FileLock, Irp, NULL );

        //
        //  Set the flag indicating if Fast I/O is possible
        //

        NtfsAcquireFsrtlHeader( Scb );
        Scb->Header.IsFastIoPossible = NtfsIsFastIoPossible( Scb );
        NtfsReleaseFsrtlHeader( Scb );

    try_exit: NOTHING;
    } finally {

        DebugUnwind( NtfsCommonLockControl );

        //
        //  Release the Fcb, and return to our caller
        //

        if (FcbAcquired) {
            NtfsReleaseFcb( IrpContext, Fcb );
        }

        //
        //  Only if this is not an abnormal termination and we did not post the irp
        //  do we delete the irp context
        //

        if (!AbnormalTermination() && !OplockPostIrp) {

            NtfsCompleteRequest( &IrpContext, NULL, 0 );
        }

        DebugTrace( -1, Dbg, ("NtfsCommonLockControl -> %08lx\n", Status) );
    }

    return Status;
}
示例#7
0
文件: lockctrl.c 项目: Realhram/wdk81
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 = 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           = %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.
        //

#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;
    } 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;
}
示例#8
0
NTSTATUS
NTAPI
FatiLockControl(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
    PIO_STACK_LOCATION IrpSp;
    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;
    NTSTATUS Status;

    /* Get IRP stack location */
    IrpSp = IoGetCurrentIrpStackLocation(Irp);

    /* Determine type of open */
    TypeOfOpen = FatDecodeFileObject(IrpSp->FileObject, &Vcb, &Fcb, &Ccb);

    /* Only user file open is allowed */
    if (TypeOfOpen != UserFileOpen)
    {
        FatCompleteRequest(IrpContext, Irp, STATUS_INVALID_PARAMETER);
        return STATUS_INVALID_PARAMETER;
    }

    /* Acquire shared FCB lock */
    if (!FatAcquireSharedFcb(IrpContext, Fcb))
    {
        UNIMPLEMENTED;
        //Status = FatFsdPostRequest(IrpContext, Irp);
        Status = STATUS_NOT_IMPLEMENTED;
        return Status;
    }

    /* Check oplock state */
    Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
                              Irp,
                              IrpContext,
                              FatOplockComplete,
                              NULL);

    if (Status != STATUS_SUCCESS)
    {
        /* Release FCB lock */
        FatReleaseFcb(IrpContext, Fcb);

        return Status;
    }

    /* Process the lock */
    Status = FsRtlProcessFileLock(&Fcb->Fcb.Lock, Irp, NULL);

    /* Update Fast I/O state */
    Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);

    /* Complete the request */
    FatCompleteRequest(IrpContext, NULL, 0);

    /* Release FCB lock */
    FatReleaseFcb(IrpContext, Fcb);

    return Status;
}
示例#9
0
文件: filelock.c 项目: RPG-7/reactos
/*
 * @implemented
 */
NTSTATUS
NTAPI
FsRtlFastUnlockSingle(IN PFILE_LOCK FileLock,
                      IN PFILE_OBJECT FileObject,
                      IN PLARGE_INTEGER FileOffset,
                      IN PLARGE_INTEGER Length,
                      IN PEPROCESS Process,
                      IN ULONG Key,
                      IN PVOID Context OPTIONAL,
                      IN BOOLEAN AlreadySynchronized)
{
    BOOLEAN FoundShared = FALSE;
    PLIST_ENTRY SharedEntry;
    PLOCK_SHARED_RANGE SharedRange = NULL;
    COMBINED_LOCK_ELEMENT Find;
    PCOMBINED_LOCK_ELEMENT Entry;
    PIRP NextMatchingLockIrp;
    PLOCK_INFORMATION InternalInfo = FileLock->LockInformation;
    DPRINT("FsRtlFastUnlockSingle(%wZ, Offset %08x%08x (%d), Length %08x%08x (%d), Key %x)\n", 
           &FileObject->FileName, 
           FileOffset->HighPart,
           FileOffset->LowPart, 
           (int)FileOffset->QuadPart,
           Length->HighPart,
           Length->LowPart,
           (int)Length->QuadPart,
           Key);
    // The region to unlock must correspond exactly to a previously locked region
    // -- msdn
    // But Windows 2003 doesn't assert on it and simply ignores that parameter
    // ASSERT(AlreadySynchronized);
    Find.Exclusive.FileLock.StartingByte = *FileOffset;
    Find.Exclusive.FileLock.EndingByte.QuadPart = 
        FileOffset->QuadPart + Length->QuadPart;
    if (!InternalInfo) {
        DPRINT("File not previously locked (ever)\n");
        return STATUS_RANGE_NOT_LOCKED;
    }
    Entry = RtlLookupElementGenericTable(&InternalInfo->RangeTable, &Find);
    if (!Entry) {
        DPRINT("Range not locked %wZ\n", &FileObject->FileName);
        return STATUS_RANGE_NOT_LOCKED;
    }

    DPRINT("Found lock entry: Exclusive %u %08x%08x:%08x%08x %wZ\n",
           Entry->Exclusive.FileLock.ExclusiveLock,
           Entry->Exclusive.FileLock.StartingByte.HighPart,
           Entry->Exclusive.FileLock.StartingByte.LowPart,
           Entry->Exclusive.FileLock.EndingByte.HighPart,
           Entry->Exclusive.FileLock.EndingByte.LowPart,
           &FileObject->FileName);
    
    if (Entry->Exclusive.FileLock.ExclusiveLock)
    {
        if (Entry->Exclusive.FileLock.Key != Key ||
            Entry->Exclusive.FileLock.ProcessId != Process->UniqueProcessId ||
            Entry->Exclusive.FileLock.StartingByte.QuadPart != FileOffset->QuadPart ||
            Entry->Exclusive.FileLock.EndingByte.QuadPart != 
            FileOffset->QuadPart + Length->QuadPart)
        {
            DPRINT("Range not locked %wZ\n", &FileObject->FileName);
            return STATUS_RANGE_NOT_LOCKED;
        }
        RtlCopyMemory(&Find, Entry, sizeof(Find));
        // Remove the old exclusive lock region
        RtlDeleteElementGenericTable(&InternalInfo->RangeTable, Entry);
    }
    else
    {
        DPRINT("Shared lock %wZ Start %08x%08x End %08x%08x\n", 
               &FileObject->FileName,
               Entry->Exclusive.FileLock.StartingByte.HighPart,
               Entry->Exclusive.FileLock.StartingByte.LowPart,
               Entry->Exclusive.FileLock.EndingByte.HighPart,
               Entry->Exclusive.FileLock.EndingByte.LowPart);
        for (SharedEntry = InternalInfo->SharedLocks.Flink;
             SharedEntry != &InternalInfo->SharedLocks;
             SharedEntry = SharedEntry->Flink)
        {
            SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
            if (SharedRange->Start.QuadPart == FileOffset->QuadPart &&
                SharedRange->End.QuadPart == FileOffset->QuadPart + Length->QuadPart &&
                SharedRange->Key == Key &&
                SharedRange->ProcessId == Process->UniqueProcessId)
            {
                FoundShared = TRUE;
                DPRINT("Found shared element to delete %wZ Start %08x%08x End %08x%08x Key %x\n",
                       &FileObject->FileName,
                       SharedRange->Start.HighPart,
                       SharedRange->Start.LowPart,
                       SharedRange->End.HighPart,
                       SharedRange->End.LowPart,
                       SharedRange->Key);
                break;
            }
        }
        if (FoundShared)
        {
            /* Remove the found range from the shared range lists */
            RemoveEntryList(&SharedRange->Entry);
            ExFreePoolWithTag(SharedRange, TAG_RANGE);
            /* We need to rebuild the list of shared ranges. */
            DPRINT("Removing the lock entry %wZ (%08x%08x:%08x%08x)\n", 
                   &FileObject->FileName, 
                   Entry->Exclusive.FileLock.StartingByte.HighPart, 
                   Entry->Exclusive.FileLock.StartingByte.LowPart,
                   Entry->Exclusive.FileLock.EndingByte.HighPart, 
                   Entry->Exclusive.FileLock.EndingByte.LowPart);
               
            /* Remember what was in there and remove it from the table */
            Find = *Entry;
            RtlDeleteElementGenericTable(&InternalInfo->RangeTable, &Find);
            /* Put shared locks back in place */
            for (SharedEntry = InternalInfo->SharedLocks.Flink;
                 SharedEntry != &InternalInfo->SharedLocks;
                 SharedEntry = SharedEntry->Flink)
            {
                COMBINED_LOCK_ELEMENT LockElement;
                SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
                LockElement.Exclusive.FileLock.FileObject = FileObject;
                LockElement.Exclusive.FileLock.StartingByte = SharedRange->Start;
                LockElement.Exclusive.FileLock.EndingByte = SharedRange->End;
                LockElement.Exclusive.FileLock.ProcessId = SharedRange->ProcessId;
                LockElement.Exclusive.FileLock.Key = SharedRange->Key;
                LockElement.Exclusive.FileLock.ExclusiveLock = FALSE;
                
                if (LockCompare(&InternalInfo->RangeTable, &Find, &LockElement) != GenericEqual)
                {
                    DPRINT("Skipping range %08x%08x:%08x%08x\n",
                           LockElement.Exclusive.FileLock.StartingByte.HighPart,
                           LockElement.Exclusive.FileLock.StartingByte.LowPart,
                           LockElement.Exclusive.FileLock.EndingByte.HighPart,
                           LockElement.Exclusive.FileLock.EndingByte.LowPart);
                    continue;
                }
                DPRINT("Re-creating range %08x%08x:%08x%08x\n",
                       LockElement.Exclusive.FileLock.StartingByte.HighPart,
                       LockElement.Exclusive.FileLock.StartingByte.LowPart,
                       LockElement.Exclusive.FileLock.EndingByte.HighPart,
                       LockElement.Exclusive.FileLock.EndingByte.LowPart);
                FsRtlpRebuildSharedLockRange(FileLock, InternalInfo, &LockElement);
            }
        }
        else
        {
            return STATUS_RANGE_NOT_LOCKED;
        }
    }

#ifndef NDEBUG    
    DPRINT("Lock still has:\n");
    for (SharedEntry = InternalInfo->SharedLocks.Flink;
         SharedEntry != &InternalInfo->SharedLocks;
         SharedEntry = SharedEntry->Flink)
    {
        SharedRange = CONTAINING_RECORD(SharedEntry, LOCK_SHARED_RANGE, Entry);
        DPRINT("Shared element %wZ Offset %08x%08x Length %08x%08x Key %x\n",
               &FileObject->FileName,
               SharedRange->Start.HighPart,
               SharedRange->Start.LowPart,
               SharedRange->End.HighPart,
               SharedRange->End.LowPart,
               SharedRange->Key);
    }
#endif
    
    // this is definitely the thing we want
    InternalInfo->Generation++;
    while ((NextMatchingLockIrp = IoCsqRemoveNextIrp(&InternalInfo->Csq, &Find)))
    {
        if (NextMatchingLockIrp->IoStatus.Information == InternalInfo->Generation)
        {
            // We've already looked at this one, meaning that we looped.  
            // Put it back and exit.
            IoCsqInsertIrpEx
                (&InternalInfo->Csq,
                 NextMatchingLockIrp,
                 NULL,
                 NULL);
            break;
        }
        // Got a new lock irp... try to do the new lock operation
        // Note that we pick an operation that would succeed at the time
        // we looked, but can't guarantee that it won't just be re-queued
        // because somebody else snatched part of the range in a new thread.
        DPRINT("Locking another IRP %p for %p %wZ\n", 
               &FileObject->FileName, FileLock, NextMatchingLockIrp);
        FsRtlProcessFileLock(InternalInfo->BelongsTo, NextMatchingLockIrp, NULL);
    }
    
    DPRINT("Success %wZ\n", &FileObject->FileName);
    return STATUS_SUCCESS;
}
示例#10
0
文件: lock.c 项目: x1596357/dokany
NTSTATUS
DokanCommonLockControl(__in PIRP Irp) {
  NTSTATUS Status = STATUS_SUCCESS;

  PDokanFCB Fcb;
  PDokanCCB Ccb;
  PFILE_OBJECT fileObject;

  PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);

  DDbgPrint("==> DokanCommonLockControl\n");

  PAGED_CODE();

  fileObject = irpSp->FileObject;
  DokanPrintFileName(fileObject);

  Ccb = fileObject->FsContext2;
  if (Ccb == NULL || Ccb->Identifier.Type != CCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }

  Fcb = Ccb->Fcb;
  if (Fcb == NULL || Fcb->Identifier.Type != FCB) {
    DDbgPrint("    DokanOplockRequest STATUS_INVALID_PARAMETER\n");
    return STATUS_INVALID_PARAMETER;
  }
  DokanFCBLockRW(Fcb);

  //
  //  If the file is not a user file open then we reject the request
  //  as an invalid parameter
  //
  if (FlagOn(Fcb->Flags, DOKAN_FILE_DIRECTORY)) {
    DDbgPrint("  DokanCommonLockControl -> STATUS_INVALID_PARAMETER\n", 0);
    DokanFCBUnlock(Fcb);
    return STATUS_INVALID_PARAMETER;
  }

  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->AdvancedFCBHeader.AllocationSize.QuadPart)) ||
        ((IRP_MN_LOCK != irpSp->MinorFunction) &&
         FsRtlAreThereWaitingFileLocks(&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
      // Dokan DokanOplockComplete sends the operation to user mode, which isn't
      // what we want to do
      // so now wait for the oplock to be broken (pass in NULL for the callback)
      Status =
          FsRtlCheckOplock(DokanGetFcbOplock(Fcb), Irp, NULL /* EventContext */,
                           NULL /*DokanOplockComplete*/, NULL);

#if (NTDDI_VERSION >= NTDDI_WIN8)
    }
#endif
    //  If we were waiting for the callback, then STATUS_PENDING would be ok too
    if (Status != STATUS_SUCCESS) {
      __leave;
    }

    //
    //  Now call the FsRtl routine to do the actual processing of the
    //  Lock request
    //
    Status = FsRtlProcessFileLock(&Fcb->FileLock, Irp, NULL);
  } finally {
    DokanFCBUnlock(Fcb);
  }

  DDbgPrint("<== DokanCommonLockControl\n");

  return Status;
}