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

📄 fsctrl.c

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

    ASSERT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ||
            Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK );
    ASSERT( FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ));

    DebugTrace(( +1, Dbg, "UdfMountVolume\n" ));

    //
    //  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;

    //
    //  Check if we have disabled the mount process.
    //

    if (UdfDisable) {

        UdfCompleteRequest( IrpContext, Irp, STATUS_UNRECOGNIZED_VOLUME );
        DebugTrace(( 0, Dbg, "UdfMountVolume, disabled\n" ));
        DebugTrace(( -1, Dbg, "UdfMountVolume -> STATUS_UNRECOGNIZED_VOLUME\n" ));

        return STATUS_UNRECOGNIZED_VOLUME;
    }

    //
    //  Do a CheckVerify here to lift the MediaChange ticker from the driver
    //

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

    if (!NT_SUCCESS( Status )) {
        
        UdfCompleteRequest( IrpContext, Irp, Status );
        DebugTrace(( 0, Dbg,
                     "UdfMountVolume, CHECK_VERIFY handed back status %08x (so don't continue)\n",
                     Status ));
        DebugTrace(( -1, Dbg,
                     "UdfMountVolume -> %08x\n",
                     Status ));

        return Status;
    }
    
    //
    //  Now let's make Jeff delirious and call to get the disk geometry.  This
    //  will fix the case where the first change line is swallowed.
    //
    //  This IOCTL does not have a generic STORAGE equivalent, so we must figure
    //  our which variant to pass down from the real underlying device object (as
    //  opposed to the top of the driver filter stack we will really be attaching
    //  on top of).
    //

    Status = UdfPerformDevIoCtrl( IrpContext,
                                  ( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
                                    IOCTL_CDROM_GET_DRIVE_GEOMETRY :
                                    IOCTL_DISK_GET_DRIVE_GEOMETRY ),
                                  DeviceObjectWeTalkTo,
                                  &DiskGeometry,
                                  sizeof( DISK_GEOMETRY ),
                                  FALSE,
                                  TRUE,
                                  NULL );

    //
    //  If this call failed, we might be able to get away with a heuristic guess as to
    //  what the sector size is (per CDFS), but that is playing with fire.  Nearly every
    //  failure here will be a permanent problem of some form.
    //

    if (!NT_SUCCESS( Status )) {

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

        return Status;
    }

    //
    //  Acquire the global resource to do mount operations.
    //

    UdfAcquireUdfData( IrpContext );

    //
    //  Use a try-finally to facilitate cleanup.
    //

    try {

        //
        //  Do a quick check to see if there any Vcb's which can be removed.
        //

        UdfScanForDismountedVcb( IrpContext );

        //
        //  Make sure that the driver/drive is not screwing up underneath of us by
        //  feeding us garbage for the sector size.
        //

        if (DiskGeometry.BytesPerSector == 0 ||
            (DiskGeometry.BytesPerSector & ~( 1 << UdfHighBit( DiskGeometry.BytesPerSector ))) != 0) {

            DebugTrace(( 0, 0,
                         "UdfMountVolume, bad DiskGeometry (%08x) .BytesPerSector == %08x\n",
                         &DiskGeometry,
                         DiskGeometry.BytesPerSector ));

            ASSERT( FALSE );

            try_leave( Status = STATUS_DRIVER_INTERNAL_ERROR );
        }

        //
        //  Now go confirm that this volume may be a UDF image by looking for a
        //  valid ISO 13346 Volume Recognition Sequence.
        //

        if (!UdfRecognizeVolume( IrpContext,
                                 DeviceObjectWeTalkTo,
                                 DiskGeometry.BytesPerSector,
                                 &BridgeMedia )) {

            DebugTrace(( 0, Dbg, "UdfMountVolume, recognition failed so not mounting\n" ));

            try_leave( Status = STATUS_UNRECOGNIZED_VOLUME );
        }

        //
        //  Create the DeviceObject for this mount attempt
        //

        Status = IoCreateDevice( UdfData.DriverObject,
                                 sizeof( VOLUME_DEVICE_OBJECT ) - sizeof( DEVICE_OBJECT ),
                                 NULL,
                                 FILE_DEVICE_CD_ROM_FILE_SYSTEM,
                                 0,
                                 FALSE,
                                 (PDEVICE_OBJECT *) &VolDo );

        if (!NT_SUCCESS( Status )) {

            DebugTrace(( 0, Dbg, "UdfMountVolume, couldn't get voldo! (%08x)\n", Status ));
            try_leave( Status );
        }

        //
        //  Our alignment requirement is the larger of the processor alignment requirement
        //  already in the volume device object and that in the DeviceObjectWeTalkTo
        //

        if (DeviceObjectWeTalkTo->AlignmentRequirement > VolDo->DeviceObject.AlignmentRequirement) {

            VolDo->DeviceObject.AlignmentRequirement = DeviceObjectWeTalkTo->AlignmentRequirement;
        }

        ClearFlag( VolDo->DeviceObject.Flags, DO_DEVICE_INITIALIZING );

        //
        //  Initialize the overflow queue for the volume
        //

        VolDo->OverflowQueueCount = 0;
        InitializeListHead( &VolDo->OverflowQueue );

        VolDo->PostedRequestCount = 0;
        KeInitializeSpinLock( &VolDo->OverflowQueueSpinLock );

        //
        //  Now before we can initialize the Vcb we need to set up the
        //  device object field in the VPB to point to our new volume device
        //  object.
        //

        Vpb->DeviceObject = (PDEVICE_OBJECT) VolDo;

        //
        //  Initialize the Vcb.  This routine will raise on an allocation
        //  failure.
        //

        UdfInitializeVcb( IrpContext,
                          &VolDo->Vcb,
                          DeviceObjectWeTalkTo,
                          Vpb,
                          &DiskGeometry,
                          MediaChangeCount );

        //
        //  We must initialize the stack size in our device object before
        //  the following reads, because the I/O system has not done it yet.
        //

        ((PDEVICE_OBJECT) VolDo)->StackSize = (CCHAR) (DeviceObjectWeTalkTo->StackSize + 1);

        //
        //  Pick up a local pointer to the new Vcb.  Here is where we start
        //  thinking about cleanup of structures if the mount is failed.
        //

        Vcb = &VolDo->Vcb;
        Vpb = NULL;
        VolDo = NULL;

        //
        //  Store the Vcb in the IrpContext as we didn't have one before.
        //

        IrpContext->Vcb = Vcb;

        UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );

        //
        //  Let's reference the Vpb to make sure we are the one to
        //  have the last dereference.
        //

        Vcb->Vpb->ReferenceCount += 1;

        //
        //  Clear the verify bit for the start of mount.
        //

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

        //
        //  Now find the multi-session bounds on this media.
        //

        UdfDetermineVolumeBounding( IrpContext,
                                    Vcb,
                                    &Vcb->BoundS,
                                    &Vcb->BoundN );

        //
        //  Now find the Anchor Volume Descriptor so we can discover the Volume Set
        //  Descriptor Sequence extent.
        //

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

        if (!NT_SUCCESS(Status)) {

            DebugTrace(( 0, Dbg, "UdfMountVolume, couldn't find anchor descriptors\n" ));
            try_leave( Status );
        }

        //
        //  Now search for the prevailing copies of the PVD, LVD, and related PD in the
        //  extents indicated by the AVD.
        //

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

        //
        //  If we discovered invalid structures on the main extent, we may still
        //  be able to use the reserve extent.  By definition the two extents
        //  must be logically equal, so just plow into it on any error.
        //

        if (!NT_SUCCESS( Status )) {

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

        if (!NT_SUCCESS(Status)) {

            DebugTrace(( 0, Dbg, "UdfMountVolume, couldn't find good VSD descriptors (PVD/LVD/PD)\n" ));
            try_leave( Status );
        }

        //
        //  Now go complete initialization of the Pcb.  After this point, we can perform
        //  physical partition mappings and know that the partition table is good.
        //

        Status = UdfCompletePcb( IrpContext,
                                 Vcb,
                                 Pcb );

        if (!NT_SUCCESS(Status)) {

            DebugTrace(( 0, Dbg, "UdfMountVolume, Pcb completion failed\n" ));
            try_leave( Status );
        }

        Vcb->Pcb = Pcb;
        Pcb = NULL;

        //
        //  Set up all the support we need to do reads into the volume.
        //

        UdfUpdateVcbPhase0( IrpContext, Vcb );

        //
        //  Now go get the fileset descriptor that will finally reveal the location
        //  of the root directory on this volume.
        //

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

        if (!NT_SUCCESS(Status)) {

            try_leave( NOTHING );
        }

        //
        //  Now that we have everything together, update the Vpb with identification
        //  of this volume.
        //

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

        UdfUpdateVolumeSerialNumber( IrpContext,
                                     &Vcb->Vpb->SerialNumber,
                                     FileSetDescriptor );

        //
        //  Check if this is a remount operation.  If so then clean up
        //  the data structures passed in and created here.
        //

        if (UdfIsRemount( IrpContext, Vcb, &OldVcb )) {

            //
            //  Link the old Vcb to point to the new device object that we
            //  should be talking to, dereferencing the previous.
            //

            ObDereferenceObject( OldVcb->TargetDeviceObject );

            Vcb->Vpb->RealDevice->Vpb = OldVcb->Vpb;

            OldVcb->Vpb->RealDevice = Vcb->Vpb->RealDevice;

            OldVcb->TargetDeviceObject = DeviceObjectWeTalkTo;
            OldVcb->VcbCondition = VcbMounted;

            OldVcb->MediaChangeCount = Vcb->MediaChangeCount;

            //
            //  Push the state of the method 2 bit across.  In changing the device,
            //  we may now be on one with a different requirement.
            //

            ClearFlag( OldVcb->VcbState, VCB_STATE_METHOD_2_FIXUP );
            SetFlag( OldVcb->VcbState, FlagOn( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP ));
            
            //
            //  See if we will need to provide notification of the remount.  This is the readonly
            //  filesystem's form of dismount/mount notification - we promise that whenever a
            //  volume is "dismounted", that a mount notification will occur when it is revalidated.
            //  Note that we do not send mount on normal remounts - that would duplicate the media
            //  arrival notification of the device driver.
            //
    
            if (FlagOn( OldVcb->VcbState, VCB_STATE_NOTIFY_REMOUNT )) {
    
                ClearFlag( OldVcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
                
                FileObjectToNotify = OldVcb->RootIndexFcb->FileObject;
                ObReferenceObject( FileObjectToNotify );
            }
            
            DebugTrace(( 0, Dbg, "UdfMountVolume, remounted old Vcb %08x\n", OldVcb ));

            try_leave( Status = STATUS_SUCCESS );
        }

        //
        //  Initialize the Vcb and associated structures from our volume descriptors
        //

        UdfUpdateVcbPhase1( IrpContext,
                            Vcb,
                            FileSetDescriptor );

        //
        //  Drop an extra reference on the root dir file so we'll be able to send
        //  notification.
        //

        if (Vcb->RootIndexFcb) {

            FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
            ObReferenceObject( FileObjectToNotify );
        }

        //
        //  The new mount is complete.  Remove the additional references on this
        //  Vcb since, at this point, we have added the real references this volume
        //  will have during its lifetime.  We also need to drop the additional
        //  reference on the device we mounted.
        //

        Vcb->VcbReference -= Vcb->VcbResidualReference;
        ASSERT( Vcb->VcbReference == Vcb->VcbResidualReference );

        ObDereferenceObject( Vcb->TargetDeviceObject );

        Vcb->VcbCondition = VcbMounted;

        UdfReleaseVcb( IrpContext, Vcb );
        Vcb = NULL;

        Status = STATUS_SUCCESS;

    } finally {

        DebugUnwind( "UdfMountVolume" );

        //
        //  If we didn't complete the mount then cleanup any remaining structures.
        //

        if (Vpb != NULL) { Vpb->DeviceObject = NULL; }

        if (Pcb != NULL) {

            UdfDeletePcb( Pcb );
        }

        if (Vcb != NULL) {

            //
            //  Make sure there is no Vcb in the IrpContext since it could go away
            //

            IrpContext->Vcb = NULL;

            Vcb->VcbReference -= Vcb->VcbResidualReference;

            if (UdfDismountVcb( IrpContext, Vcb )) {

                UdfReleaseVcb( IrpContext, Vcb );
            }

        } else if (VolDo != NULL) {

            IoDeleteDevice( (PDEVICE_OBJECT)VolDo );
            Vpb->DeviceObject = NULL;
        }

        //
        //  Release the global resource.
        //

        UdfReleaseUdfData( IrpContext );

        //
        //  Free any structures we may have been allocated
        //

        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.

⌨️ 快捷键说明

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