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

📄 fsctrl.c

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

    UdfCompleteRequest( IrpContext, Irp, Status );
    DebugTrace(( -1, Dbg, "UdfMountVolume -> %08x\n", Status ));

    return Status;
}


//
//  Local support routine
//

NTSTATUS
UdfVerifyVolume (
    IN PIRP_CONTEXT IrpContext,
    IN PIRP Irp
    )

/*++

Routine Description:

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

Arguments:

    Irp - Supplies the Irp to process

Return Value:

    NTSTATUS - The return status for the operation

--*/

{
    PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    PVPB Vpb = IrpSp->Parameters.VerifyVolume.Vpb;
    PVCB Vcb = &((PVOLUME_DEVICE_OBJECT) IrpSp->Parameters.VerifyVolume.DeviceObject)->Vcb;

    PPCB Pcb = NULL;

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

    ULONG MediaChangeCount = 0;
    ULONG Index;

    PFILE_OBJECT FileObjectToNotify = NULL;

    BOOLEAN ReturnError;
    BOOLEAN ReleaseVcb;

    IO_STATUS_BLOCK Iosb;

    WCHAR VolumeLabel[ MAXIMUM_VOLUME_LABEL_LENGTH / sizeof( WCHAR )];
    USHORT VolumeLabelLength;
    ULONG VolumeSerialNumber;

    NTSTATUS Status;

    PAGED_CODE();

    //
    //  Check input.
    //

    ASSERT_IRP_CONTEXT( IrpContext );

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

    ASSERT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ||
            Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK );

    ASSERT_VCB( Vcb );

    //
    //  Update the real device in the IrpContext from the Vpb.  There was no available
    //  file object when the IrpContext was created.
    //

    IrpContext->RealDevice = Vpb->RealDevice;

    //
    //  Acquire shared global access, the termination handler for the
    //  following try statement will free the access.
    //

    UdfAcquireUdfData( IrpContext );
    UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    ReleaseVcb = TRUE;

    DebugTrace(( +1, Dbg, "UdfVerifyVolume, Vcb %08x\n", Vcb ));

    try {

        //
        //  Check if the real device still needs to be verified.  If it doesn't
        //  then obviously someone beat us here and already did the work
        //  so complete the verify irp with success.  Otherwise reenable
        //  the real device and get to work.
        //

        if (!FlagOn( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME )) {

            DebugTrace(( 0, Dbg, "UdfVerifyVolume, verify bit was cleared out ahead of us\n" ));

            MediaChangeCount = Vcb->MediaChangeCount;
            try_leave( Status = STATUS_SUCCESS );
        }

        //
        //  Verify that there is a disk here.
        //

        Status = UdfPerformDevIoCtrl( IrpContext,
                                      ( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
                                        IOCTL_CDROM_CHECK_VERIFY :
                                        IOCTL_DISK_CHECK_VERIFY ),
                                      Vcb->TargetDeviceObject,
                                      &MediaChangeCount,
                                      sizeof(ULONG),
                                      FALSE,
                                      TRUE,
                                      &Iosb );

        if (!NT_SUCCESS( Status )) {

            DebugTrace(( 0, Dbg, "UdfVerifyVolume, CHECK_VERIFY failed\n" ));

            //
            //  If we will allow a raw mount then return WRONG_VOLUME to
            //  allow the volume to be mounted by raw.
            //

            if (FlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT )) {

                DebugTrace(( 0, Dbg, "UdfVerifyVolume, ... allowing raw mount\n" ));

                Status = STATUS_WRONG_VOLUME;
            }

            try_leave( Status );
        }

        if (Iosb.Information != sizeof(ULONG)) {

            //
            //  Be safe about the count in case the driver didn't fill it in
            //

            MediaChangeCount = 0;
        }

        //
        //  Verify that the device actually saw a change. If the driver does not
        //  support the MCC, then we must verify the volume in any case.
        //

        if (MediaChangeCount == 0 || Vcb->MediaChangeCount != MediaChangeCount) {

            //
            //  Now we need to navigate the disc to find the relavent decriptors.  This is
            //  much the same as the mount process.
            //

            //
            //  Find the AVD.
            //

            Status = UdfFindAnchorVolumeDescriptor( IrpContext,
                                                    Vcb,
                                                    &AnchorVolumeDescriptor );

            if (!NT_SUCCESS(Status)) {
                
                DebugTrace(( 0, Dbg, "UdfVerifyVolume, No AVD visible\n" ));
                try_leave( Status = STATUS_WRONG_VOLUME );
            }
            
            //
            //  Get the prevailing descriptors out of the VDS, building a fresh Pcb.
            //

            Status = UdfFindVolumeDescriptors( IrpContext,
                                               Vcb,
                                               &AnchorVolumeDescriptor->Main,
                                               &Pcb,
                                               &PrimaryVolumeDescriptor,
                                               &LogicalVolumeDescriptor );

            //
            //  Try the reserve sequence in case of error.
            //

            if (Status == STATUS_DISK_CORRUPT_ERROR) {

                Status = UdfFindVolumeDescriptors( IrpContext,
                                                   Vcb,
                                                   &AnchorVolumeDescriptor->Reserve,
                                                   &Pcb,
                                                   &PrimaryVolumeDescriptor,
                                                   &LogicalVolumeDescriptor );
            }

            //
            //  If we're totally unable to find a VDS, give up.
            //

            if (!NT_SUCCESS(Status)) {

                DebugTrace(( 0, Dbg, "UdfVerifyVolume, PVD/LVD/PD pickup failed\n" ));

                try_leave( Status = STATUS_WRONG_VOLUME );
            }

            //
            //  Now go complete initialization of the Pcb so we can compare it.
            //

            Status = UdfCompletePcb( IrpContext,
                                     Vcb,
                                     Pcb );

            if (!NT_SUCCESS(Status)) {

                DebugTrace(( 0, Dbg, "UdfVerifyVolume, Pcb completion failed\n" ));

                try_leave( Status = STATUS_WRONG_VOLUME );
            }

            //
            //  Now let's compare this new Pcb to the previous Vcb's Pcb to see if they
            //  appear to be equivalent.
            //

            if (!UdfEquivalentPcb( IrpContext,
                                   Pcb,
                                   Vcb->Pcb)) {

                DebugTrace(( 0, Dbg, "UdfVerifyVolume, Pcbs are not equivalent\n" ));

                try_leave( Status = STATUS_WRONG_VOLUME );
            }

            //
            //  At this point we know that the Vcb's Pcb is OK for mapping to find the fileset
            //  descriptor, so we can drop the new one we built for comparison purposes.
            //

            UdfDeletePcb( Pcb );
            Pcb = NULL;

            //
            //  Go pick up the fileset descriptor.
            //

            Status = UdfFindFileSetDescriptor( IrpContext,
                                               Vcb,
                                               &LogicalVolumeDescriptor->FSD,
                                               &FileSetDescriptor );

            if (!NT_SUCCESS(Status)) {

                try_leave( Status = STATUS_WRONG_VOLUME );
            }

            //
            //  Now that everything is in place, build a volume label and serial number from these
            //  descriptors and perform the final check that this Vcb is (or is not) the right one
            //  for the media now in the drive.
            //

            UdfUpdateVolumeLabel( IrpContext,
                                  VolumeLabel,
                                  &VolumeLabelLength,
                                  LogicalVolumeDescriptor->VolumeID,
                                  sizeof( LogicalVolumeDescriptor->VolumeID ));

            UdfUpdateVolumeSerialNumber( IrpContext,
                                         &VolumeSerialNumber,
                                         FileSetDescriptor );

            if (Vcb->Vpb->SerialNumber != VolumeSerialNumber ||
                Vcb->Vpb->VolumeLabelLength != VolumeLabelLength ||
                RtlCompareMemory( Vcb->Vpb->VolumeLabel,
                                  VolumeLabel,
                                  VolumeLabelLength )) {

                DebugTrace(( 0, Dbg, "UdfVerifyVolume, volume label/sn mismatch\n" ));

                try_leave( Status = STATUS_WRONG_VOLUME );
            }
        }

        //
        //  The volume is OK, clear the verify bit.
        //

        DebugTrace(( 0, Dbg, "UdfVerifyVolume, looks like the same volume\n" ));

        Vcb->VcbCondition = VcbMounted;

        ClearFlag( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );

        //
        //  See if we will need to provide notification of the remount.  This is the readonly
        //  filesystem's form of dismount/mount notification.
        //

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

            ClearFlag( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
            
            FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
            ObReferenceObject( FileObjectToNotify );
        }
        
    } finally {

        //
        //  If we did not raise an exception, update the current Vcb.
        //

        if (!AbnormalTermination()) {

            //
            //  Update the media change count to note that we have verified the volume
            //  at this value
            //

            Vcb->MediaChangeCount = MediaChangeCount;

            //
            //  Mark the Vcb as not mounted.
            //

            if (Status == STATUS_WRONG_VOLUME) {

                Vcb->VcbCondition = VcbNotMounted;
		
		//
		//  Now, if there are no user handles to the volume, try to spark
		//  teardown by purging the volume.
		//

		if (Vcb->VcbCleanup == 0) {

		    if (NT_SUCCESS( UdfPurgeVolume( IrpContext, Vcb, FALSE ))) {

			ReleaseVcb = UdfCheckForDismount( IrpContext, Vcb, FALSE );
		    }
		}
            }
        }

        DebugTrace(( -1, Dbg, "UdfVerifyVolume -> %08x\n", Status ));

        if (ReleaseVcb) {
	    
	    UdfReleaseVcb( IrpContext, Vcb );
	}

        UdfReleaseUdfData( IrpContext );

	//
        //  Delete the Pcb if built.
        //

        if (Pcb != NULL) {

            UdfDeletePcb( Pcb );
        }

        UdfFreePool( &AnchorVolumeDescriptor );
        UdfFreePool( &PrimaryVolumeDescriptor );
        UdfFreePool( &LogicalVolumeDescriptor );
        UdfFreePool( &FileSetDescriptor );
    }

    //
    //  Now send mount notification.
    //
    
    if (FileObjectToNotify) {

        FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
        ObDereferenceObject( FileObjectToNotify );
    }
    
    //
    //  Complete the request if no exception.
    //

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


//
//  Local support routine
//

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

/*++

Routine Description:

    This routine walks through the links of the Vcb chain in the global
    data structure.  The remount condition is met when the following
    conditions are all met:

            1 - The 32 serial for this VPB matches that in a previous
                VPB.

            2 - The volume label for this VPB matches that in the previous
                VPB.

            3 - The system pointer to the real device object in the current
                VPB matches that in the same previous VPB.

            4 - Finally the previous Vcb cannot be invalid or have a dismount
                underway.

    If a VPB is found which matches these conditions, then the address of
    the Vcb for that VPB is returned via the pointer OldVcb.

    Skip over the current Vcb.

Arguments:

    Vcb - This is the Vcb we are checking for a remount.

    OldVcb -  A pointer to the address to store the address for the Vcb
              for the volume if this is a remount.  (This is a pointer to
              a pointer)

Return Value:

    BOOLEAN - TRUE if this is in fact a remount, FALSE otherwise.

--*/

{
    PLIST_ENTRY Link;

    PVPB Vpb = Vcb->Vpb;
    PVPB OldVpb;

    BOOLEAN Remount = FALSE;

    PAGED_CODE();

    //
    //  Check input.
    //

    ASSERT_IRP_CONTEXT( IrpContext );
    ASSERT_VCB( Vcb );

    DebugTrace(( +1, Dbg, "UdfIsRemount, Vcb %08x\n", Vcb ));

    for (Link = UdfData.VcbQueue.Flink;
         Link != &UdfData.VcbQueue;
         Link = Link->Flink) {

        *OldVcb = CONTAINING_RECORD( Link, VCB, VcbLinks );

        //
        //  Skip ourselves.
        //

        if (Vcb == *OldVcb) { continue; }

        //
        //  Look at the Vpb and state of the previous Vcb.
        //

        OldVpb = (*OldVcb)->Vpb;

        if ((OldVpb != Vpb) &&
            (OldVpb->RealDevice == Vpb->RealDevice) &&
            ((*OldVcb)->VcbCondition == VcbNotMounted)) {

            //
            //  Go ahead and compare serial numbers and volume label.
            //

            if ((OldVpb->SerialNumber == Vpb->SerialNumber) &&
                       (Vpb->VolumeLabelLength == OldVpb->VolumeLabelLength) &&
               

⌨️ 快捷键说明

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