Exemplo n.º 1
0
BOOLEAN
NTAPI
FatAcquireSharedFcb(IN PFAT_IRP_CONTEXT IrpContext,
                    IN PFCB Fcb)
{
RetryLockingS:
    /* Try to acquire the shared lock*/
    if (ExAcquireResourceSharedLite(Fcb->Header.Resource,
        BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_CANWAIT)))
    {
        /* Wait same way MS's FASTFAT wait, i.e.
           checking that there are outstanding async writes,
           or someone is waiting on it*/
        if (Fcb->OutstandingAsyncWrites &&
            ((IrpContext->MajorFunction != IRP_MJ_WRITE) ||
             !FlagOn(IrpContext->Irp->Flags, IRP_NOCACHE) ||
             ExGetSharedWaiterCount(Fcb->Header.Resource) ||
             ExGetExclusiveWaiterCount(Fcb->Header.Resource)))
        {
            KeWaitForSingleObject(Fcb->OutstandingAsyncEvent,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);

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

            /* Retry */
            goto RetryLockingS;
        }

        /* Return success */
        return TRUE;
    }

    /* Return failure */
    return FALSE;
}
Exemplo n.º 2
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;
}
Exemplo n.º 3
0
NTSTATUS
NdFatCommonFlushBuffers (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for flushing a buffer.

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;
    PCCB Ccb;

    BOOLEAN VcbAcquired = FALSE;
    BOOLEAN FcbAcquired = FALSE;

    PDIRENT Dirent;
    PBCB DirentBcb = NULL;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;

	PSECONDARY_REQUEST			secondaryRequest = NULL;

	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;



    PAGED_CODE();

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

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

	
	//
    //  Extract and decode the file object
    //

    FileObject = IrpSp->FileObject;
    TypeOfOpen = FatDecodeFileObject( FileObject, &Vcb, &Fcb, &Ccb );

    //
    //  CcFlushCache is always synchronous, so if we can't wait enqueue
    //  the irp to the Fsp.
    //

    if ( !FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ) {

        Status = FatFsdPostRequest( IrpContext, Irp );

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

    Status = STATUS_SUCCESS;

    try {

		if (!FlagOn(Ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

			do {
			
				secondarySessionResourceAcquired 
					= SecondaryAcquireResourceExclusiveLite( IrpContext, 
															 &volDo->Secondary->SessionResource, 
															 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

				if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

					PrintIrp( Dbg2, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );
					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );	
				}

				secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, IRP_MJ_FLUSH_BUFFERS, 0 );

				if (secondaryRequest == NULL) {
	
					Status = STATUS_INSUFFICIENT_RESOURCES;
					break;
				}

				ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;

				INITIALIZE_NDFS_REQUEST_HEADER( ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_FLUSH_BUFFERS, 0 );

				ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
				ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

				INITIALIZE_NDFS_WINXP_REQUEST_HEADER( ndfsWinxpRequestHeader, 
													  IrpContext->OriginatingIrp, 
													  IoGetCurrentIrpStackLocation(IrpContext->OriginatingIrp), 
													  Ccb->PrimaryFileHandle );
				
				ASSERT( !ExIsResourceAcquiredSharedLite(&IrpContext->Vcb->Resource) );	

				secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
				QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

				timeOut.QuadPart = -NDFAT_TIME_OUT;		
				Status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
			
				if (Status != STATUS_SUCCESS) {

					ASSERT( NDFAT_BUG );
					break;
				}

				KeClearEvent (&secondaryRequest->CompleteEvent);

				if (BooleanFlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED)) {

					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}

				if (secondaryRequest->ExecuteStatus == STATUS_SUCCESS) {

					ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
					ASSERT(ndfsWinxpReplytHeader->Status == STATUS_SUCCESS);
				}

				if (secondaryRequest) {

					DereferenceSecondaryRequest( secondaryRequest );
					secondaryRequest = NULL;
				}

				if ( secondarySessionResourceAcquired == TRUE ) {
					
					SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );		
					secondarySessionResourceAcquired = FALSE;
				}

				break;

			} while(0);
		} 

		Status = STATUS_SUCCESS;

        //
        //  Case on the type of open that we are trying to flush
        //

        switch (TypeOfOpen) {

        case VirtualVolumeFile:
        case EaFile:
        case DirectoryFile:

            DebugTrace(0, Dbg, "Flush that does nothing\n", 0);
            break;

        case UserFileOpen:

            DebugTrace(0, Dbg, "Flush User File Open\n", 0);

            (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );

            FcbAcquired = TRUE;

            FatVerifyFcb( IrpContext, Fcb );

            //
            //  If the file is cached then flush its cache
            //

            Status = FatFlushFile( IrpContext, Fcb, Flush );

            //
            //  Also update and flush the file's dirent in the parent directory if the
            //  file flush worked.
            //

            if (NT_SUCCESS( Status )) {

                //
                //  Insure that we get the filesize to disk correctly.  This is
                //  benign if it was already good.
                //
                //  (why do we need to do this?)
                //

                SetFlag(FileObject->Flags, FO_FILE_SIZE_CHANGED);
#if 0
                FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
#endif                
                //
                //  Flush the volume file to get any allocation information
                //  updates to disk.
                //

                if (FlagOn(Fcb->FcbState, FCB_STATE_FLUSH_FAT)) {

                    Status = FatFlushFat( IrpContext, Vcb );

                    ClearFlag(Fcb->FcbState, FCB_STATE_FLUSH_FAT);
                }

                //
                //  Set the write through bit so that these modifications
                //  will be completed with the request.
                //

                SetFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH);
            }

            break;

        case UserDirectoryOpen:

            //
            //  If the user had opened the root directory then we'll
            //  oblige by flushing the volume.
            //

            if (NodeType(Fcb) != FAT_NTC_ROOT_DCB) {

                DebugTrace(0, Dbg, "Flush a directory does nothing\n", 0);
                break;
            }

        case UserVolumeOpen:

            DebugTrace(0, Dbg, "Flush User Volume Open, or root dcb\n", 0);

            //
            //  Acquire exclusive access to the Vcb.
            //

            {
                BOOLEAN Finished;
                Finished = FatAcquireExclusiveSecondaryVcb( IrpContext, Vcb );
                ASSERT( Finished );
            }

            VcbAcquired = TRUE;

            //
            //  Mark the volume clean and then flush the volume file,
            //  and then all directories
            //

            Status = FatFlushVolume( IrpContext, Vcb, Flush );

            //
            //  If the volume was dirty, do the processing that the delayed
            //  callback would have done.
            //

            if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY)) {

                //
                //  Cancel any pending clean volumes.
                //

                (VOID)KeCancelTimer( &Vcb->CleanVolumeTimer );
                (VOID)KeRemoveQueueDpc( &Vcb->CleanVolumeDpc );

                //
                //  The volume is now clean, note it.
                //

                if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_MOUNTED_DIRTY)) {

                    FatMarkVolume( IrpContext, Vcb, VolumeClean );
                    ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_VOLUME_DIRTY );
                }

                //
                //  Unlock the volume if it is removable.
                //

                if (FlagOn(Vcb->VcbState, VCB_STATE_FLAG_REMOVABLE_MEDIA) &&
                    !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_BOOT_OR_PAGING_FILE)) {

                    FatToggleMediaEjectDisable( IrpContext, Vcb, FALSE );
                }
            }

            break;

        default:

            FatBugCheck( TypeOfOpen, 0, 0 );
        }

        FatUnpinBcb( IrpContext, DirentBcb );

        FatUnpinRepinnedBcbs( IrpContext );

    } finally {

        DebugUnwind( FatCommonFlushBuffers );

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );

		if (secondarySessionResourceAcquired) {

			SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );		
		}

        FatUnpinBcb( IrpContext, DirentBcb );

        if (VcbAcquired) { FatReleaseSecondaryVcb( IrpContext, Vcb ); }

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

        //
        //  If this is a normal termination then pass the request on
        //  to the target device object.
        //

        if (!AbnormalTermination()) {

            NTSTATUS DriverStatus;
            PIO_STACK_LOCATION NextIrpSp;

            //
            //  Get the next stack location, and copy over the stack location
            //

            NextIrpSp = IoGetNextIrpStackLocation( Irp );

            *NextIrpSp = *IrpSp;

            //
            //  Set up the completion routine
            //

            IoSetCompletionRoutine( Irp,
                                    FatFlushCompletionRoutine,
                                    ULongToPtr( Status ),
                                    TRUE,
                                    TRUE,
                                    TRUE );

            //
            //  Send the request.
            //

            DriverStatus = IoCallDriver(Vcb->TargetDeviceObject, Irp);

            Status = (DriverStatus == STATUS_INVALID_DEVICE_REQUEST) ?
                     Status : DriverStatus;

            //
            //  Free the IrpContext and return to the caller.
            //

            FatCompleteRequest( IrpContext, FatNull, STATUS_SUCCESS );
        }

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

    return Status;
}
Exemplo n.º 4
0
NTSTATUS
NdFatSecondaryCommonWrite3 (
	IN PIRP_CONTEXT IrpContext,
	IN PIRP			Irp
	)
{
	NTSTATUS					status;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;
	
	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation( Irp );
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	struct Write				write;
	
	PSECONDARY_REQUEST			secondaryRequest = NULL;
	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;

	TYPE_OF_OPEN				typeOfOpen;
	PVCB						vcb;
	PFCB						fcb;
	PCCB						ccb;
	BOOLEAN						fcbAcquired = FALSE;

	BOOLEAN						writeToEof;
	PUCHAR						inputBuffer;
	ULONG						totalWriteLength;


	ASSERT( KeGetCurrentIrql() < DISPATCH_LEVEL );
	ASSERT (!FlagOn(Irp->Flags, IRP_PAGING_IO));
	
	typeOfOpen = FatDecodeFileObject( fileObject, &vcb, &fcb, &ccb );

	ASSERT( typeOfOpen == UserFileOpen );

	if (FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

		/*if (FlagOn( fcb->FcbState, FCB_STATE_FILE_DELETED )) {
	
			ASSERT( FALSE );
			FatRaiseStatus( IrpContext, STATUS_FILE_DELETED, NULL, NULL );
					
		} else */{
					
			ASSERT( FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );

			status = STATUS_FILE_CORRUPT_ERROR;
	        FatCompleteRequest( IrpContext, Irp, status );
			return status;
		}
	}

	writeToEof = (irpSp->Parameters.Write.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE && 
				  irpSp->Parameters.Write.ByteOffset.HighPart == -1);

	write.ByteOffset	= irpSp->Parameters.Write.ByteOffset;
	write.Key			= irpSp->Parameters.Write.Key;
	write.Length		= irpSp->Parameters.Write.Length;

	ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); 

	//FatAcquireSharedFcb( IrpContext, fcb );
	//fcbAcquired = TRUE;


	try {

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->Secondary->SessionResource, 
													 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

		if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

			PrintIrp( Dbg, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );

			if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
	
				try_return( status = STATUS_FILE_LOCK_CONFLICT );
				
			} else {

				FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
			}
		}

		inputBuffer = FatMapUserBuffer( IrpContext, Irp );
		totalWriteLength = 0;

		do {

			ULONG	inputBufferLength;
			_U8		*ndfsWinxpRequestData;
			_U64	primaryFileHandle;

			if (fcb->UncleanCount == 0) {

				DebugTrace( 0, Dbg2, "NdFatSecondaryCommonWrite2: fileName = %wZ\n", &fileObject->FileName );

				totalWriteLength = write.Length;
				status = STATUS_FILE_CLOSED;
				break;
			}

			if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {

				primaryFileHandle = ccb->PrimaryFileHandle;

			} else {

				PLIST_ENTRY	ccbListEntry;

				ExAcquireFastMutex( &fcb->CcbQMutex );
				
				for (primaryFileHandle = 0, ccbListEntry = fcb->CcbQueue.Flink; 
					 ccbListEntry != &fcb->CcbQueue; 
					 ccbListEntry = ccbListEntry->Flink) {

					if (!FlagOn(CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->NdFatFlags, ND_FAT_CLEANUP_COMPLETE)) {
						
						primaryFileHandle = CONTAINING_RECORD(ccbListEntry, CCB, FcbListEntry)->PrimaryFileHandle;
						break;
					}
				}

				ExReleaseFastMutex( &fcb->CcbQMutex );
			}

			ASSERT( primaryFileHandle );

			inputBufferLength = ((write.Length-totalWriteLength) <= volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize) 
									? (write.Length-totalWriteLength) : volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize;

			secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
															  IRP_MJ_WRITE,
															  volDo->Secondary->Thread.SessionContext.PrimaryMaxDataSize );

			if (secondaryRequest == NULL) {

				FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
			}

			ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
			INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_WRITE, inputBufferLength );

			ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
			ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

			//ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
			ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_WRITE;
			ndfsWinxpRequestHeader->IrpMinorFunction = 0;

			ndfsWinxpRequestHeader->FileHandle = primaryFileHandle;

			ndfsWinxpRequestHeader->IrpFlags   = 0;
			ndfsWinxpRequestHeader->IrpSpFlags = 0;

			ndfsWinxpRequestHeader->Write.Length		= inputBufferLength;
			ndfsWinxpRequestHeader->Write.Key			= write.Key;
			if (writeToEof)
				ndfsWinxpRequestHeader->Write.ByteOffset = write.ByteOffset.QuadPart;
			else
				ndfsWinxpRequestHeader->Write.ByteOffset = write.ByteOffset.QuadPart + totalWriteLength;
			
			ndfsWinxpRequestHeader->Write.ForceWrite	= TRUE;


			DebugTrace2( 0, Dbg, ("ndfsWinxpRequestHeader->Write.ByteOffset = %I64d, ndfsWinxpRequestHeader->Write.Length = %d\n", 
								   ndfsWinxpRequestHeader->Write.ByteOffset, ndfsWinxpRequestHeader->Write.Length) );

			ndfsWinxpRequestData = (_U8 *)(ndfsWinxpRequestHeader+1);

			if (inputBufferLength) {

				try {

					RtlCopyMemory( ndfsWinxpRequestData,
								   inputBuffer + totalWriteLength,
								   inputBufferLength );

				} except (EXCEPTION_EXECUTE_HANDLER) {

					DebugTrace2( 0, Dbg2, ("RedirectIrp: Exception - Input buffer is not valid\n") );
					
					status = GetExceptionCode();
					break;
				}
			}

			//if (fcb->Header.FileSize.LowPart < 100)
			//	DbgPrint( "data = %s\n", ndfsWinxpRequestData );

			secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
			QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

			timeOut.QuadPart = -NDFAT_TIME_OUT;
			status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
		
			if (status != STATUS_SUCCESS) {

				secondaryRequest = NULL;
				status = STATUS_IO_DEVICE_ERROR;
				leave;
			}

			KeClearEvent( &secondaryRequest->CompleteEvent );

			if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

				if (IrpContext->OriginatingIrp)
					PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );
			
				DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

				if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
	
					try_return( status = STATUS_FILE_LOCK_CONFLICT );
				
				} else {

					FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
				}
			}

			ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;

			if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {
			
				DebugTrace2( 0, Dbg, ("ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );

				if (totalWriteLength)
					status = STATUS_SUCCESS;
				else
					status = ndfsWinxpReplytHeader->Status;

				ASSERT( ndfsWinxpReplytHeader->Information == 0 );
				DereferenceSecondaryRequest( secondaryRequest );
				secondaryRequest = NULL;				
				
				break;
			}

			totalWriteLength += ndfsWinxpReplytHeader->Information;

			ASSERT( ndfsWinxpReplytHeader->Information <= inputBufferLength );
			ASSERT( ndfsWinxpReplytHeader->Information != 0 );
		
			DereferenceSecondaryRequest( secondaryRequest );
			secondaryRequest = NULL;

		} while( totalWriteLength < write.Length );

try_exit: NOTHING;

	} finally {

		if (!AbnormalTermination()) {
			
			if (totalWriteLength) {

				Irp->IoStatus.Information = totalWriteLength;
				Irp->IoStatus.Status = STATUS_SUCCESS;
		
			} else {
		
				Irp->IoStatus.Information = 0;
				Irp->IoStatus.Status = status;
			}
		}

		DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart = %I64x, write.Length = %x, totalWriteRequestLength = %x lastStatus = %x\n", 
								write.ByteOffset.QuadPart, write.Length, totalWriteLength, status) );

		if (!FlagOn(ccb->NdFatFlags, ND_FAT_CLEANUP_COMPLETE) && Irp->IoStatus.Status != STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart = %I64x, write.Length = %x, totalWriteRequestLength = %x lastStatus = %x\n", 
								 write.ByteOffset.QuadPart, write.Length, totalWriteLength, status) );

			PrintIrp( Dbg, "RedirectIrpMajorWrite", NULL, Irp );
		}

		if (secondarySessionResourceAcquired == TRUE)
			SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );

		if (fcbAcquired) {
             FatReleaseFcb( IrpContext, fcb );
        }

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}
			
	FatCompleteRequest( IrpContext, Irp, status );
	return status;
}
Exemplo n.º 5
0
NTSTATUS
NdFatSecondaryCommonWrite (
	IN PIRP_CONTEXT IrpContext,
	IN PIRP			Irp
	)
{
	NTSTATUS					status;

	PVOLUME_DEVICE_OBJECT		volDo = CONTAINING_RECORD( IrpContext->Vcb, VOLUME_DEVICE_OBJECT, Vcb );
	BOOLEAN						secondarySessionResourceAcquired = FALSE;
	
	PIO_STACK_LOCATION			irpSp = IoGetCurrentIrpStackLocation( Irp );
	PFILE_OBJECT				fileObject = irpSp->FileObject;

	struct Write				write;
	
	PSECONDARY_REQUEST			secondaryRequest = NULL;
	PNDFS_REQUEST_HEADER		ndfsRequestHeader;
	PNDFS_WINXP_REQUEST_HEADER	ndfsWinxpRequestHeader;
	PNDFS_WINXP_REPLY_HEADER	ndfsWinxpReplytHeader;

	LARGE_INTEGER				timeOut;

	TYPE_OF_OPEN				typeOfOpen;
	PVCB						vcb;
	PFCB						fcb;
	PCCB						ccb;
	BOOLEAN						fcbAcquired = FALSE;


	ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL );

	typeOfOpen = FatDecodeFileObject( fileObject, &vcb, &fcb, &ccb );

	ASSERT( typeOfOpen == UserFileOpen );

	if (FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_UNOPENED)) {

		/*if (FlagOn( fcb->FcbState, FCB_STATE_FILE_DELETED )) {
	
			ASSERT( FALSE );
			FatRaiseStatus( IrpContext, STATUS_FILE_DELETED, NULL, NULL );
					
		} else */{
					
			ASSERT( FlagOn(ccb->NdFatFlags, ND_FAT_CCB_FLAG_CORRUPTED) );
			
			return STATUS_FILE_CORRUPT_ERROR;
		}
	}

	if (irpSp->Parameters.Write.ByteOffset.QuadPart == FILE_WRITE_TO_END_OF_FILE && 
		irpSp->Parameters.Write.ByteOffset.HighPart == -1) {

		write.ByteOffset = fcb->Header.FileSize;

	} else {

		write.ByteOffset = irpSp->Parameters.Write.ByteOffset;
	}

	write.Key		= 0;
	write.Length	= irpSp->Parameters.Write.Length;

	if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
		
		ASSERT( (write.ByteOffset.QuadPart + write.Length) <= 
				((fcb->Header.AllocationSize.QuadPart + PAGE_SIZE - 1) & ~((LONGLONG) (PAGE_SIZE-1))) );

		return STATUS_SUCCESS;
	}

	ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ); 
	//ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_LAZY_WRITE ) );

	if ( (write.ByteOffset.QuadPart + write.Length) <= fcb->Header.FileSize.LowPart) {

		return STATUS_SUCCESS;
	}

	if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

		return STATUS_PENDING;

		ASSERT( FALSE );
		DebugTrace2( 0, Dbg, ("Can't wait in NdFatSecondaryCommonWrite\n") );

		status = FatFsdPostRequest( IrpContext, Irp );

		DebugTrace2( -1, Dbg2, ("NdFatSecondaryCommonWrite:  FatFsdPostRequest -> %08lx\n", status) );
		return status;
	}

		DebugTrace2( 0, Dbg, ("write.ByteOffset.QuadPart + write.Length > fcb->Header.AllocationSize.QuadPart = %d "
								 "ExIsResourceAcquiredSharedLite(fcb->Header.Resource) = %d\n",
							   ((write.ByteOffset.QuadPart + write.Length) > fcb->Header.AllocationSize.QuadPart),
							   ExIsResourceAcquiredSharedLite(fcb->Header.Resource)) );

	if ((write.ByteOffset.QuadPart + write.Length) > fcb->Header.AllocationSize.QuadPart) {

		FatAcquireExclusiveFcb( IrpContext, fcb );
		fcbAcquired = TRUE;
	
	} 	

	try {

		secondarySessionResourceAcquired 
			= SecondaryAcquireResourceExclusiveLite( IrpContext, 
													 &volDo->Secondary->SessionResource, 
													 BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );

		if (FlagOn(volDo->Secondary->Thread.Flags, SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED) ) {

			PrintIrp( Dbg, "SECONDARY_THREAD_FLAG_REMOTE_DISCONNECTED", NULL, IrpContext->OriginatingIrp );
			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );	
		}


		secondaryRequest = ALLOC_WINXP_SECONDARY_REQUEST( volDo->Secondary, 
														  IRP_MJ_SET_INFORMATION,
														  volDo->Secondary->Thread.SessionContext.SecondaryMaxDataSize );

		if (secondaryRequest == NULL) {

			FatRaiseStatus( IrpContext, STATUS_INSUFFICIENT_RESOURCES );
		}

		ndfsRequestHeader = &secondaryRequest->NdfsRequestHeader;
		INITIALIZE_NDFS_REQUEST_HEADER(	ndfsRequestHeader, NDFS_COMMAND_EXECUTE, volDo->Secondary, IRP_MJ_SET_INFORMATION, 0 );

		ndfsWinxpRequestHeader = (PNDFS_WINXP_REQUEST_HEADER)(ndfsRequestHeader+1);
		ASSERT( ndfsWinxpRequestHeader == (PNDFS_WINXP_REQUEST_HEADER)secondaryRequest->NdfsRequestData );

		//ndfsWinxpRequestHeader->IrpTag   = (_U32)Irp;
		ndfsWinxpRequestHeader->IrpMajorFunction = IRP_MJ_SET_INFORMATION;
		ndfsWinxpRequestHeader->IrpMinorFunction = 0;

		ndfsWinxpRequestHeader->FileHandle = ccb->PrimaryFileHandle;

		ndfsWinxpRequestHeader->IrpFlags   = 0;
		ndfsWinxpRequestHeader->IrpSpFlags = 0;

		ndfsWinxpRequestHeader->SetFile.FileHandle				= 0;
		ndfsWinxpRequestHeader->SetFile.Length					= sizeof( FILE_END_OF_FILE_INFORMATION );
		ndfsWinxpRequestHeader->SetFile.FileInformationClass	= FileEndOfFileInformation;

		ndfsWinxpRequestHeader->SetFile.EndOfFileInformation.EndOfFile = write.ByteOffset.QuadPart + write.Length;


		secondaryRequest->RequestType = SECONDARY_REQ_SEND_MESSAGE;
		QueueingSecondaryRequest( volDo->Secondary, secondaryRequest );

		timeOut.QuadPart = -NDFAT_TIME_OUT;
		status = KeWaitForSingleObject( &secondaryRequest->CompleteEvent, Executive, KernelMode, FALSE, &timeOut );
		
		if (status != STATUS_SUCCESS) {

			secondaryRequest = NULL;
			status = STATUS_IO_DEVICE_ERROR;
			leave;
		}

		KeClearEvent( &secondaryRequest->CompleteEvent );

		if (secondaryRequest->ExecuteStatus != STATUS_SUCCESS) {

			if (IrpContext->OriginatingIrp)
				PrintIrp( Dbg2, "secondaryRequest->ExecuteStatus != STATUS_SUCCESS", NULL, IrpContext->OriginatingIrp );
			DebugTrace2( 0, Dbg2, ("secondaryRequest->ExecuteStatus != STATUS_SUCCESS file = %s, line = %d\n", __FILE__, __LINE__) );

			FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
		}

		ndfsWinxpReplytHeader = (PNDFS_WINXP_REPLY_HEADER)secondaryRequest->NdfsReplyData;
		status = ndfsWinxpReplytHeader->Status;
		Irp->IoStatus.Information = write.Length;

		if (ndfsWinxpReplytHeader->Status != STATUS_SUCCESS) {

			DebugTrace2( 0, Dbg2, ("NdNtfsSecondaryCommonWrite: ndfsWinxpReplytHeader->Status = %x\n", ndfsWinxpReplytHeader->Status) );
			ASSERT( ndfsWinxpReplytHeader->Information == 0 );
		
		} else
			ASSERT( ndfsWinxpReplytHeader->FileInformationSet );
	
		if (ndfsWinxpReplytHeader->FileInformationSet) {

			PNDFS_FAT_MCB_ENTRY	mcbEntry;
			ULONG			index;

			BOOLEAN			lookupResut;
			VBO				vcn;
			LBO				lcn;
			//LBO			startingLcn;
			ULONG			clusterCount;

			//DbgPrint( "w ndfsWinxpReplytHeader->FileSize = %x\n", ndfsWinxpReplytHeader->FileSize );

			if (ndfsWinxpReplytHeader->AllocationSize != fcb->Header.AllocationSize.QuadPart) {

				ASSERT( ExIsResourceAcquiredExclusiveLite(fcb->Header.Resource) );

				ASSERT( ndfsWinxpReplytHeader->AllocationSize > fcb->Header.AllocationSize.QuadPart );

				mcbEntry = (PNDFS_FAT_MCB_ENTRY)( ndfsWinxpReplytHeader+1 );

				for (index=0, vcn=0; index < ndfsWinxpReplytHeader->NumberOfMcbEntry; index++, mcbEntry++) {

					lookupResut = FatLookupMcbEntry( vcb, &fcb->Mcb, vcn, &lcn, &clusterCount, NULL );
					
					if (lookupResut == TRUE && vcn < fcb->Header.AllocationSize.QuadPart) {

						ASSERT( lookupResut == TRUE );
						//ASSERT( startingLcn == lcn );
						ASSERT( vcn == mcbEntry->Vcn );
						ASSERT( lcn == (((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector) );
						ASSERT( clusterCount <= mcbEntry->ClusterCount );

						if (clusterCount < mcbEntry->ClusterCount) {

							FatAddMcbEntry ( vcb, 
											 &fcb->Mcb, 
											 (VBO)mcbEntry->Vcn, 
											 ((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector, 
											 (ULONG)mcbEntry->ClusterCount );

							lookupResut = FatLookupMcbEntry( vcb, &fcb->Mcb, vcn, &lcn, &clusterCount, NULL );

							ASSERT( lookupResut == TRUE );
							//ASSERT( startingLcn == lcn );
							ASSERT( vcn == mcbEntry->Vcn );
							ASSERT( lcn == (((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector) );
							ASSERT( clusterCount == mcbEntry->ClusterCount );
						}
					
					} else { 

						ASSERT( lookupResut == FALSE || lcn == 0 );

						FatAddMcbEntry ( vcb, 
										 &fcb->Mcb, 
										 (VBO)mcbEntry->Vcn, 
										 ((LBO)mcbEntry->Lcn) << vcb->AllocationSupport.LogOfBytesPerSector, 
										 (ULONG)mcbEntry->ClusterCount );
					}

					vcn += (ULONG)mcbEntry->ClusterCount;
				}

				ASSERT( vcn == ndfsWinxpReplytHeader->AllocationSize );

				fcb->Header.AllocationSize.QuadPart = ndfsWinxpReplytHeader->AllocationSize;
				SetFlag( fcb->FcbState, FCB_STATE_TRUNCATE_ON_CLOSE );		

				if (CcIsFileCached(fileObject)) {

					ASSERT( fileObject->SectionObjectPointer->SharedCacheMap != NULL );
					CcSetFileSizes( fileObject, (PCC_FILE_SIZES)&fcb->Header.AllocationSize );
				}
			}

			DebugTrace2(0, Dbg, ("write scb->Header.FileSize.LowPart = %I64x, scb->Header.ValidDataLength.QuadPart = %I64x\n", 
								 fcb->Header.FileSize.LowPart, fcb->Header.ValidDataLength.QuadPart) );

		}

#if DBG
		{
			BOOLEAN			lookupResut;
			VBO				vcn;
			LBO				lcn;
			//LCN				startingLcn;
			ULONG			clusterCount;

			vcn = 0;
			while (1) {

				lookupResut = FatLookupMcbEntry( vcb, &fcb->Mcb, vcn, &lcn, &clusterCount, NULL );
				if (lookupResut == FALSE || lcn == 0)
					break;

				vcn += clusterCount;
			}

			ASSERT( vcn == fcb->Header.AllocationSize.QuadPart );
		}

#endif

	} finally {
	
		if (secondarySessionResourceAcquired == TRUE)
				SecondaryReleaseResourceLite( IrpContext, &volDo->Secondary->SessionResource );

		if (fcbAcquired) {
             FatReleaseFcb( IrpContext, fcb );
        }

		if (secondaryRequest)
			DereferenceSecondaryRequest( secondaryRequest );
	}
			
	return status;
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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 = 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;
}
Exemplo n.º 8
0
IO_STATUS_BLOCK
NTAPI
FatiOpenExistingDcb(IN PFAT_IRP_CONTEXT IrpContext,
                    IN PFILE_OBJECT FileObject,
                    IN PVCB Vcb,
                    IN PFCB Dcb,
                    IN PACCESS_MASK DesiredAccess,
                    IN USHORT ShareAccess,
                    IN ULONG CreateDisposition,
                    IN BOOLEAN NoEaKnowledge,
                    IN BOOLEAN DeleteOnClose)
{
    IO_STATUS_BLOCK Iosb = {{0}};
    PCCB Ccb;

    /* Exclusively lock this FCB */
    FatAcquireExclusiveFcb(IrpContext, Dcb);

    /* Check if it's a delete-on-close of a root DCB */
    if (FatNodeType(Dcb) == FAT_NTC_ROOT_DCB && DeleteOnClose)
    {
        Iosb.Status = STATUS_CANNOT_DELETE;

        /* Release the lock and return */
        FatReleaseFcb(IrpContext, Dcb);
        return Iosb;
    }

    /*if (NoEaKnowledge && NodeType(Dcb) != FAT_NTC_ROOT_DCB &&
        !FatIsFat32(Vcb))
    {
        UNIMPLEMENTED;
    }*/

    /* Check the create disposition and desired access */
    if ((CreateDisposition != FILE_OPEN) &&
        (CreateDisposition != FILE_OPEN_IF))
    {
        Iosb.Status = STATUS_OBJECT_NAME_COLLISION;

        /* Release the lock and return */
        FatReleaseFcb(IrpContext, Dcb);
        return Iosb;
    }

#if 0
    if (!FatCheckFileAccess(IrpContext,
                            Dcb->DirentFatFlags,
                            DesiredAccess))
    {
        Iosb.Status = STATUS_ACCESS_DENIED;
        try_return( Iosb );
    }
#endif

    /* If it's already opened - check share access */
    if (Dcb->OpenCount > 0)
    {
        Iosb.Status = IoCheckShareAccess(*DesiredAccess,
                                         ShareAccess,
                                         FileObject,
                                         &Dcb->ShareAccess,
                                         TRUE);

        if (!NT_SUCCESS(Iosb.Status))
        {
            /* Release the lock and return */
            FatReleaseFcb(IrpContext, Dcb);
            return Iosb;
        }
    }
    else
    {
        IoSetShareAccess(*DesiredAccess,
                         ShareAccess,
                         FileObject,
                         &Dcb->ShareAccess);
    }

    /* Set the file object */
    Ccb = FatCreateCcb();
    FatSetFileObject(FileObject,
                     UserDirectoryOpen,
                     Dcb,
                     Ccb);

    /* Increase counters */
    Dcb->UncleanCount++;
    Dcb->OpenCount++;
    Vcb->OpenFileCount++;
    if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;

    /* Set delete on close */
    if (DeleteOnClose)
        SetFlag(Ccb->Flags, CCB_DELETE_ON_CLOSE);

    /* Clear delay close flag */
    ClearFlag(Dcb->State, FCB_STATE_DELAY_CLOSE);

    /* That's it */
    Iosb.Status = STATUS_SUCCESS;
    Iosb.Information = FILE_OPENED;

    /* Release the lock */
    FatReleaseFcb(IrpContext, Dcb);

    return Iosb;
}
Exemplo n.º 9
0
IO_STATUS_BLOCK
NTAPI
FatiOpenExistingFcb(IN PFAT_IRP_CONTEXT IrpContext,
                    IN PFILE_OBJECT FileObject,
                    IN PVCB Vcb,
                    IN PFCB Fcb,
                    IN PACCESS_MASK DesiredAccess,
                    IN USHORT ShareAccess,
                    IN ULONG AllocationSize,
                    IN PFILE_FULL_EA_INFORMATION EaBuffer,
                    IN ULONG EaLength,
                    IN UCHAR FileAttributes,
                    IN ULONG CreateDisposition,
                    IN BOOLEAN NoEaKnowledge,
                    IN BOOLEAN DeleteOnClose,
                    IN BOOLEAN OpenedAsDos,
                    OUT PBOOLEAN OplockPostIrp)
{
    IO_STATUS_BLOCK Iosb = {{0}};
    ACCESS_MASK AddedAccess = 0;
    BOOLEAN Hidden;
    BOOLEAN System;
    PCCB Ccb = NULL;
    NTSTATUS Status, StatusPrev;

    /* Acquire exclusive FCB lock */
    (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);

    *OplockPostIrp = FALSE;

    /* Check if there is a batch oplock */
    if (FsRtlCurrentBatchOplock(&Fcb->Fcb.Oplock))
    {
        /* Return with a special information field */
        Iosb.Information = FILE_OPBATCH_BREAK_UNDERWAY;

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

        if (Iosb.Status != STATUS_SUCCESS &&
            Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
        {
            /* The Irp needs to be queued */
            *OplockPostIrp = TRUE;

            /* Release the FCB and return */
            FatReleaseFcb(IrpContext, Fcb);
            return Iosb;
        }
    }

    /* Validate parameters and modify access */
    if (CreateDisposition == FILE_CREATE)
    {
        Iosb.Status = STATUS_OBJECT_NAME_COLLISION;

        /* Release the FCB and return */
        FatReleaseFcb(IrpContext, Fcb);
        return Iosb;
    }
    else if (CreateDisposition == FILE_SUPERSEDE)
    {
        SetFlag(AddedAccess, DELETE & ~(*DesiredAccess));
        *DesiredAccess |= DELETE;
    }
    else if ((CreateDisposition == FILE_OVERWRITE) ||
             (CreateDisposition == FILE_OVERWRITE_IF))
    {
        SetFlag(AddedAccess,
                (FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES)
                & ~(*DesiredAccess) );

        *DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;
    }

    // TODO: Check desired access

    // TODO: Check if this file is readonly and DeleteOnClose is set

    /* Validate disposition information */
    if ((CreateDisposition == FILE_SUPERSEDE) ||
        (CreateDisposition == FILE_OVERWRITE) ||
        (CreateDisposition == FILE_OVERWRITE_IF))
    {
        // TODO: Get this attributes from the dirent
        Hidden = FALSE;
        System = FALSE;

        if ((Hidden && !FlagOn(FileAttributes, FILE_ATTRIBUTE_HIDDEN)) ||
            (System && !FlagOn(FileAttributes, FILE_ATTRIBUTE_SYSTEM)))
        {
            DPRINT1("Hidden/system attributes don't match\n");

            Iosb.Status = STATUS_ACCESS_DENIED;

            /* Release the FCB and return */
            FatReleaseFcb(IrpContext, Fcb);
            return Iosb;
        }

        // TODO: Check for write protected volume
    }

    /* Check share access */
    Iosb.Status = IoCheckShareAccess(*DesiredAccess,
                                     ShareAccess,
                                     FileObject,
                                     &Fcb->ShareAccess,
                                     FALSE);
    if (!NT_SUCCESS(Iosb.Status))
    {
        /* Release the FCB and return */
        FatReleaseFcb(IrpContext, Fcb);
        return Iosb;
    }

    /* Check the oplock status after checking for share access */
    Iosb.Status = FsRtlCheckOplock(&Fcb->Fcb.Oplock,
                                   IrpContext->Irp,
                                   IrpContext,
                                   FatOplockComplete,
                                   FatPrePostIrp );

    if (Iosb.Status != STATUS_SUCCESS &&
        Iosb.Status != STATUS_OPLOCK_BREAK_IN_PROGRESS)
    {
        /* The Irp needs to be queued */
        *OplockPostIrp = TRUE;

        /* Release the FCB and return */
        FatReleaseFcb(IrpContext, Fcb);
        return Iosb;
    }

    /* Set Fast I/O flag */
    Fcb->Header.IsFastIoPossible = FALSE; //FatiIsFastIoPossible(Fcb);

    /* Make sure image is not mapped */
    if (DeleteOnClose || FlagOn(*DesiredAccess, FILE_WRITE_DATA))
    {
        /* Try to flush the image section */
        if (!MmFlushImageSection(&Fcb->SectionObjectPointers, MmFlushForWrite))
        {
            /* Yes, image section exists, set correct status code */
            if (DeleteOnClose)
                Iosb.Status = STATUS_CANNOT_DELETE;
            else
                Iosb.Status = STATUS_SHARING_VIOLATION;

            /* Release the FCB and return */
            FatReleaseFcb(IrpContext, Fcb);
            return Iosb;
        }
    }

    /* Flush the cache if it's non-cached non-pagefile access */
    if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING) &&
        Fcb->SectionObjectPointers.DataSectionObject &&
        !FlagOn(Fcb->State, FCB_STATE_PAGEFILE))
    {
        /* Set the flag that create is in progress */
        SetFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);

        /* Flush the cache */
        CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);

        /* Acquire and release Paging I/O resource before purging the cache section
           to let lazy writer finish */
        ExAcquireResourceExclusiveLite( Fcb->Header.PagingIoResource, TRUE);
        ExReleaseResourceLite( Fcb->Header.PagingIoResource );

        /* Delete the cache section */
        CcPurgeCacheSection(&Fcb->SectionObjectPointers, NULL, 0, FALSE);

        /* Clear the flag */
        ClearFlag(Fcb->Vcb->State, VCB_STATE_CREATE_IN_PROGRESS);
    }

    /* Check create disposition flags and branch accordingly */
    if (CreateDisposition == FILE_OPEN ||
        CreateDisposition == FILE_OPEN_IF)
    {
        DPRINT("Opening a file\n");

        /* Check if we need to bother with EA */
        if (NoEaKnowledge && FALSE /* FatIsFat32(Vcb)*/)
        {
            UNIMPLEMENTED;
        }

        /* Set up file object */
        Ccb = FatCreateCcb();
        FatSetFileObject(FileObject,
                         UserFileOpen,
                         Fcb,
                         Ccb);

        FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;

        /* The file is opened */
        Iosb.Information = FILE_OPENED;
        goto SuccComplete;
    }
    else if ((CreateDisposition == FILE_SUPERSEDE) ||
             (CreateDisposition == FILE_OVERWRITE) ||
             (CreateDisposition == FILE_OVERWRITE_IF))
    {
        /* Remember previous status */
        StatusPrev = Iosb.Status;

        // TODO: Check system security access

        /* Perform overwrite operation */
        Iosb = FatiOverwriteFile(IrpContext,
                                 FileObject,
                                 Fcb,
                                 AllocationSize,
                                 EaBuffer,
                                 EaLength,
                                 FileAttributes,
                                 CreateDisposition,
                                 NoEaKnowledge);

        /* Restore previous status in case of success */
        if (Iosb.Status == STATUS_SUCCESS)
            Iosb.Status = StatusPrev;

        /* Fall down to completion */
    }
    else
    {
        /* We can't get here */
        KeBugCheckEx(FAT_FILE_SYSTEM, CreateDisposition, 0, 0, 0);
    }


SuccComplete:
    /* If all is fine */
    if (Iosb.Status != STATUS_PENDING &&
        NT_SUCCESS(Iosb.Status))
    {
        /* Update access if needed */
        if (AddedAccess)
        {
            /* Remove added access flags from desired access */
            ClearFlag(*DesiredAccess, AddedAccess);

            /* Check share access */
            Status = IoCheckShareAccess(*DesiredAccess,
                                        ShareAccess,
                                        FileObject,
                                        &Fcb->ShareAccess,
                                        TRUE);

            /* Make sure it's success */
            ASSERT(Status == STATUS_SUCCESS);
        }
        else
        {
            /* Update the share access */
            IoUpdateShareAccess(FileObject, &Fcb->ShareAccess);
        }

        /* Clear the delay close */
        ClearFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);

        /* Increase counters */
        Fcb->UncleanCount++;
        Fcb->OpenCount++;
        Vcb->OpenFileCount++;
        if (IsFileObjectReadOnly(FileObject)) Vcb->ReadOnlyCount++;
        if (FlagOn(FileObject->Flags, FO_NO_INTERMEDIATE_BUFFERING)) Fcb->NonCachedUncleanCount++;

        // TODO: Handle DeleteOnClose and OpenedAsDos by storing those flags in CCB
    }

    return Iosb;
}
Exemplo n.º 10
0
/* Last handle to a file object is closed */
NTSTATUS
NTAPI
FatiCleanup(PFAT_IRP_CONTEXT IrpContext, PIRP Irp)
{
    PIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;
    TYPE_OF_OPEN TypeOfOpen;
    PSHARE_ACCESS ShareAccess;
    BOOLEAN SendUnlockNotification = FALSE;
    PLARGE_INTEGER TruncateSize = NULL;
    //LARGE_INTEGER LocalTruncateSize;
    BOOLEAN AcquiredVcb = FALSE, AcquiredFcb = FALSE;
    NTSTATUS Status;
    PVCB Vcb;
    PFCB Fcb;
    PCCB Ccb;

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DPRINT("FatiCleanup\n");
    DPRINT("\tIrp           = %p\n", Irp);
    DPRINT("\t->FileObject  = %p\n", IrpSp->FileObject);

    FileObject = IrpSp->FileObject;
    TypeOfOpen = FatDecodeFileObject(FileObject, &Vcb, &Fcb, &Ccb);

    if (TypeOfOpen == UnopenedFileObject)
    {
        DPRINT1("Unopened File Object\n");

        FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
        return STATUS_SUCCESS;
    }

    if (FlagOn( FileObject->Flags, FO_CLEANUP_COMPLETE ))
    {
        /* Just flush the file */

        if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
            FlagOn(FileObject->Flags, FO_FILE_MODIFIED) &&
            !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED) &&
            (TypeOfOpen == UserFileOpen))
        {
            //Status = FatFlushFile(IrpContext, Fcb, Flush);
            //if (!NT_SUCCESS(Status)) FatNormalizeAndRaiseStatus(IrpContext, Status);
            UNIMPLEMENTED;
        }

        FatCompleteRequest(IrpContext, Irp, STATUS_SUCCESS);
        return STATUS_SUCCESS;
    }

    if (TypeOfOpen == UserFileOpen ||
        TypeOfOpen == UserDirectoryOpen)
    {
        ASSERT(Fcb != NULL);

        (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);

        AcquiredFcb = TRUE;

        /* Set FCB flags according to DELETE_ON_CLOSE */
        if (FlagOn(Ccb->Flags, CCB_DELETE_ON_CLOSE))
        {
            ASSERT(FatNodeType(Fcb) != FAT_NTC_ROOT_DCB);

            SetFlag(Fcb->State, FCB_STATE_DELETE_ON_CLOSE);

            /* Issue a notification */
            if (TypeOfOpen == UserDirectoryOpen)
            {
                FsRtlNotifyFullChangeDirectory(Vcb->NotifySync,
                                               &Vcb->NotifyList,
                                               FileObject->FsContext,
                                               NULL,
                                               FALSE,
                                               FALSE,
                                               0,
                                               NULL,
                                               NULL,
                                               NULL);
            }
        }

        /* If file should be deleted, acquire locks */
        if ((Fcb->UncleanCount == 1) &&
            FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
            (Fcb->Condition != FcbBad) &&
            !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
        {
            FatReleaseFcb(IrpContext, Fcb);
            AcquiredFcb = FALSE;

            (VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
            AcquiredVcb = TRUE;

            (VOID)FatAcquireExclusiveFcb(IrpContext, Fcb);
            AcquiredFcb = TRUE;
        }
    }

    /* Acquire VCB lock if it was a volume open */
    if (TypeOfOpen == UserVolumeOpen)
    {
        (VOID)FatAcquireExclusiveVcb(IrpContext, Vcb);
        AcquiredVcb = TRUE;
    }

    /* Cleanup all notifications */
    if (TypeOfOpen == UserDirectoryOpen)
    {
        FsRtlNotifyCleanup(Vcb->NotifySync,
                           &Vcb->NotifyList,
                           Ccb);
    }

    if (Fcb)
    {
        //TODO: FatVerifyFcb
    }

    switch (TypeOfOpen)
    {
    case DirectoryFile:
    case VirtualVolumeFile:
        DPRINT1("Cleanup VirtualVolumeFile/DirectoryFile\n");
        ShareAccess = NULL;
        break;

    case UserVolumeOpen:
        DPRINT("Cleanup UserVolumeOpen\n");

        if (FlagOn(Ccb->Flags, CCB_COMPLETE_DISMOUNT))
        {
            FatCheckForDismount( IrpContext, Vcb, TRUE );
        } else if (FileObject->WriteAccess &&
            FlagOn(FileObject->Flags, FO_FILE_MODIFIED))
        {
            UNIMPLEMENTED;
        }

        /* Release the volume and send notification */
        if (FlagOn(Vcb->State, VCB_STATE_FLAG_LOCKED) &&
            (Vcb->FileObjectWithVcbLocked == FileObject))
        {
            UNIMPLEMENTED;
            SendUnlockNotification = TRUE;
        }

        ShareAccess = &Vcb->ShareAccess;
        break;

    case EaFile:
        DPRINT1("Cleanup EaFileObject\n");
        ShareAccess = NULL;
        break;

    case UserDirectoryOpen:
        DPRINT("Cleanup UserDirectoryOpen\n");

        ShareAccess = &Fcb->ShareAccess;

        /* Should it be a delayed close? */
        if ((Fcb->UncleanCount == 1) &&
            (Fcb->OpenCount == 1) &&
            (Fcb->Dcb.DirectoryFileOpenCount == 0) &&
            !FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
            Fcb->Condition == FcbGood)
        {
            /* Yes, a delayed one */
            SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
        }

        if (VcbGood == Vcb->Condition)
        {
            //FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
            //TODO: Actually update dirent
        }

        if ((Fcb->UncleanCount == 1) &&
            (FatNodeType(Fcb) == FAT_NTC_DCB) &&
            (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE)) &&
            (Fcb->Condition != FcbBad) &&
            !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
        {
            UNIMPLEMENTED;
        }

        /*  Decrement unclean counter */
        ASSERT(Fcb->UncleanCount != 0);
        Fcb->UncleanCount--;
        break;

    case UserFileOpen:
        DPRINT("Cleanup UserFileOpen\n");

        ShareAccess = &Fcb->ShareAccess;

        /* Should it be a delayed close? */
        if ((FileObject->SectionObjectPointer->DataSectionObject == NULL) &&
            (FileObject->SectionObjectPointer->ImageSectionObject == NULL) &&
            (Fcb->UncleanCount == 1) &&
            (Fcb->OpenCount == 1) &&
            !FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
            Fcb->Condition == FcbGood)
        {
            /* Yes, a delayed one */
            //SetFlag(Fcb->State, FCB_STATE_DELAY_CLOSE);
            DPRINT1("Setting a delay on close for some reason for FCB %p, FF handle %p, file name '%wZ'\n", Fcb, Fcb->FatHandle, &Fcb->FullFileName);
        }

        /* Unlock all file locks */
        FsRtlFastUnlockAll(&Fcb->Fcb.Lock,
                           FileObject,
                           IoGetRequestorProcess(Irp),
                           NULL);

        if (Vcb->Condition == VcbGood)
        {
            if (Fcb->Condition != FcbBad)
            {
                //FatUpdateDirentFromFcb( IrpContext, FileObject, Fcb, Ccb );
                // TODO: Update on-disk structures
            }

            if (Fcb->UncleanCount == 1 &&
                Fcb->Condition != FcbBad)
            {
                //DELETE_CONTEXT DeleteContext;

                /* Should this file be deleted on close? */
                if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
                    !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
                {
                    UNIMPLEMENTED;
                }
                else
                {
                    if (!FlagOn(Fcb->State, FCB_STATE_PAGEFILE) &&
                        (Fcb->Header.ValidDataLength.LowPart < Fcb->Header.FileSize.LowPart))
                    {
#if 0
                        ULONG ValidDataLength;

                        ValidDataLength = Fcb->Header.ValidDataLength.LowPart;

                        if (ValidDataLength < Fcb->ValidDataToDisk) {
                            ValidDataLength = Fcb->ValidDataToDisk;
                        }

                        if (ValidDataLength < Fcb->Header.FileSize.LowPart)
                        {
                            FatZeroData( IrpContext,
                                Vcb,
                                FileObject,
                                ValidDataLength,
                                Fcb->Header.FileSize.LowPart -
                                ValidDataLength );

                            Fcb->ValidDataToDisk =
                                Fcb->Header.ValidDataLength.LowPart =
                                Fcb->Header.FileSize.LowPart;

                            if (CcIsFileCached(FileObject))
                            {
                                CcSetFileSizes(FileObject, (PCC_FILE_SIZES)&Fcb->Header.AllocationSize);
                            }
                        }
#endif
                        DPRINT1("Zeroing out data is not implemented\n");
                    }
                }

                /* Should the file be truncated on close? */
                if (FlagOn(Fcb->State, FCB_STATE_TRUNCATE_ON_CLOSE))
                {
                    if (Vcb->Condition == VcbGood)
                    {
                        // TODO: Actually truncate the file allocation
                        UNIMPLEMENTED;
                    }

                    /* Remove truncation flag */
                    Fcb->State &= ~FCB_STATE_TRUNCATE_ON_CLOSE;
                }

                /* Check again if it should be deleted */
                if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE) &&
                    Fcb->Header.AllocationSize.LowPart == 0)
                {
                    FatNotifyReportChange(IrpContext,
                                          Vcb,
                                          Fcb,
                                          FILE_NOTIFY_CHANGE_FILE_NAME,
                                          FILE_ACTION_REMOVED);
                }

                /* Remove the entry from the splay table if the file was deleted */
                if (FlagOn(Fcb->State, FCB_STATE_DELETE_ON_CLOSE))
                {
                    FatRemoveNames(IrpContext, Fcb);
                }
            }
        }

        ASSERT(Fcb->UncleanCount != 0);
        Fcb->UncleanCount--;
        if (!FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED))
        {
            ASSERT(Fcb->NonCachedUncleanCount != 0);
            Fcb->NonCachedUncleanCount--;
        }

        if (FlagOn(FileObject->Flags, FO_CACHE_SUPPORTED) &&
            (Fcb->NonCachedUncleanCount != 0) &&
            (Fcb->NonCachedUncleanCount == Fcb->UncleanCount) &&
            (Fcb->SectionObjectPointers.DataSectionObject != NULL))
        {
            CcFlushCache(&Fcb->SectionObjectPointers, NULL, 0, NULL);

            /* Acquire and release PagingIo to get in sync with lazy writer */
            ExAcquireResourceExclusiveLite(Fcb->Header.PagingIoResource, TRUE);
            ExReleaseResourceLite(Fcb->Header.PagingIoResource);

            CcPurgeCacheSection(&Fcb->SectionObjectPointers,
                                NULL,
                                0,
                                FALSE);
        }

        if (Fcb->Condition == FcbBad)
        {
            //TruncateSize = &FatLargeZero;
            UNIMPLEMENTED;
        }

        /*  Cleanup the cache map */
        CcUninitializeCacheMap(FileObject, TruncateSize, NULL);
        break;

    default:
        KeBugCheckEx(FAT_FILE_SYSTEM, __LINE__, (ULONG_PTR)TypeOfOpen, 0, 0);
    }

    /* Cleanup the share access */

    if (ShareAccess)
    {
        DPRINT("Cleaning up the share access\n");
        IoRemoveShareAccess(FileObject, ShareAccess);
    }

    if (TypeOfOpen == UserFileOpen)
    {
        /* Update oplocks */
        FsRtlCheckOplock(&Fcb->Fcb.Oplock,
                         Irp,
                         IrpContext,
                         NULL,
                         NULL);

        Fcb->Header.IsFastIoPossible = FatIsFastIoPossible(Fcb);
    }

    /* Set the FO_CLEANUP_COMPLETE flag */
    SetFlag(FileObject->Flags, FO_CLEANUP_COMPLETE);

    Status = STATUS_SUCCESS;

    // TODO: Unpin repinned BCBs
    //FatUnpinRepinnedBcbs(IrpContext);

    /* Flush the volume if necessary */
    if (FlagOn(Vcb->State, VCB_STATE_FLAG_DEFERRED_FLUSH) &&
        !FlagOn(Vcb->State, VCB_STATE_FLAG_WRITE_PROTECTED))
    {
        UNIMPLEMENTED;
    }

    /* Cleanup */
    if (AcquiredFcb) FatReleaseFcb(IrpContext, Fcb);
    if (AcquiredVcb) FatReleaseVcb(IrpContext, Vcb);

    /* Send volume notification */
    if (SendUnlockNotification)
        FsRtlNotifyVolumeEvent(FileObject, FSRTL_VOLUME_UNLOCK);

    return Status;
}
Exemplo n.º 11
0
 __drv_mustHoldCriticalRegion
FINISHED
FatAcquireSharedFcb (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb
    )

/*++

Routine Description:

    This routine acquires shared access to the Fcb.

    After we acquire the resource check to see if this operation is legal.
    If it isn't (ie. we get an exception), release the resource.

Arguments:

    Fcb - Supplies the Fcb to acquire

Return Value:

    FINISHED - TRUE if we have the resource and FALSE if we needed to block
        for the resource but Wait is FALSE.

--*/

{
    PAGED_CODE();

RetryFcbShared:

    if (ExAcquireResourceSharedLite( Fcb->Header.Resource, BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT))) {

        //
        //  Check for anything other than a non-cached write if the
        //  async count is non-zero in the Fcb, or if others are waiting
        //  for the resource.  Then wait for all outstanding I/O to finish,
        //  drop the resource, and wait again.
        //

        if ((Fcb->NonPaged->OutstandingAsyncWrites != 0) &&
            ((IrpContext->MajorFunction != IRP_MJ_WRITE) ||
             !FlagOn(IrpContext->OriginatingIrp->Flags, IRP_NOCACHE) ||
             (ExGetSharedWaiterCount(Fcb->Header.Resource) != 0) ||
             (ExGetExclusiveWaiterCount(Fcb->Header.Resource) != 0))) {

            KeWaitForSingleObject( Fcb->NonPaged->OutstandingAsyncEvent,
                                   Executive,
                                   KernelMode,
                                   FALSE,
                                   (PLARGE_INTEGER) NULL );

            FatReleaseFcb( IrpContext, Fcb );

            goto RetryFcbShared;
        }

        try {

            FatVerifyOperationIsLegal( IrpContext );

        } finally {

            if ( AbnormalTermination() ) {

                FatReleaseFcb( IrpContext, Fcb );
            }
        }


        return TRUE;

    } else {

        return FALSE;
Exemplo n.º 12
0
VOID
FatForceCacheMiss (
    IN PIRP_CONTEXT IrpContext,
    IN PFCB Fcb,
    IN FAT_FLUSH_TYPE FlushType
    )

/*++

Routine Description:

    The following routine asks either Cc or Mm to get rid of any cached
    pages on a file.  Note that this will fail if a user has mapped a file.

    If there is a shared cache map, purge the cache section.  Otherwise
    we have to go and ask Mm to blow away the section.

    NOTE: This caller MUST own the Vcb exclusive.

Arguments:

    Fcb - Supplies a pointer to an fcb

    FlushType - Specifies the kind of flushing to perform
    
Return Value:

    None.

--*/

{
    PVCB Vcb;
    BOOLEAN ChildrenAcquired = FALSE;

    PAGED_CODE();

    //
    //  If we can't wait, bail.
    //

    ASSERT( FatVcbAcquiredExclusive( IrpContext, Fcb->Vcb ) ||
            FlagOn( Fcb->Vcb->VcbState, VCB_STATE_FLAG_LOCKED ) );

    if (!FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {

        FatRaiseStatus( IrpContext, STATUS_CANT_WAIT );
    }

    //
    //  If we are purging a directory file object, we must acquire all the
    //  FCBs exclusive so that the parent directory is not being pinned.
    //  Careful, we can collide with something acquiring up the tree like
    //  an unpin repinned flush (FsRtlAcquireFileForCcFlush ...) of a parent
    //  dir on extending writethrough of a child file (oops).  So get things
    //  going up the tree, not down.
    //

    if ((NodeType(Fcb) != FAT_NTC_FCB) &&
        !IsListEmpty(&Fcb->Specific.Dcb.ParentDcbQueue)) {

        PLIST_ENTRY Links;
        PFCB TempFcb;

        ChildrenAcquired = TRUE;

        for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
             Links != &Fcb->Specific.Dcb.ParentDcbQueue;
             Links = Links->Flink) {

            TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );

            (VOID)FatAcquireExclusiveFcb( IrpContext, TempFcb );
        }
    }

    (VOID)FatAcquireExclusiveFcb( IrpContext, Fcb );

    //
    //  We use this flag to indicate to a close beneath us that
    //  the Fcb resource should be freed before deleting the Fcb.
    //

    Vcb = Fcb->Vcb;

    SetFlag( Fcb->FcbState, FCB_STATE_FORCE_MISS_IN_PROGRESS );

    ClearFlag( Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB );

    try {

        BOOLEAN DataSectionExists;
        BOOLEAN ImageSectionExists;

        PSECTION_OBJECT_POINTERS Section;

        if ( FlushType ) {

            (VOID)FatFlushFile( IrpContext, Fcb, FlushType );
        }

        //
        //  The Flush may have made the Fcb go away
        //

        if (!FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB)) {

            Section = &Fcb->NonPaged->SectionObjectPointers;

            DataSectionExists = (BOOLEAN)(Section->DataSectionObject != NULL);
            ImageSectionExists = (BOOLEAN)(Section->ImageSectionObject != NULL);

            //
            //  Note, it is critical to do the Image section first as the
            //  purge of the data section may cause the image section to go
            //  away, but the opposite is not true.
            //

            if (ImageSectionExists) {

                (VOID)MmFlushImageSection( Section, MmFlushForWrite );
            }

            if (DataSectionExists) {

                CcPurgeCacheSection( Section, NULL, 0, FALSE );
            }
        }

    } finally {

        //
        //  If we purging a directory file object, release all the Fcb
        //  resources that we acquired above.  The Dcb cannot have vanished
        //  if there were Fcbs underneath it, and the Fcbs couldn't have gone
        //  away since I own the Vcb.
        //

        if (ChildrenAcquired) {

            PLIST_ENTRY Links;
            PFCB TempFcb;

            for (Links = Fcb->Specific.Dcb.ParentDcbQueue.Flink;
                 Links != &Fcb->Specific.Dcb.ParentDcbQueue;
                 Links = Links->Flink) {

                TempFcb = CONTAINING_RECORD( Links, FCB, ParentDcbLinks );

                FatReleaseFcb( IrpContext, TempFcb );
            }
        }

        //
        //  Since we have the Vcb exclusive we know that if any closes
        //  come in it is because the CcPurgeCacheSection caused the
        //  Fcb to go away.  Also in close, the Fcb was released
        //  before being freed.
        //

        if ( !FlagOn(Vcb->VcbState, VCB_STATE_FLAG_DELETED_FCB) ) {

            ClearFlag( Fcb->FcbState, FCB_STATE_FORCE_MISS_IN_PROGRESS );

            FatReleaseFcb( (IRPCONTEXT), Fcb );
        }
    }
}