示例#1
0
VOID
NtfsReleaseVolumeFromClose (
    IN PVOID OpaqueVcb
    )

/*++

Routine Description:

    The address of this routine is specified when creating a CacheMap for
    a file.  It is subsequently called by the Lazy Writer after its
    performing closes on the file.

Arguments:

    Vcb - The Vcb which was specified as a close context parameter for this
          routine.

Return Value:

    None

--*/

{
    PVCB Vcb = (PVCB)OpaqueVcb;

    ASSERT_VCB(Vcb);

    PAGED_CODE();

    NtfsReleaseVcb( NULL, Vcb );

    return;
}
示例#2
0
NTSTATUS
NtfsCommonSetVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for set Volume Information 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;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );
    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonSetVolumeInfo\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.SetVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.SetVolume.Length;
    FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

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

    if (TypeOfOpen != UserVolumeOpen &&
        (TypeOfOpen != UserViewIndexOpen ||
         FsInformationClass != FileFsControlInformation ||
         Fcb != Vcb->QuotaTableScb->Fcb)) {

        NtfsCompleteRequest( IrpContext, Irp, STATUS_ACCESS_DENIED );

        DebugTrace( -1, Dbg2, ("NtfsCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n") );

        return STATUS_ACCESS_DENIED;
    }

    //
    //  The volume must be writable.
    //

    if (NtfsIsVolumeReadOnly( Vcb )) {

        Status = STATUS_MEDIA_WRITE_PROTECTED;
        NtfsCompleteRequest( IrpContext, Irp, Status );

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

#ifdef __ND_NTFS_SECONDARY__

	if (!FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )) {

		return NtfsPostRequest( IrpContext, Irp );
	}

#endif

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

    NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE );

    try {

		//
        //  Proceed only if the volume is mounted.
        //

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

#ifdef __ND_NTFS_SECONDARY__

			if(IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {

				DebugTrace( 0, DEBUG_TRACE_ALL, ("IrpSp->FileObject is NULL, IrpSp->MajorFunction = %x, IrpSp->MinorFunction = %x\n", IrpSp->MajorFunction, IrpSp->MinorFunction) );
			}
			if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

				Status = NdNtfsSecondaryCommonSetVolumeInfo( IrpContext, Irp );
				leave;
			}
#endif

			//
            //  Based on the information class we'll do different actions.  Each
            //  of the procedures that we're calling performs the action if
            //  possible and returns true if it successful and false if it couldn't
            //  wait for any I/O to complete.
            //

            switch (FsInformationClass) {

            case FileFsLabelInformation:

                Status = NtfsSetFsLabelInfo( IrpContext, Vcb, Buffer );
                break;

            case FileFsControlInformation:

                Status = NtfsSetFsControlInfo( IrpContext, Vcb, Buffer );
                break;

            case FileFsObjectIdInformation:

                Status = NtfsSetFsVolumeObjectIdInfo( IrpContext, Vcb, Buffer );
				DebugTrace( 0, Dbg2, ("NtfsCommonSetVolumeInfo %x, FileFsObjectIdInformation Vcb = %p\n", Status, IrpContext->Vcb) );
                break;

            default:

                Status = STATUS_INVALID_PARAMETER;
                break;
            }

        } else {

            Status = STATUS_FILE_INVALID;
        }

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonSetVolumeInfo );

        NtfsReleaseVcb( IrpContext, Vcb );

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

    NtfsCompleteRequest( IrpContext, Irp, Status );
    return Status;
}
示例#3
0
NTSTATUS
NtfsCommonQueryVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for query Volume Information 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;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;
    BOOLEAN AcquiredVcb = FALSE;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );
    ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));

    PAGED_CODE();

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonQueryVolumeInfo...\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.QueryVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.QueryVolume.Length;
    FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

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

    //
    //  Let's kill invalid vol. query requests.
    //

    if (UnopenedFileObject == TypeOfOpen) {

        DebugTrace( 0, Dbg2, ("Invalid file object for write\n") );
        DebugTrace( -1, Dbg2, ("NtfsCommonQueryVolume:  Exit -> %08lx\n", STATUS_INVALID_DEVICE_REQUEST) );

        NtfsCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        return STATUS_INVALID_DEVICE_REQUEST;
    }

#ifdef __ND_NTFS_SECONDARY__

	if (!FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT )) {

		return NtfsPostRequest( IrpContext, Irp );
	}

#endif

    //
    //  Get the Vcb shared and raise if we can't wait for the resource.
    //  We're only using $Volume Scb for the query size calls because the info
    //  it gets is static and we only need to protect against dismount
    //  Doing this prevents a deadlock with commit extensions from mm which use
    //  this call. However for system files like the mft we always need the vcb to avoid deadlock
    //
                         
    if ((FsInformationClass != FileFsSizeInformation) || 
        (FlagOn( Scb->Fcb->FcbState, FCB_STATE_SYSTEM_FILE ))) {
        
        NtfsAcquireSharedVcb( IrpContext, Vcb, TRUE );
        AcquiredVcb = TRUE;
    } else {
        
        NtfsAcquireSharedScb( IrpContext, Scb );
    }

    try {

        //
        //  Make sure the volume is mounted.
        //

        if ((AcquiredVcb && !FlagOn( Vcb->VcbState, VCB_STATE_VOLUME_MOUNTED )) ||
            (!AcquiredVcb && FlagOn( Scb->ScbState, SCB_STATE_VOLUME_DISMOUNTED))) {
            
            Irp->IoStatus.Information = 0;
            Status = STATUS_VOLUME_DISMOUNTED;
            leave;
        }

#ifdef __ND_NTFS_SECONDARY__

		if(IoGetCurrentIrpStackLocation(Irp)->FileObject == NULL) {

			DebugTrace( 0, DEBUG_TRACE_ALL, ("IrpSp->FileObject is NULL, IrpSp->MajorFunction = %x, IrpSp->MinorFunction = %x\n", IrpSp->MajorFunction, IrpSp->MinorFunction) );
		}

		if (IS_SECONDARY_FILEOBJECT(IoGetCurrentIrpStackLocation(Irp)->FileObject)) {

			Status = NdNtfsSecondaryCommonQueryVolumeInfo( IrpContext, Irp );
			leave;
		}
#endif
        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling fills up the output buffer
        //  if possible and returns true if it successfully filled the buffer
        //  and false if it couldn't wait for any I/O to complete.
        //

        switch (FsInformationClass) {

        case FileFsVolumeInformation:

            Status = NtfsQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsSizeInformation:

            Status = NtfsQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsDeviceInformation:

            Status = NtfsQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsAttributeInformation:

            Status = NtfsQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsControlInformation:

            Status = NtfsQueryFsControlInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsFullSizeInformation:
        
            Status = NtfsQueryFsFullSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsObjectIdInformation:
        
            Status = NtfsQueryFsVolumeObjectIdInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

        //
        //  Set the information field to the number of bytes actually filled in
        //

        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonQueryVolumeInfo );

        if (AcquiredVcb) {
            NtfsReleaseVcb( IrpContext, Vcb );
        } else  {
            NtfsReleaseScb( IrpContext, Scb );
        }   

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

	if (Status != STATUS_SUCCESS && Status != STATUS_BUFFER_OVERFLOW)
		DebugTrace( 0, Dbg2, ("NtfsCommonQueryVolumeInfo %x, FsInformationClass = %d Vcb = %p\n", Status, FsInformationClass, IrpContext->Vcb) );

    NtfsCompleteRequest( IrpContext, Irp, Status );
    return Status;
}
示例#4
0
VOID
NtfsSpecialDispatch (
    PVOID Context
    )

/*++

Routine Description:

    This routine is called when a special operation needs to be posted.
    It is called indirectly by NtfsPostSpecial.  It is assumes that the
    Vcb is protected from going away by incrementing the volemue close
    counts for a file.  If this routine fails nothing is done except
    to clean up the Vcb.  This routine also handles issues log file full
    and can't wait.

    The function to be called is stored in the PostSpecialCallout field
    of the Irp Context, and the context is stored int he OriginatingIrp.
    Both fields are zeroed before the the callout function is called.

Arguments:

    Context - Supplies a pointer to an IrpContext.

Return Value:

--*/

{
    PVCB Vcb;
    PIRP_CONTEXT IrpContext = Context;
    TOP_LEVEL_CONTEXT TopLevelContext;
    PTOP_LEVEL_CONTEXT ThreadTopLevelContext;
    POST_SPECIAL_CALLOUT PostSpecialCallout;
    PVOID SpecialContext;
    ULONG LogFileFullCount;
    BOOLEAN Retry;

    PAGED_CODE();

    FsRtlEnterFileSystem();

    do {

        Vcb = IrpContext->Vcb;
        LogFileFullCount = 0;

        //
        //  Capture the funciton pointer and context before using the IrpContext.
        //

        PostSpecialCallout = IrpContext->Union.PostSpecialCallout;
        SpecialContext = IrpContext->OriginatingIrp;
        IrpContext->Union.PostSpecialCallout = NULL;
        IrpContext->OriginatingIrp = NULL;

        ThreadTopLevelContext = NtfsInitializeTopLevelIrp( &TopLevelContext, TRUE, TRUE );
        ASSERT( ThreadTopLevelContext == &TopLevelContext );
        ASSERT( !FlagOn( IrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
        ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_ALLOC_FROM_POOL ));

        //
        //  Initialize the thread top level structure, if needed.
        //

        ASSERT( IoGetTopLevelIrp() != (PIRP) &TopLevelContext );
        NtfsUpdateIrpContextWithTopLevel( IrpContext, ThreadTopLevelContext );

        //
        //  Don't let this IrpContext be deleted.
        //

        SetFlag( IrpContext->State, IRP_CONTEXT_STATE_PERSISTENT );

        do {

            Retry = FALSE;

            try {

                //
                //  See if we failed due to a log file full condition, and
                //  if so, then do a clean volume checkpoint if we are the
                //  first ones to get there.  If we see a different Lsn and do
                //  not do the checkpoint, the worst that can happen is that we
                //  will fail again if the log file is still full.
                //

                if (IrpContext->LastRestartArea.QuadPart != 0) {

                    NtfsCheckpointForLogFileFull( IrpContext );

                    if (++LogFileFullCount >= 2) {

                        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_EXCESS_LOG_FULL );
                    }
                }

                //
                //  Call the requested function.
                //

                ASSERT( FlagOn( IrpContext->TopLevelIrpContext->State, IRP_CONTEXT_STATE_OWNS_TOP_LEVEL ));
                PostSpecialCallout( IrpContext, SpecialContext );

                NtfsCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );

            } except(NtfsExceptionFilter( IrpContext, GetExceptionInformation() )) {

                NTSTATUS ExceptionCode;

                ExceptionCode = GetExceptionCode();
                ExceptionCode = NtfsProcessException( IrpContext, NULL, ExceptionCode );

                if ((ExceptionCode == STATUS_CANT_WAIT) ||
                    (ExceptionCode == STATUS_LOG_FILE_FULL)) {

                    Retry = TRUE;
                }
            }

        } while (Retry);

        //
        //  Ok to let this IrpContext be deleted.
        //

        ClearFlag( IrpContext->State, IRP_CONTEXT_STATE_PERSISTENT );

        //
        //  At this point regardless of the status the volume needs to
        //  be cleaned up and the IrpContext freed.
        //  Dereference the Vcb and check to see if it needs to be deleted.
        //  since this call might raise wrap it with a try/execpt.
        //

        try {

            //
            //  Acquire the volume exclusive so the counts can be
            //  updated.
            //

            ASSERT( FlagOn( IrpContext->State, IRP_CONTEXT_STATE_WAIT ));
            NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE );

            InterlockedDecrement( &Vcb->SystemFileCloseCount );
            InterlockedDecrement( &Vcb->CloseCount );

            NtfsReleaseVcb( IrpContext, Vcb );

        } except( EXCEPTION_EXECUTE_HANDLER ) {

            ASSERT( FsRtlIsNtstatusExpected( GetExceptionCode() ) );
        }

        //
        //  Free the irp context.
        //

        NtfsCleanupIrpContext( IrpContext, TRUE );

        //
        //  See if there is more work on the scavenger list.
        //

        ExAcquireFastMutexUnsafe( &NtfsScavengerLock );

        ASSERT( NtfsScavengerRunning );

        IrpContext = NtfsScavengerWorkList;

        if (IrpContext != NULL) {

            //
            //  Remove the entry from the list.
            //

            NtfsScavengerWorkList = (PIRP_CONTEXT) IrpContext->WorkQueueItem.List.Flink;
            IrpContext->WorkQueueItem.List.Flink = NULL;

        } else {

            NtfsScavengerRunning = FALSE;

        }

        ExReleaseFastMutexUnsafe( &NtfsScavengerLock );

    } while ( IrpContext != NULL );

    FsRtlExitFileSystem();
}
示例#5
0
VOID
NtfsReleaseAllFiles (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN BOOLEAN ReleasePagingIo
    )

/*++

Routine Description:

    This routine non-recursively requires all files on a volume.

Arguments:

    Vcb - Supplies the volume

    ReleasePagingIo - Indicates whether we should release the paging io resources
        as well.

Return Value:

    None

--*/

{
    PFCB Fcb;
    PSCB *Scb;
    PVOID RestartKey;

    PAGED_CODE();

    //
    //  Loop to flush all of the prerestart streams, to do the loop
    //  we cycle through the Fcb Table and for each fcb we acquire it.
    //

    RestartKey = NULL;
    while (TRUE) {

        NtfsAcquireFcbTable( IrpContext, Vcb );
        Fcb = NtfsGetNextFcbTableEntry(Vcb, &RestartKey);
        NtfsReleaseFcbTable( IrpContext, Vcb );

        if (Fcb == NULL) {

            break;
        }

        ASSERT_FCB( Fcb );

        if (NtfsSegmentNumber( &Fcb->FileReference ) >= FIRST_USER_FILE_NUMBER) {

            //
            //  Release the file.
            //

            if (ReleasePagingIo && (Fcb->PagingIoResource != NULL)) {

                ExReleaseResource( Fcb->PagingIoResource );
            }

            NtfsReleaseFcb( IrpContext, Fcb );
        }
    }

    //
    //  Now release the Fcb's in the Vcb.
    //

    Scb = &Vcb->QuotaTableScb;

    while (TRUE) {

        if (*Scb != NULL) {

            if (ReleasePagingIo && ((*Scb)->Fcb->PagingIoResource != NULL)) {

                ExReleaseResource( (*Scb)->Fcb->PagingIoResource );
            }

            NtfsReleaseFcb( IrpContext, (*Scb)->Fcb );
        }

        if (Scb == &Vcb->MftScb) {

            break;
        }

        Scb -= 1;
    }

    NtfsReleaseVcb( IrpContext, Vcb );

    return;
}
示例#6
0
NTSTATUS
NtfsCommonSetVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for set Volume Information 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;
    PMyIO_STACK_LOCATION IrpSp;
    PFILE_OBJECT FileObject;

    TYPE_OF_OPEN TypeOfOpen;
    PVCB Vcb;
    PFCB Fcb;
    PSCB Scb;
    PCCB Ccb;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current Irp stack location
    //

    IrpSp = (PMyIO_STACK_LOCATION)IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonSetVolumeInfo\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.SetVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.SetVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.SetVolume.Length;
    FsInformationClass = IrpSp->Parameters.SetVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

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

    if (TypeOfOpen != UserVolumeOpen) {

        NtfsCompleteRequest( &IrpContext, &Irp, STATUS_ACCESS_DENIED );

        DebugTrace( -1, Dbg, ("NtfsCommonSetVolumeInfo -> STATUS_ACCESS_DENIED\n") );

        return STATUS_ACCESS_DENIED;
    }

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

    NtfsAcquireExclusiveVcb( IrpContext, Vcb, TRUE );

    try {

        //
        //  Proceed only if the volume is mounted.
        //

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

            //
            //  Based on the information class we'll do different actions.  Each
            //  of the procedures that we're calling performs the action if
            //  possible and returns true if it successful and false if it couldn't
            //  wait for any I/O to complete.
            //

            switch (FsInformationClass) {

            case FileFsLabelInformation:

                Status = NtfsSetFsLabelInfo( IrpContext, Vcb, Buffer );
                break;

#ifdef _CAIRO_

            case FileFsQuotaSetInformation:
    
                Status = NtfsFsQuotaSetInfo( IrpContext, Vcb, Buffer, Length );
                break;

            case FileFsControlInformation:

                Status = NtfsSetFsControlInfo( IrpContext, Vcb, Buffer );
                break;

#endif // _CAIRO_

            default:

                Status = STATUS_INVALID_PARAMETER;
                break;
            }

        } else {

            Status = STATUS_FILE_INVALID;
        }

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonSetVolumeInfo );

        NtfsReleaseVcb( IrpContext, Vcb );

        if (!AbnormalTermination()) {

            NtfsCompleteRequest( &IrpContext, &Irp, Status );
        }

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

    return Status;
}
示例#7
0
NTSTATUS
NtfsCommonQueryVolumeInfo (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for query Volume Information 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;

    ULONG Length;
    FS_INFORMATION_CLASS FsInformationClass;
    PVOID Buffer;

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    PAGED_CODE();

    //
    //  Get the current stack location
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    DebugTrace( +1, Dbg, ("NtfsCommonQueryVolumeInfo...\n") );
    DebugTrace( 0, Dbg, ("IrpContext         = %08lx\n", IrpContext) );
    DebugTrace( 0, Dbg, ("Irp                = %08lx\n", Irp) );
    DebugTrace( 0, Dbg, ("Length             = %08lx\n", IrpSp->Parameters.QueryVolume.Length) );
    DebugTrace( 0, Dbg, ("FsInformationClass = %08lx\n", IrpSp->Parameters.QueryVolume.FsInformationClass) );
    DebugTrace( 0, Dbg, ("Buffer             = %08lx\n", Irp->AssociatedIrp.SystemBuffer) );

    //
    //  Reference our input parameters to make things easier
    //

    Length = IrpSp->Parameters.QueryVolume.Length;
    FsInformationClass = IrpSp->Parameters.QueryVolume.FsInformationClass;
    Buffer = Irp->AssociatedIrp.SystemBuffer;

    //
    //  Extract and decode the file object to get the Vcb, we don't really
    //  care what the type of open is.
    //

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

    //
    //  We need exclusive access to the Vcb because we are going to verify
    //  it.  After we verify the vcb we'll convert our access to shared
    //

    NtfsAcquireSharedVcb( IrpContext, Vcb, FALSE );

    try {

        //
        //  Based on the information class we'll do different actions.  Each
        //  of the procedures that we're calling fills up the output buffer
        //  if possible and returns true if it successfully filled the buffer
        //  and false if it couldn't wait for any I/O to complete.
        //

        switch (FsInformationClass) {

        case FileFsVolumeInformation:

            Status = NtfsQueryFsVolumeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsSizeInformation:

            Status = NtfsQueryFsSizeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsDeviceInformation:

            Status = NtfsQueryFsDeviceInfo( IrpContext, Vcb, Buffer, &Length );
            break;

        case FileFsAttributeInformation:

            Status = NtfsQueryFsAttributeInfo( IrpContext, Vcb, Buffer, &Length );
            break;

#ifdef _CAIRO_
        case FileFsControlInformation:

            Status = NtfsQueryFsControlInfo( IrpContext, Vcb, Buffer, &Length );
            break;


        case FileFsQuotaQueryInformation:

            Status = NtfsFsQuotaQueryInfo( IrpContext, Vcb, Buffer, &Length );
            break;

#endif // _CAIRO_

        default:

            Status = STATUS_INVALID_PARAMETER;
            break;
        }

        //
        //  Set the information field to the number of bytes actually filled in
        //

        Irp->IoStatus.Information = IrpSp->Parameters.QueryVolume.Length - Length;

        //
        //  Abort transaction on error by raising.
        //

        NtfsCleanupTransaction( IrpContext, Status, FALSE );

    } finally {

        DebugUnwind( NtfsCommonQueryVolumeInfo );

        NtfsReleaseVcb( IrpContext, Vcb );

        if (!AbnormalTermination()) {

            NtfsCompleteRequest( &IrpContext, &Irp, Status );
        }

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

    return Status;
}