⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fsctrl.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
/*++

Copyright (c) 1989-2000 Microsoft Corporation

Module Name:

    FsCtrl.c

Abstract:

    This module implements the File System Control routines for Cdfs called
    by the Fsd/Fsp dispatch drivers.


--*/

#include "CdProcs.h"

//
//  The Bug check file id for this module
//

#define BugCheckFileId                   (CDFS_BUG_CHECK_FSCTRL)

//
//  Local constants
//

BOOLEAN CdDisable = FALSE;
BOOLEAN CdNoJoliet = FALSE;

//
//  Local support routines
//

NTSTATUS
CdUserFsctl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

VOID
CdReMountOldVcb(
    IN PIRP_CONTEXT IrpContext,
    IN PVCB OldVcb,
    IN PVCB NewVcb,
    IN PDEVICE_OBJECT DeviceObjectWeTalkTo
    );

NTSTATUS
CdMountVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdVerifyVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdOplockRequest (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdLockVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdUnlockVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdDismountVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

int
CdIsVolumeDirty (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdIsVolumeMounted (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdIsPathnameValid (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

NTSTATUS
CdInvalidateVolumes (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    );

VOID
CdScanForDismountedVcb (
    IN PIRP_CONTEXT IrpContext
    );

BOOLEAN
CdFindPrimaryVd (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PCHAR RawIsoVd,
    IN ULONG BlockFactor,
    IN BOOLEAN ReturnOnError,
    IN BOOLEAN VerifyVolume
    );

BOOLEAN
CdIsRemount (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    OUT PVCB *OldVcb
    );

VOID
CdFindActiveVolDescriptor (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN OUT PCHAR RawIsoVd,
    IN BOOLEAN VerifyVolume
    );

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, CdCommonFsControl)
#pragma alloc_text(PAGE, CdDismountVolume)
#pragma alloc_text(PAGE, CdFindActiveVolDescriptor)
#pragma alloc_text(PAGE, CdFindPrimaryVd)
#pragma alloc_text(PAGE, CdIsPathnameValid)
#pragma alloc_text(PAGE, CdIsRemount)
#pragma alloc_text(PAGE, CdIsVolumeDirty)
#pragma alloc_text(PAGE, CdIsVolumeMounted)
#pragma alloc_text(PAGE, CdLockVolume)
#pragma alloc_text(PAGE, CdMountVolume)
#pragma alloc_text(PAGE, CdOplockRequest)
#pragma alloc_text(PAGE, CdScanForDismountedVcb)
#pragma alloc_text(PAGE, CdUnlockVolume)
#pragma alloc_text(PAGE, CdUserFsctl)
#pragma alloc_text(PAGE, CdVerifyVolume)
#endif


//
//  Local support routine
//

NTSTATUS
CdLockVolumeInternal (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_OBJECT FileObject OPTIONAL
    )

/*++

Routine Description:

    This routine performs the actual lock volume operation.  It will be called
    by anyone wishing to try to protect the volume for a long duration.  PNP
    operations are such a user.
    
    The volume must be held exclusive by the caller.

Arguments:

    Vcb - The volume being locked.
    
    FileObject - File corresponding to the handle locking the volume.  If this
        is not specified, a system lock is assumed.

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    KIRQL SavedIrql;
    NTSTATUS FinalStatus = (FileObject? STATUS_ACCESS_DENIED: STATUS_DEVICE_BUSY);
    ULONG RemainingUserReferences = (FileObject? 1: 0);

    //
    //  The cleanup count for the volume only reflects the fileobject that
    //  will lock the volume.  Otherwise, we must fail the request.
    //
    //  Since the only cleanup is for the provided fileobject, we will try
    //  to get rid of all of the other user references.  If there is only one
    //  remaining after the purge then we can allow the volume to be locked.
    //
    
    CdPurgeVolume( IrpContext, Vcb, FALSE );

    //
    //  Now back out of our synchronization and wait for the lazy writer
    //  to finish off any lazy closes that could have been outstanding.
    //
    //  Since we purged, we know that the lazy writer will issue all
    //  possible lazy closes in the next tick - if we hadn't, an otherwise
    //  unopened file with a large amount of dirty data could have hung
    //  around for a while as the data trickled out to the disk.
    //
    //  This is even more important now since we send notification to
    //  alert other folks that this style of check is about to happen so
    //  that they can close their handles.  We don't want to enter a fast
    //  race with the lazy writer tearing down his references to the file.
    //

    CdReleaseVcb( IrpContext, Vcb );

    Status = CcWaitForCurrentLazyWriterActivity();

    //
    //  This is intentional. If we were able to get the Vcb before, just
    //  wait for it and take advantage of knowing that it is OK to leave
    //  the flag up.
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    
    if (!NT_SUCCESS( Status )) {

        return Status;
    }

    CdFspClose( Vcb );

    //
    //  If the volume is already explicitly locked then fail.  We use the
    //  Vpb locked flag as an 'explicit lock' flag in the same way as Fat.
    //

    IoAcquireVpbSpinLock( &SavedIrql ); 
        
    if (!FlagOn( Vcb->Vpb->Flags, VPB_LOCKED ) && 
        (Vcb->VcbCleanup == RemainingUserReferences) &&
        (Vcb->VcbUserReference == CDFS_RESIDUAL_USER_REFERENCE + RemainingUserReferences))  {

        SetFlag( Vcb->VcbState, VCB_STATE_LOCKED );
        SetFlag( Vcb->Vpb->Flags, VPB_LOCKED);
        Vcb->VolumeLockFileObject = FileObject;
        FinalStatus = STATUS_SUCCESS;
    }
    
    IoReleaseVpbSpinLock( SavedIrql );  
    
    return FinalStatus;
}


NTSTATUS
CdUnlockVolumeInternal (
    IN PIRP_CONTEXT IrpContext,
    IN PVCB Vcb,
    IN PFILE_OBJECT FileObject OPTIONAL
    )

/*++

Routine Description:

    This routine performs the actual unlock volume operation. 
    
    The volume must be held exclusive by the caller.

Arguments:

    Vcb - The volume being locked.
    
    FileObject - File corresponding to the handle locking the volume.  If this
        is not specified, a system lock is assumed.

Return Value:

    NTSTATUS - The return status for the operation
    
    Attempting to remove a system lock that did not exist is OK.

--*/

{
    NTSTATUS Status = STATUS_NOT_LOCKED;
    KIRQL SavedIrql;

    //
    //  Note that we check the VPB_LOCKED flag here rather than the Vcb
    //  lock flag.  The Vpb flag is only set for an explicit lock request,  not
    //  for the implicit lock obtained on a volume open with zero share mode.
    //
    
    IoAcquireVpbSpinLock( &SavedIrql ); 
 
    if (FlagOn(Vcb->Vpb->Flags, VPB_LOCKED) && 
        (FileObject == Vcb->VolumeLockFileObject))  {

        ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
        ClearFlag( Vcb->Vpb->Flags, VPB_LOCKED);
        Vcb->VolumeLockFileObject = NULL;
        Status = STATUS_SUCCESS;
    }
    
    IoReleaseVpbSpinLock( SavedIrql );  

    return Status;
}


NTSTATUS
CdCommonFsControl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This is the common routine for doing FileSystem 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 = IoGetCurrentIrpStackLocation( Irp );

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

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    PAGED_CODE();

    //
    //  We know this is a file system control so we'll case on the
    //  minor function, and call a internal worker routine to complete
    //  the irp.
    //

    switch (IrpSp->MinorFunction) {

    case IRP_MN_USER_FS_REQUEST:

        Status = CdUserFsctl( IrpContext, Irp );
        break;

    case IRP_MN_MOUNT_VOLUME:

        Status = CdMountVolume( IrpContext, Irp );
        break;

    case IRP_MN_VERIFY_VOLUME:

        Status = CdVerifyVolume( IrpContext, Irp );
        break;

    default:

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return Status;
}


//
//  Local support routine
//

NTSTATUS
CdUserFsctl (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )
/*++

Routine Description:

    This is the common routine for implementing the user's requests made
    through NtFsControlFile.

Arguments:

    Irp - Supplies the Irp being processed

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

    PAGED_CODE();

    //
    //  Case on the control code.
    //

    switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) {

    case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
    case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
    case FSCTL_REQUEST_BATCH_OPLOCK :
    case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
    case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
    case FSCTL_OPLOCK_BREAK_NOTIFY :
    case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
    case FSCTL_REQUEST_FILTER_OPLOCK :

        Status = CdOplockRequest( IrpContext, Irp );
        break;

    case FSCTL_LOCK_VOLUME :

        Status = CdLockVolume( IrpContext, Irp );
        break;

    case FSCTL_UNLOCK_VOLUME :

        Status = CdUnlockVolume( IrpContext, Irp );
        break;

    case FSCTL_DISMOUNT_VOLUME :

        Status = CdDismountVolume( IrpContext, Irp );
        break;

    case FSCTL_IS_VOLUME_DIRTY :

        Status = CdIsVolumeDirty( IrpContext, Irp );
        break;

    case FSCTL_IS_VOLUME_MOUNTED :

        Status = CdIsVolumeMounted( IrpContext, Irp );
        break;

    case FSCTL_IS_PATHNAME_VALID :

        Status = CdIsPathnameValid( IrpContext, Irp );
        break;

    case FSCTL_INVALIDATE_VOLUMES :

        Status = CdInvalidateVolumes( IrpContext, Irp );
        break;


    //
    //  We don't support any of the known or unknown requests.
    //

    default:

        CdCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
        Status = STATUS_INVALID_DEVICE_REQUEST;
        break;
    }

    return Status;
}


VOID
CdReMountOldVcb(
    IN PIRP_CONTEXT IrpContext,
    IN PVCB OldVcb,
    IN PVCB NewVcb,
    IN PDEVICE_OBJECT DeviceObjectWeTalkTo
    )
{
    KIRQL SavedIrql;
    ULONG Index;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -