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

📄 fsctrl.c

📁 winddk src目录下的文件系统驱动源码压缩!
💻 C
📖 第 1 页 / 共 5 页
字号:
                ObReferenceObject( FileObjectToNotify );
            }
            
            try_leave( Status = STATUS_SUCCESS );
        }

        //
        //  This is a new mount.  Go ahead and initialize the
        //  Vcb from the volume descriptor.
        //

        CdUpdateVcbFromVolDescriptor( IrpContext,
                                      Vcb,
                                      RawIsoVd );

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

        //
        //  Now check the maximum transfer limits on the device in case we
        //  get raw reads on this volume.
        //

        Status = CdPerformDevIoCtrl( IrpContext,
                                     IOCTL_SCSI_GET_CAPABILITIES,
                                     DeviceObjectWeTalkTo,
                                     &Capabilities,
                                     sizeof( IO_SCSI_CAPABILITIES ),
                                     FALSE,
                                     TRUE,
                                     NULL );

        if (NT_SUCCESS(Status)) {

            Vcb->MaximumTransferRawSectors = Capabilities.MaximumTransferLength / RAW_SECTOR_SIZE;
            Vcb->MaximumPhysicalPages = Capabilities.MaximumPhysicalPages;

        } else {

            //
            //  This should never happen, but we can safely assume 64k and 16 pages.
            //

            Vcb->MaximumTransferRawSectors = (64 * 1024) / RAW_SECTOR_SIZE;
            Vcb->MaximumPhysicalPages = 16;
        }

        //
        //  The new mount is complete.  Remove the additional references on this
        //  Vcb and the device we are mounted on top of.
        //

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

        ObDereferenceObject( Vcb->TargetDeviceObject );

        CdUpdateVcbCondition( Vcb, VcbMounted);

        CdReleaseVcb( IrpContext, Vcb );
        Vcb = NULL;

        Status = STATUS_SUCCESS;

    } finally {

        //
        //  Free the TOC buffer if not in the Vcb.
        //

        if (CdromToc != NULL) {

            CdFreePool( &CdromToc );
        }

        //
        //  Free the sector buffer if allocated.
        //

        if (RawIsoVd != NULL) {

            CdFreePool( &RawIsoVd );
        }

        //
        //  If we are not mounting the device,  then set the verify bit again.
        //
        
        if ((AbnormalTermination() || (Status != STATUS_SUCCESS)) && 
            SetDoVerifyOnFail)  {

            CdMarkRealDevForVerify( IrpContext->RealDevice);
        }

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

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

        if (Vcb != NULL) {

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

            IrpContext->Vcb = NULL;

            Vcb->VcbReference -= CDFS_RESIDUAL_REFERENCE;

            if (CdDismountVcb( IrpContext, Vcb )) {

                CdReleaseVcb( IrpContext, Vcb );
            }

        } else if (VolDo != NULL) {

            IoDeleteDevice( (PDEVICE_OBJECT) VolDo );
        }

        //
        //  Release the global resource.
        //

        CdReleaseCdData( IrpContext );
    }

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

        FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
        ObDereferenceObject( FileObjectToNotify );
    }

    //
    //  Complete the request if no exception.
    //

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


//
//  Local support routine
//

NTSTATUS
CdVerifyVolume (
    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;

    PCHAR RawIsoVd = NULL;

    PCDROM_TOC_LARGE CdromToc = NULL;
    ULONG TocLength = 0;
    ULONG TocTrackCount = 0;
    ULONG TocDiskFlags = 0;

    ULONG MediaChangeCount = Vcb->MediaChangeCount;

    PFILE_OBJECT FileObjectToNotify = NULL;

    BOOLEAN ReturnError;
    BOOLEAN ReleaseVcb = FALSE;

    IO_STATUS_BLOCK Iosb;

    STRING AnsiLabel;
    UNICODE_STRING UnicodeLabel;

    WCHAR VolumeLabel[ VOLUME_ID_LENGTH ];
    ULONG VolumeLabelLength;

    ULONG Index;

    NTSTATUS Status;

    PAGED_CODE();

    //
    //  We check that we are talking to a Cdrom device.
    //

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

    //
    //  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 the global resource to synchronise against mounts and teardown,
    //  finally clause releases.
    //

    CdAcquireCdData( IrpContext );

    try {

        CdAcquireVcbExclusive( IrpContext, Vcb, FALSE );
        ReleaseVcb = TRUE;

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

        Status = CdPerformDevIoCtrl( IrpContext,
                                     IOCTL_CDROM_CHECK_VERIFY,
                                     Vcb->TargetDeviceObject,
                                     &MediaChangeCount,
                                     sizeof(ULONG),
                                     FALSE,
                                     TRUE,
                                     &Iosb );

        if (!NT_SUCCESS( Status )) {

            //
            //  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 )) {

                Status = STATUS_WRONG_VOLUME;
            }

            try_return( 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)) {

            //
            //  Allocate a buffer to query the TOC.
            //

            CdromToc = FsRtlAllocatePoolWithTag( CdPagedPool,
                                                 sizeof( CDROM_TOC_LARGE ),
                                                 TAG_CDROM_TOC );

            RtlZeroMemory( CdromToc, sizeof( CDROM_TOC_LARGE ));

            //
            //  Let's query for the Toc now and handle any error we get from this operation.
            //

            Status = CdProcessToc( IrpContext,
                                   Vcb->TargetDeviceObject,
                                   CdromToc,
                                   &TocLength,
                                   &TocTrackCount,
                                   &TocDiskFlags );

            //
            //  If we failed to read the TOC,  then give up now.  Drives will fail
            //  a TOC read on,  for example,  erased CD-RW media.
            //

            if (Status != STATUS_SUCCESS) {

                //
                //  For any errors other than no media and not ready,  commute the
                //  status to ensure that the current VPB is kicked off the device
                //  below - there is probably blank media in the drive,  since we got
                //  further than the check verify.
                //

                if (!CdIsRawDevice( IrpContext, Status )) {

                    Status = STATUS_WRONG_VOLUME;
                }

                try_return( Status );

            //
            //  We got a TOC.  Verify that it matches the previous Toc.
            //

            } else if ((Vcb->TocLength != TocLength) ||
                       (Vcb->TrackCount != TocTrackCount) ||
                       (Vcb->DiskFlags != TocDiskFlags) ||
                       !RtlEqualMemory( CdromToc,
                                        Vcb->CdromToc,
                                        TocLength )) {

                try_return( Status = STATUS_WRONG_VOLUME );
            }

            //
            //  If the disk to verify is an audio disk then we already have a
            //  match.  Otherwise we need to check the volume descriptor.
            //

            if (!FlagOn( Vcb->VcbState, VCB_STATE_AUDIO_DISK )) {

                //
                //  Allocate a buffer for the sector buffer.
                //

                RawIsoVd = FsRtlAllocatePoolWithTag( CdNonPagedPool,
                                                     ROUND_TO_PAGES( 2 * SECTOR_SIZE ),
                                                     TAG_VOL_DESC );

                //
                //  Read the primary volume descriptor for this volume.  If we
                //  get an io error and this verify was a the result of DASD open,
                //  commute the Io error to STATUS_WRONG_VOLUME.  Note that if we currently
                //  expect a music disk then this request should fail.
                //

                ReturnError = FALSE;

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

                    ReturnError = TRUE;
                }

                if (!CdFindPrimaryVd( IrpContext,
                                      Vcb,
                                      RawIsoVd,
                                      Vcb->BlockFactor,
                                      ReturnError,
                                      TRUE )) {

                    //
                    //  If the previous Vcb did not represent a raw disk
                    //  then show this volume was dismounted.
                    //

                    try_return( Status = STATUS_WRONG_VOLUME );

                } 
                else {

                    //
                    //  Look for a supplementary VD.
                    //
                    //  Store the primary volume descriptor in the second half of
                    //  RawIsoVd.  Then if our search for a secondary fails we can
                    //  recover this immediately.
                    //

                    RtlCopyMemory( Add2Ptr( RawIsoVd, SECTOR_SIZE, PVOID ),
                                   RawIsoVd,
                                   SECTOR_SIZE );

                    //
                    //  We have the initial volume descriptor.  Locate a secondary
                    //  volume descriptor if present.
                    //

                    CdFindActiveVolDescriptor( IrpContext,
                                               Vcb,
                                               RawIsoVd,
                                               TRUE);
                    //
                    //  Compare the serial numbers.  If they don't match, set the
                    //  status to wrong volume.
                    //

                    if (Vpb->SerialNumber != CdSerial32( RawIsoVd, SECTOR_SIZE )) {

                        try_return( Status = STATUS_WRONG_VOLUME );
                    }

                    //
                    //  Verify the volume labels.
                    //

                    if (!FlagOn( Vcb->VcbState, VCB_STATE_JOLIET )) {

                        //
                        //  Compute the length of the volume name
                        //

                        AnsiLabel.Buffer = CdRvdVolId( RawIsoVd, Vcb->VcbState );
                        AnsiLabel.MaximumLength = AnsiLabel.Length = VOLUME_ID_LENGTH;

                        UnicodeLabel.MaximumLength = VOLUME_ID_LENGTH * sizeof( WCHAR );
                        UnicodeLabel.Buffer = VolumeLabel;

                        //
                        //  Convert this to unicode.  If we get any error then use a name
                        //  length of zero.
                        //

                        VolumeLabelLength = 0;

                        if (NT_SUCCESS( RtlOemStringToCountedUnicodeString( &UnicodeLabel,
                                                                            &AnsiLabel,
                                                                            FALSE ))) {

                            VolumeLabelLength = UnicodeLabel.Length;
                        }

                    //
                    //  We need to convert from big-endian to little endian.
                    //

                    } else {

                        CdConvertBigToLittleEndian( IrpContext,
                                                    CdRvdVolId( RawIsoVd, Vcb->VcbState ),
                                                    VOLUME_ID_LENGTH,
                                                    (PCHAR) VolumeLabel );

                        VolumeLabelLength = VOLUME_ID_LENGTH;
                    }

                    //
                    //  Strip the trailing spaces or zeroes from the name.
                    //

                    Index = VolumeLabelLength / sizeof( WCHAR );

                    while (Index > 0) {

                        if ((VolumeLabel[ Index - 1 ] != L'\0') &&
                            (VolumeLabel[ Index - 1 ] != L' ')) {

                            break;
                        }

                        Index -= 1;
                    }

                    //
                    //  Now set the final length for the name.
                    //

                    VolumeLabelLength = (USHORT) (Index * sizeof( WCHAR ));

                    //
                    //  Now check that the label matches.
                    //
                    if ((Vpb->VolumeLabelLength != VolumeLabelLength) ||
                        !RtlEqualMemory( Vpb->VolumeLabel,
                                         VolumeLabel,
                                         VolumeLabelLength )) {

                        try_return( Status = STATUS_WRONG_VOLUME );
                    }
                }
            }
        }

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

        CdUpdateVcbCondition( Vcb, VcbMounted);

⌨️ 快捷键说明

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