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

📄 fsctrl.c

📁 windows 2000中的UDF文件系统的驱动程序.只有读的功能,不支持未关闭的盘片.只支持UDF2.0以下版本,不支持VAT格式的UDF.
💻 C
📖 第 1 页 / 共 5 页
字号:
    //

    Vcb = Fcb->Vcb;

    UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );

    //
    //  Mark the volume as invalid, but only do it if the vcb is locked
    //  by this handle and the volume is currently mounted.  No more
    //  operations will occur on this vcb except cleanup/close.
    //

    if ((Vcb->VcbCondition != VcbMounted) &&
        (Vcb->VolumeLockFileObject != IrpSp->FileObject)) {

        Status = STATUS_NOT_IMPLEMENTED;

    } else {

        SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
        SetFlag( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );

        Status = STATUS_SUCCESS;
    }

    //
    //  Release all of our resources
    //

    UdfReleaseVcb( IrpContext, Vcb );

    if (!NT_SUCCESS( Status )) {

        FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT_FAILED );
    }

    //
    //  Complete the request if there haven't been any exceptions.
    //

    UdfCompleteRequest( IrpContext, Irp, Status );
    return Status;
}


//
//  Local support routine
//

UdfIsVolumeDirty (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine determines if a volume is currently dirty.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PIO_STACK_LOCATION IrpSp;

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

    PULONG VolumeState;
    
    //
    //  Get the current stack location and extract the output
    //  buffer information.
    //

    IrpSp = IoGetCurrentIrpStackLocation( Irp );

    //
    //  Get a pointer to the output buffer.  Look at the system buffer field in the
    //  irp first.  Then the Irp Mdl.
    //

    if (Irp->AssociatedIrp.SystemBuffer != NULL) {

        VolumeState = Irp->AssociatedIrp.SystemBuffer;

    } else if (Irp->MdlAddress != NULL) {

        VolumeState = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );

        if (NULL == VolumeState)  {
        
            UdfCompleteRequest( IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES );
            return STATUS_INSUFFICIENT_RESOURCES;
        }
    } else {

        UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_USER_BUFFER );
        return STATUS_INVALID_USER_BUFFER;
    }

    //
    //  Make sure the output buffer is large enough and then initialize
    //  the answer to be that the volume isn't dirty.
    //

    if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) {

        UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        return STATUS_INVALID_PARAMETER;
    }

    *VolumeState = 0;

    //
    //  Decode the file object
    //

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

    if (TypeOfOpen != UserVolumeOpen) {

        UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        return STATUS_INVALID_PARAMETER;
    }

    if (Fcb->Vcb->VcbCondition != VcbMounted) {

        UdfCompleteRequest( IrpContext, Irp, STATUS_VOLUME_DISMOUNTED );
        return STATUS_VOLUME_DISMOUNTED;
    }

    //
    //  Now set up to return the clean state.  If we paid attention to the dirty
    //  state of the media we could be more accurate, but since this is a readonly
    //  implementation at the moment we think it is clean all of the time.
    //
    
    Irp->IoStatus.Information = sizeof( ULONG );

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


//
//  Local support routine
//

NTSTATUS
UdfIsVolumeMounted (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine determines if a volume is currently mounted.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );

    PFCB Fcb;
    PCCB Ccb;

    PAGED_CODE();

    //
    //  Decode the file object.
    //

    UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );

    if (Fcb != NULL) {

        //
        //  Disable PopUps, we want to return any error.
        //

        SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS );

        //
        //  Verify the Vcb.  This will raise in the error condition.
        //

        UdfVerifyVcb( IrpContext, Fcb->Vcb );
    }

    UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );

    return STATUS_SUCCESS;
}


//
//  Local support routine
//

NTSTATUS
UdfIsPathnameValid (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine determines if pathname is a valid UDFS pathname.
    We always succeed this request.

Arguments:

    Irp - Supplies the Irp to process.

Return Value:

    None

--*/

{
    PAGED_CODE();

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


//
//  Local support routine
//

NTSTATUS
UdfInvalidateVolumes (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine searches for all the volumes mounted on the same real device
    of the current DASD handle, and marks them all bad.  The only operation
    that can be done on such handles is cleanup and close.

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

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

    LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};

    HANDLE Handle;

    PVPB NewVpb;
    PVCB Vcb;

    PLIST_ENTRY Links;

    PFILE_OBJECT FileToMarkBad;
    PDEVICE_OBJECT DeviceToMarkBad;

    //
    //  Check for the correct security access.
    //  The caller must have the SeTcbPrivilege.
    //

    if (!SeSinglePrivilegeCheck( TcbPrivilege, Irp->RequestorMode )) {

        UdfCompleteRequest( IrpContext, Irp, STATUS_PRIVILEGE_NOT_HELD );

        return STATUS_PRIVILEGE_NOT_HELD;
    }

    //
    //  Try to get a pointer to the device object from the handle passed in.
    //

    if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( HANDLE )) {

        UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
        return STATUS_INVALID_PARAMETER;
    }

    Handle = *((PHANDLE) Irp->AssociatedIrp.SystemBuffer);

    Status = ObReferenceObjectByHandle( Handle,
                                        0,
                                        *IoFileObjectType,
                                        KernelMode,
                                        &FileToMarkBad,
                                        NULL );

    if (!NT_SUCCESS(Status)) {

        UdfCompleteRequest( IrpContext, Irp, Status );
        return Status;
    }

    //
    //  Grab the DeviceObject from the FileObject.
    //

    DeviceToMarkBad = FileToMarkBad->DeviceObject;

    //
    //  We only needed the device object involved, not a reference to the file.
    //

    ObDereferenceObject( FileToMarkBad );

    //
    //  Create a new Vpb for this device so that any new opens will mount
    //  a new volume.
    //

    NewVpb = ExAllocatePoolWithTag( NonPagedPoolMustSucceed, sizeof( VPB ), TAG_VPB );
    RtlZeroMemory( NewVpb, sizeof( VPB ) );

    NewVpb->Type = IO_TYPE_VPB;
    NewVpb->Size = sizeof( VPB );
    NewVpb->RealDevice = DeviceToMarkBad;
    NewVpb->Flags = FlagOn( DeviceToMarkBad->Vpb->Flags, VPB_REMOVE_PENDING );

    //
    //  Make sure this request can wait.
    //

    SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );

    UdfAcquireUdfData( IrpContext );

    //
    //  Nothing can go wrong now.
    //

    IoAcquireVpbSpinLock( &SavedIrql );
    DeviceToMarkBad->Vpb = NewVpb;
    IoReleaseVpbSpinLock( SavedIrql );

    //
    //  Now walk through all the mounted Vcb's looking for candidates to
    //  mark invalid.
    //
    //  On volumes we mark invalid, check for dismount possibility (which is
    //  why we have to get the next link so early).
    //

    Links = UdfData.VcbQueue.Flink;

    while (Links != &UdfData.VcbQueue) {

        Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks);

        Links = Links->Flink;

        //
        //  If we get a match, mark the volume Bad, and also check to
        //  see if the volume should go away.
        //

        UdfLockVcb( IrpContext, Vcb );

        if (Vcb->Vpb->RealDevice == DeviceToMarkBad) {

            if (Vcb->VcbCondition != VcbDismountInProgress) {
                
                Vcb->VcbCondition = VcbInvalid;
            }

            UdfUnlockVcb( IrpContext, Vcb );

            UdfPurgeVolume( IrpContext, Vcb, FALSE );

            UdfCheckForDismount( IrpContext, Vcb, FALSE );

        } else {

            UdfUnlockVcb( IrpContext, Vcb );
        }
    }

    UdfReleaseUdfData( IrpContext );

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


//
//  Local support routine
//

NTSTATUS
UdfMountVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

    This routine performs the mount volume operation.  It is responsible for
    either completing of enqueuing the input Irp.

    Its job is to verify that the volume denoted in the IRP is a UDF volume,
    and create the VCB and root directory FCB structures.  The algorithm it
    uses is essentially as follows:

    1. Create a new Vcb Structure, and initialize it enough to do I/O
       through the on-disk volume descriptors.

    2. Read the disk and check if it is a UDF volume.

    3. If it is not a UDF volume then delete the Vcb and
       complete the IRP with STATUS_UNRECOGNIZED_VOLUME

    4. Check if the volume was previously mounted and if it was then do a
       remount operation.  This involves deleting the VCB, hook in the
       old VCB, and complete the IRP.

    5. Otherwise create a Vcb and root directory FCB

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    NTSTATUS Status;

    PVOLUME_DEVICE_OBJECT VolDo = NULL;
    PVCB Vcb = NULL;
    PVCB OldVcb = NULL;
    PPCB Pcb = NULL;

    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    PDEVICE_OBJECT DeviceObjectWeTalkTo = IrpSp->Parameters.MountVolume.DeviceObject;
    PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb;

    PFILE_OBJECT FileObjectToNotify = NULL;

    ULONG MediaChangeCount = 0;

    DISK_GEOMETRY DiskGeometry;

    PNSR_ANCHOR AnchorVolumeDescriptor = NULL;
    PNSR_PVD PrimaryVolumeDescriptor = NULL;
    PNSR_LVOL LogicalVolumeDescriptor = NULL;
    PNSR_FSD FileSetDescriptor = NULL;

    BOOLEAN BridgeMedia;

    PAGED_CODE();

    //
    //  Check the input parameters
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_IRP( Irp );

    //
    //  Check that we are talking to a Cdrom or Disk device.  This request should
    //  always be waitable.
    //

⌨️ 快捷键说明

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