test: udfs/fsctrl.c File Reference

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# fsctrl.c File Reference

`#include "UdfProcs.h"`

Go to the source code of this file.

## Defines

#define | BugCheckFileId (UDFS_BUG_CHECK_FSCTRL)
#define | Dbg (UDFS_DEBUG_LEVEL_FSCTRL)

## Functions

INLINE VOID | UdfStoreFileSetDescriptorIfPrevailing (IN OUT PNSR_FSD *StoredFSD, IN OUT PNSR_FSD *NewFSD)
VOID | UdfDetermineVolumeBounding (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PULONG S, IN PULONG N)
NTSTATUS | UdfDismountVolume (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfFindAnchorVolumeDescriptor (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN OUT PNSR_ANCHOR *AnchorVolumeDescriptor)
NTSTATUS | UdfFindFileSetDescriptor (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PLONGAD LongAd, IN OUT PNSR_FSD *FileSetDescriptor)
NTSTATUS | UdfFindVolumeDescriptors (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PEXTENTAD Extent, IN OUT PPCB *Pcb, IN OUT PNSR_PVD *PrimaryVolumeDescriptor, IN OUT PNSR_LVOL *LogicalVolumeDescriptor)
NTSTATUS | UdfInvalidateVolumes (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfIsPathnameValid (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
BOOLEAN | UdfIsRemount (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, OUT PVCB *OldVcb)
| UdfIsVolumeDirty (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfIsVolumeMounted (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfLockVolume (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfMountVolume (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfOplockRequest (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
BOOLEAN | UdfRecognizeVolume (IN PIRP_CONTEXT IrpContext, IN PDEVICE_OBJECT DeviceObject, IN ULONG SectorSize, IN OUT PBOOLEAN Bridge)
VOID | UdfScanForDismountedVcb (IN PIRP_CONTEXT IrpContext)
NTSTATUS | UdfUnlockVolume (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
VOID | UdfUpdateVolumeLabel (IN PIRP_CONTEXT IrpContext, IN PWCHAR VolumeLabel, IN OUT PUSHORT VolumeLabelLength, IN PUCHAR Dstring, IN UCHAR FieldLength)
VOID | UdfUpdateVolumeSerialNumber (IN PIRP_CONTEXT IrpContext, IN OUT PULONG VolumeSerialNumber, IN PNSR_FSD Fsd)
NTSTATUS | UdfUserFsctl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfVerifyVolume (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
VOID | UdfStoreVolumeDescriptorIfPrevailing (IN OUT PNSR_VD_GENERIC *StoredVD, IN OUT PNSR_VD_GENERIC NewVD)
NTSTATUS | UdfCommonFsControl (IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
NTSTATUS | UdfLockVolumeInternal (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject OPTIONAL)
NTSTATUS | UdfUnlockVolumeInternal (IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PFILE_OBJECT FileObject OPTIONAL)

## Variables

BOOLEAN | UdfDisable = FALSE

## Define Documentation

#define BugCheckFileId (UDFS_BUG_CHECK_FSCTRL)

| Definition at line 28 of file udfs/fsctrl.c.

#define Dbg (UDFS_DEBUG_LEVEL_FSCTRL)

| Definition at line 34 of file udfs/fsctrl.c.

## Function Documentation

NTSTATUS UdfCommonFsControl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 283 of file udfs/fsctrl.c.

References ASSERT_IRP, ASSERT_IRP_CONTEXT, IoGetCurrentIrpStackLocation, Irp, IRP_MN_MOUNT_VOLUME, IRP_MN_USER_FS_REQUEST, IRP_MN_VERIFY_VOLUME, _IO_STACK_LOCATION::MinorFunction, NTSTATUS(), PAGED_CODE, Status, UdfCompleteRequest(), UdfMountVolume(), UdfUserFsctl(), and UdfVerifyVolume().

Referenced by UdfFsdDispatch(), and UdfFspDispatch().

    00290                    :
    00291
    00292     This is the common routine for doing FileSystem control operations called
    00293     by both the fsd and fsp threads
    00294
    00295 Arguments:
    00296
    00297     Irp - Supplies the Irp to process
    00298
    00299 Return Value:
    00300
    00301     NTSTATUS - The return status for the operation
    00302
    00303 --*/
    00304
    00305 {
    00306     NTSTATUS Status;
    00307     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00308
    00309     PAGED_CODE();
    00310
    00311     //
    00312     //  Check the input parameters
    00313     //
    00314
    00315     ASSERT_IRP_CONTEXT( IrpContext );
    00316     ASSERT_IRP( Irp );
    00317
    00318     //
    00319     //  Get a pointer to the current Irp stack location
    00320     //
    00321
    00322     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00323
    00324     //
    00325     //  We know this is a file system control so we'll case on the
    00326     //  minor function, and call a internal worker routine to complete
    00327     //  the irp.
    00328     //
    00329
    00330     switch (IrpSp->MinorFunction) {
    00331
    00332     case IRP_MN_MOUNT_VOLUME:
    00333
    00334         Status = UdfMountVolume( IrpContext, Irp );
    00335         break;
    00336
    00337     case IRP_MN_VERIFY_VOLUME:
    00338
    00339         Status = UdfVerifyVolume( IrpContext, Irp );
    00340         break;
    00341
    00342     case IRP_MN_USER_FS_REQUEST:
    00343
    00344         Status = UdfUserFsctl( IrpContext, Irp );
    00345         break;
    00346
    00347     default:
    00348
    00349         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
    00350         Status = STATUS_INVALID_DEVICE_REQUEST;
    00351         break;
    00352     }
    00353
    00354     return Status;
    00355 }

VOID UdfDetermineVolumeBounding | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PULONG | S,
|  | IN PULONG | N
| ) |

Definition at line 3817 of file udfs/fsctrl.c.

References ASSERT_IRP_CONTEXT, ASSERT_VCB, Dbg, DebugTrace, DebugUnwind, FALSE, FsRtlAllocatePoolWithTag, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, Status, SwapCopyUchar4, TAG_CDROM_TOC, TRUE, try_leave, UdfFreePool(), UdfPagedPool, UdfPerformDevIoCtrl(), and UdfRaiseStatus().

Referenced by UdfMountVolume().

    03826                    :
    03827
    03828     This routine will figure out where the base offset to discover volume descriptors
    03829     lies and where the end of the disc is.  In the case where this is a non-CD media,
    03830     this will tend to not to set the end bound since there is no uniform way to figure
    03831     that piece of information out.
    03832
    03833     The bounding information is used to start the hunt for CD-UDF (UDF 1.5) volumes.
    03834     Anyone who puts CD-UDF on non-CD media deserves what they get.
    03835
    03836 Arguments:
    03837
    03838     Vcb - the volume we are operating on
    03839
    03840     S - an address to store the start of the volume for the purposes of finding descriptors
    03841
    03842     N - an address to store the end of the volume for the purposes of finding descriptors
    03843
    03844 Return Value:
    03845
    03846     None.
    03847
    03848     Benign inability find the S/N information will result in 0/0 being returned.
    03849
    03850 --*/
    03851
    03852 {
    03853     NTSTATUS Status;
    03854     PCDROM_TOC CdromToc;
    03855     PTRACK_DATA TrackData;
    03856
    03857     PAGED_CODE();
    03858
    03859     //
    03860     //  Check input.
    03861     //
    03862
    03863     ASSERT_IRP_CONTEXT( IrpContext );
    03864     ASSERT_VCB( Vcb );
    03865
    03866     //
    03867     //  Allocate a buffer for the last session information.
    03868     //
    03869
    03870     CdromToc = FsRtlAllocatePoolWithTag( UdfPagedPool,
    03871                                          sizeof( CDROM_TOC ),
    03872                                          TAG_CDROM_TOC );
    03873
    03874     RtlZeroMemory( CdromToc, sizeof( CDROM_TOC ));
    03875
    03876     DebugTrace(( +1, Dbg,
    03877                "UdfDetermineVolumeBounding, Vcb %08x S %08x N %08x\n",
    03878                Vcb,
    03879                S,
    03880                N ));
    03881
    03882     //
    03883     //  Whack the inputs to the benign state.
    03884     //
    03885
    03886     *S = *N = 0;
    03887
    03888     //
    03889     //  Try to retrieve the CDROM last session information.
    03890     //
    03891
    03892     try {
    03893
    03894         //
    03895         //  Pull up the TOC.  The information for track AA (start of leadout)
    03896         //  will get us the end of disc within some tolerance dependent on how
    03897         //  much the device manufacturer paid attention to specifications.
    03898         //  (-152, -150, -2, and 0 are possible offsets to the real end).
    03899         //
    03900
    03901         Status = UdfPerformDevIoCtrl( IrpContext,
    03902                                       IOCTL_CDROM_READ_TOC,
    03903                                       Vcb->TargetDeviceObject,
    03904                                       CdromToc,
    03905                                       sizeof( CDROM_TOC ),
    03906                                       FALSE,
    03907                                       TRUE,
    03908                                       NULL );
    03909
    03910         //
    03911         //  Raise an exception if there was an allocation failure.
    03912         //
    03913
    03914         if (Status == STATUS_INSUFFICIENT_RESOURCES) {
    03915
    03916             DebugTrace(( 0, Dbg, "UdfDetermineVolumeBounding, READ_TOC failed INSUFFICIENT_RESOURCES\n" ));
    03917             UdfRaiseStatus( IrpContext, Status );
    03918         }
    03919
    03920         //
    03921         //  For other errors, just fail.  Perhaps this will turn out to be benign, in any case
    03922         //  the mount will rapidly and correctly fail if it really was dependant on this work.
    03923         //
    03924
    03925         if (!NT_SUCCESS( Status )) {
    03926
    03927             try_leave( NOTHING );
    03928         }
    03929
    03930         //
    03931         //  Sanity chck that the TOC is well-bounded.
    03932         //
    03933
    03934         if (CdromToc->LastTrack - CdromToc->FirstTrack >= MAXIMUM_NUMBER_TRACKS) {
    03935
    03936             DebugTrace(( 0, Dbg, "UdfDetermineVolumeBounding, TOC malf (too many tracks)\n" ));
    03937             try_leave( NOTHING );
    03938         }
    03939
    03940         TrackData = &CdromToc->TrackData[(CdromToc->LastTrack - CdromToc->FirstTrack + 1)];
    03941
    03942 #if 0
    03943         //
    03944         //  Better be AA ...
    03945         //
    03946
    03947         if (TrackData->TrackNumber != 0xaa) {
    03948
    03949             DebugTrace(( 0, Dbg, "UdfDetermineVolumeBounding, TOC malf (aa not last)\n" ));
    03950             try_leave( NOTHING );
    03951         }
    03952 #endif
    03953
    03954         //
    03955         //  Now, find the AA info and convert MSF to a logical block address.  75 frames/sectors
    03956         //  per second, 60 seconds per minute.  The MSF address is stored LSB (the F byte) high
    03957         //  in the word.
    03958         //
    03959
    03960         //
    03961         //  NOTE: MSF is only capable of representing 256*(256+256*60)*75 = 0x11ce20 sectors.
    03962         //  This is 2.3gb, much less than the size of DVD media, which will respond to CDROM_TOC.
    03963         //  Caveat user.
    03964         //
    03965
    03966         *N = (TrackData->Address[3] + (TrackData->Address[2] + TrackData->Address[1] * 60) * 75) - 1;
    03967
    03968         //
    03969         //  We must bias back by 0/2/0 MSF since that is the defined location of sector 0.  This
    03970         //  works out to 150 sectors.
    03971         //
    03972
    03973         if (*N <= 150) {
    03974
    03975             *N = 0;
    03976             try_leave( NOTHING );
    03977         }
    03978
    03979         *N -= 150;
    03980
    03981         //
    03982         //  Query the last session information from the driver.
    03983         //
    03984
    03985         Status = UdfPerformDevIoCtrl( IrpContext,
    03986                                       IOCTL_CDROM_GET_LAST_SESSION,
    03987                                       Vcb->TargetDeviceObject,
    03988                                       CdromToc,
    03989                                       sizeof( CDROM_TOC ),
    03990                                       FALSE,
    03991                                       TRUE,
    03992                                       NULL );
    03993
    03994         //
    03995         //  Raise an exception if there was an allocation failure.
    03996         //
    03997
    03998         if (Status == STATUS_INSUFFICIENT_RESOURCES) {
    03999
    04000             DebugTrace(( 0, Dbg, "UdfDetermineVolumeBounding, GET_LAST_SESSION failed INSUFFICIENT_RESOURCES\n" ));
    04001             UdfRaiseStatus( IrpContext, Status );
    04002         }
    04003
    04004         //
    04005         //  Now, if we got anything interesting out of this try, return it.  If this
    04006         //  failed for any other reason, we don't really care - it just means that
    04007         //  if this was CDUDF media, we're gonna fail to figure it out pretty quickly.
    04008         //
    04009         //  Life is tough.
    04010         //
    04011
    04012         if (NT_SUCCESS( Status ) &&
    04013             CdromToc->FirstTrack != CdromToc->LastTrack) {
    04014
    04015             //
    04016             //  The 0 entry in TrackData tells us about the start of the session as a
    04017             //  logical block address.
    04018             //
    04019
    04020             SwapCopyUchar4( S, &CdromToc->TrackData[0].Address );
    04021
    04022             //
    04023             //  Save grief if the session info is screwed up.
    04024             //
    04025
    04026             if (*N <= *S) {
    04027
    04028                 DebugTrace(( 0, Dbg, "UdfDetermineVolumeBounding, N before S, whacking both back!\n" ));
    04029                 *S = *N = 0;
    04030             }
    04031         }
    04032
    04033         DebugTrace(( 0, Dbg, "UdfDetermineVolumeBounding, S %08x N %08x\n", *S, *N ));
    04034
    04035     } finally {
    04036
    04037         DebugUnwind( "UdfDetermineVolumeBounding" );
    04038
    04039         if (CdromToc != NULL) {
    04040
    04041             UdfFreePool( &CdromToc );
    04042         }
    04043     }
    04044
    04045     DebugTrace(( -1, Dbg, "UdfDetermineVolumeBounding -> VOID\n" ));
    04046
    04047     return;
    04048 }

NTSTATUS UdfDismountVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 966 of file udfs/fsctrl.c.

References DO_VERIFY_VOLUME, FALSE, _IO_STACK_LOCATION::FileObject, _DEVICE_OBJECT::Flags, FSRTL_VOLUME_DISMOUNT, FSRTL_VOLUME_DISMOUNT_FAILED, FsRtlNotifyVolumeEvent(), IoGetCurrentIrpStackLocation, Irp, NT_SUCCESS, NTSTATUS(), PAGED_CODE, _VPB::RealDevice, SetFlag, Status, UdfAcquireVcbExclusive, UdfCompleteRequest(), UdfDecodeFileObject(), UdfReleaseVcb, UserVolumeOpen, _FCB::Vcb, VCB_STATE_NOTIFY_REMOUNT, _VCB::VcbCondition, VcbMounted, _VCB::VcbState, _VCB::VolumeLockFileObject, and _VCB::Vpb.

Referenced by UdfUserFsctl().

    00973                    :
    00974
    00975     This routine performs the dismount volume operation.  It is responsible for
    00976     either completing of enqueuing the input Irp.  We only dismount a volume which
    00977     has been locked.  The intent here is that someone has locked the volume (they are the
    00978     only remaining handle).  We set the volume state to invalid so that it will be torn
    00979     down quickly.
    00980
    00981 Arguments:
    00982
    00983     Irp - Supplies the Irp to process
    00984
    00985 Return Value:
    00986
    00987     NTSTATUS - The return status for the operation
    00988
    00989 --*/
    00990
    00991 {
    00992     NTSTATUS Status;
    00993     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00994
    00995     PVCB Vcb;
    00996     PFCB Fcb;
    00997     PCCB Ccb;
    00998
    00999     PAGED_CODE();
    01000
    01001     if (UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
    01002
    01003         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    01004         return STATUS_INVALID_PARAMETER;
    01005     }
    01006
    01007     //
    01008     //  Send notification.
    01009     //
    01010
    01011     FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT );
    01012
    01013     //
    01014     //  Acquire exclusive access to the Vcb.
    01015     //
    01016
    01017     Vcb = Fcb->Vcb;
    01018
    01019     UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    01020
    01021     //
    01022     //  Mark the volume as invalid, but only do it if the vcb is locked
    01023     //  by this handle and the volume is currently mounted.  No more
    01024     //  operations will occur on this vcb except cleanup/close.
    01025     //
    01026
    01027     if ((Vcb->VcbCondition != VcbMounted) &&
    01028         (Vcb->VolumeLockFileObject != IrpSp->FileObject)) {
    01029
    01030         Status = STATUS_NOT_IMPLEMENTED;
    01031
    01032     } else {
    01033
    01034         SetFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
    01035         SetFlag( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
    01036
    01037         Status = STATUS_SUCCESS;
    01038     }
    01039
    01040     //
    01041     //  Release all of our resources
    01042     //
    01043
    01044     UdfReleaseVcb( IrpContext, Vcb );
    01045
    01046     if (!NT_SUCCESS( Status )) {
    01047
    01048         FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_DISMOUNT_FAILED );
    01049     }
    01050
    01051     //
    01052     //  Complete the request if there haven't been any exceptions.
    01053     //
    01054
    01055     UdfCompleteRequest( IrpContext, Irp, Status );
    01056     return Status;
    01057 }

NTSTATUS UdfFindAnchorVolumeDescriptor | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN OUT PNSR_ANCHOR * | AnchorVolumeDescriptor
| ) |

Definition at line 3307 of file udfs/fsctrl.c.

References ANCHOR_SECTOR, ASSERT, ASSERT_IRP_CONTEXT, ASSERT_VCB, ClearFlag, Dbg, DebugTrace, DESTAG_ID_NSR_ANCHOR, FALSE, FsRtlAllocatePoolWithTag, LlBytesFromSectors, NSR_ANCHOR, NT_SUCCESS, NTSTATUS(), NULL, PAGED_CODE, SetFlag, Status, TAG_NSR_VDSD, TRUE, UdfMethod2TransformSector, UdfNonPagedPool, UdfRawBufferSize(), UdfRawReadSize(), UdfReadSectors(), UdfVerifyDescriptor(), and VCB_STATE_METHOD_2_FIXUP.

Referenced by UdfMountVolume(), and UdfVerifyVolume().

    03315                    :
    03316
    03317     This routine will find the Anchor Volume Descriptor for a piece of media
    03318
    03319 Arguments:
    03320
    03321     Vcb - Vcb of volume to search
    03322
    03323     AnchorVolumeDescriptor - Caller's pointer to an AVD
    03324
    03325 Return Value:
    03326
    03327     Boolean TRUE if AVD is discovered, FALSE otherwise.
    03328
    03329 --*/
    03330
    03331 {
    03332     ULONG ThisPass;
    03333     ULONG ReadLsn;
    03334     ULONG Lsn;
    03335     BOOLEAN Found = FALSE;
    03336     NTSTATUS Status;
    03337
    03338     PAGED_CODE();
    03339
    03340     //
    03341     //  Check the input parameters
    03342     //
    03343
    03344     ASSERT_IRP_CONTEXT( IrpContext);
    03345     ASSERT_VCB( Vcb );
    03346
    03347     ASSERT(*AnchorVolumeDescriptor == NULL);
    03348
    03349     //
    03350     //  Discover the Anchor Volume Descriptor, which will point towards the
    03351     //  Volume Set Descriptor Sequence.  The AVD may exist at sector 256 or
    03352     //  in the last sector of the volume.
    03353     //
    03354
    03355     *AnchorVolumeDescriptor = (PNSR_ANCHOR) FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    03356                                                                       UdfRawBufferSize( Vcb, sizeof(NSR_ANCHOR) ),
    03357                                                                       TAG_NSR_VDSD );
    03358
    03359
    03360     //
    03361     //  Search the three possible locations for an AVD to exist on the volume,
    03362     //  plus check for the possibility of a method 2 fixup requirement.
    03363     //
    03364
    03365     for ( ThisPass = 1; ThisPass <= 4; ThisPass++ ) {
    03366
    03367         if (ThisPass == 1) {
    03368
    03369             ReadLsn = Lsn = ANCHOR_SECTOR + Vcb->BoundS;
    03370
    03371         } else if (ThisPass == 2) {
    03372
    03373             //
    03374             //  It is so unlikely that we will get a disk that doesn't have
    03375             //  an anchor at 256 that this is a pretty good indication we
    03376             //  have a CD-RW here and the drive is method 2 goofy.  Take
    03377             //  a shot.
    03378             //
    03379
    03380             ReadLsn = UdfMethod2TransformSector( Vcb, ANCHOR_SECTOR );
    03381             Lsn = ANCHOR_SECTOR;
    03382
    03383         } else if (ThisPass == 3) {
    03384
    03385             //
    03386             //  Our remaining two chances depend on being able to determine
    03387             //  the last recorded sector for the volume.  If we were unable
    03388             //  to do this, stop.
    03389             //
    03390
    03391             if (!Vcb->BoundN) {
    03392
    03393                 break;
    03394             }
    03395
    03396             ReadLsn = Lsn = Vcb->BoundN;
    03397
    03398         } else if (ThisPass == 4) {
    03399
    03400             ReadLsn = Lsn = Vcb->BoundN - ANCHOR_SECTOR;
    03401         }
    03402
    03403         //
    03404         //  We may have more chances to succeed if failure occurs.
    03405         //
    03406
    03407         Status = UdfReadSectors( IrpContext,
    03408                                  LlBytesFromSectors( Vcb, ReadLsn ),
    03409                                  UdfRawReadSize( Vcb, sizeof(NSR_ANCHOR) ),
    03410                                  TRUE,
    03411                                  *AnchorVolumeDescriptor,
    03412                                  Vcb->TargetDeviceObject );
    03413
    03414         if (!NT_SUCCESS( Status )) {
    03415             continue;
    03416         }
    03417
    03418         if (!UdfVerifyDescriptor( IrpContext,
    03419                                   &(*AnchorVolumeDescriptor)->Destag,
    03420                                   DESTAG_ID_NSR_ANCHOR,
    03421                                   sizeof(NSR_ANCHOR),
    03422                                   Lsn,
    03423                                   TRUE)) {
    03424
    03425             continue;
    03426         }
    03427
    03428         //
    03429         //  Got one!  Set the method 2 fixup appropriately.
    03430         //
    03431
    03432         if (ThisPass == 2) {
    03433
    03434             DebugTrace(( 0, Dbg, "************************************************\n"));
    03435             DebugTrace(( 0, Dbg, "METHOD 2 FIXUPS ACTIVATED FOR Vcb @ %08x\n", Vcb ));
    03436             DebugTrace(( 0, Dbg, "************************************************\n"));
    03437
    03438             SetFlag( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP );
    03439
    03440         } else {
    03441
    03442             ClearFlag( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP );
    03443         }
    03444
    03445         return STATUS_SUCCESS;
    03446     }
    03447
    03448     return STATUS_UNRECOGNIZED_VOLUME;
    03449 }

NTSTATUS UdfFindFileSetDescriptor | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PLONGAD | LongAd,
|  | IN OUT PNSR_FSD * | FileSetDescriptor
| ) |

Definition at line 2558 of file udfs/fsctrl.c.

References ASSERT, ASSERT_IRP_CONTEXT, BlockOffset, BlockSize, Dbg, DebugTrace, NSR_FSD::Destag, DESTAG_ID_NOTSPEC, DESTAG_ID_NSR_FSD, DESTAG_ID_NSR_TERM, FsRtlAllocatePoolWithTag, DESTAG::Ident, NSRLENGTH::Length, LONGAD::Length, LlBytesFromBlocks, LlBytesFromSectors, NSR_FSD::NextExtent, NSR_FSD, NSRLENGTH_TYPE_RECORDED, NT_SUCCESS, NTSTATUS(), NULL, Offset, PAGED_CODE, Status, TAG_NSR_FSD, TRUE, try_leave, UdfExceptionFilter(), UdfFreePool(), UdfLookupPsnOfExtent(), UdfNonPagedPool, UdfRawBufferSize(), UdfRawReadSize(), UdfReadSectors(), UdfStoreFileSetDescriptorIfPrevailing(), and UdfVerifyDescriptor().

Referenced by UdfMountVolume(), and UdfVerifyVolume().

    02567                    :
    02568
    02569     This routine walks a Fileset Descriptor Sequence looking for the default
    02570     descriptor.  This will reveal the location of the root directory on the
    02571     volume.
    02572
    02573 Arguments:
    02574
    02575     Vcb - Vcb of volume to search
    02576
    02577     LongAd - Long allocation descriptor describing the start of the sequence
    02578
    02579     FileSetDescriptor - Address of caller's pointer to an FSD
    02580
    02581 Return Value:
    02582
    02583     STATUS_SUCCESS if all descriptors are found, read, and are valid.
    02584
    02585     STATUS_DISK_CORRUPT_ERROR if corrupt/bad descriptors are found (may be raised)
    02586
    02587 --*/
    02588
    02589 {
    02590     PNSR_FSD FSD = NULL;
    02591     ULONGLONG Offset;
    02592     ULONG Lbn, Len;
    02593
    02594     NTSTATUS Status = STATUS_SUCCESS;
    02595
    02596     PAGED_CODE();
    02597
    02598     //
    02599     //  Check inputs
    02600     //
    02601
    02602     ASSERT_IRP_CONTEXT( IrpContext );
    02603     ASSERT( *FileSetDescriptor == NULL );
    02604
    02605     DebugTrace(( +1, Dbg,
    02606                  "UdfFindFileSetDescriptor, Vcb %08x, LongAd %08x %x/%08x +%08x (type %x)\n",
    02607                  Vcb,
    02608                  LongAd,
    02609                  LongAd->Start.Partition,
    02610                  LongAd->Start.Lbn,
    02611                  LongAd->Length.Length,
    02612                  LongAd->Length.Type ));
    02613
    02614     //
    02615     //  If the extent we begin from is not a whole number of recorded logical blocks,
    02616     //  we can't continue.
    02617     //
    02618
    02619 #ifndef UDF_SUPPORT_NONSTANDARD_ALLSTOR
    02620
    02621     //
    02622     //  Disable checking the sanity of the longad here.
    02623     //
    02624     //  Reason: first drop of Allstor media recorded the type as unrecorded (!)
    02625     //
    02626
    02627     if (LongAd->Length.Length == 0 ||
    02628         LongAd->Length.Type != NSRLENGTH_TYPE_RECORDED ||
    02629         BlockOffset( Vcb, LongAd->Length.Length )) {
    02630
    02631         DebugTrace(( +0, Dbg,
    02632                      "UdfFindFileSetDescriptor, bad longad length\n" ));
    02633         DebugTrace(( -1, Dbg,
    02634                      "UdfFindFileSetDescriptor ->  STATUS_DISK_CORRUPT_ERROR\n" ));
    02635
    02636         return STATUS_DISK_CORRUPT_ERROR;
    02637     }
    02638
    02639 #endif
    02640
    02641     //
    02642     //  Use a try-finally for cleanup
    02643     //
    02644
    02645     try {
    02646
    02647         try {
    02648
    02649             for ( //
    02650                   //  Home ourselves in the search and make a pass through the sequence.
    02651                   //
    02652
    02653                   Len = LongAd->Length.Length,
    02654                   Lbn = LongAd->Start.Lbn,
    02655                   Offset = LlBytesFromSectors( Vcb, UdfLookupPsnOfExtent( IrpContext,
    02656                                                                           Vcb,
    02657                                                                           LongAd->Start.Partition,
    02658                                                                           Lbn,
    02659                                                                           Len ));
    02660
    02661                   Len;
    02662
    02663                   //
    02664                   //  Advance to the next descriptor offset in the sequence.
    02665                   //
    02666
    02667                   Len -= BlockSize( Vcb ),
    02668                   Lbn++,
    02669                   Offset += BlockSize( Vcb )) {
    02670
    02671                 //
    02672                 //  Allocate a buffer to read fileset descriptors.
    02673                 //
    02674
    02675                 if (FSD == NULL) {
    02676
    02677                     FSD = FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    02678                                                     UdfRawBufferSize( Vcb, sizeof(NSR_FSD) ),
    02679                                                     TAG_NSR_FSD );
    02680                 }
    02681
    02682                 Status = UdfReadSectors( IrpContext,
    02683                                          Offset,
    02684                                          UdfRawReadSize( Vcb, sizeof(NSR_FSD) ),
    02685                                          TRUE,
    02686                                          FSD,
    02687                                          Vcb->TargetDeviceObject );
    02688
    02689                 if (!NT_SUCCESS( Status ) ||
    02690                     FSD->Destag.Ident == DESTAG_ID_NOTSPEC) {
    02691
    02692                     //
    02693                     //  These are both an excellent sign that this is an unrecorded sector, which
    02694                     //  is defined to terminate the sequence. (3/8.4.2)
    02695                     //
    02696
    02697                     break;
    02698                 }
    02699
    02700                 if ((FSD->Destag.Ident != DESTAG_ID_NSR_FSD &&
    02701                      FSD->Destag.Ident != DESTAG_ID_NSR_TERM) ||
    02702
    02703                     !UdfVerifyDescriptor( IrpContext,
    02704                                           &FSD->Destag,
    02705                                           FSD->Destag.Ident,
    02706                                           sizeof(NSR_FSD),
    02707                                           Lbn,
    02708                                           TRUE)) {
    02709
    02710                     //
    02711                     //  If we spot an illegal descriptor type in the stream, there is no reasonable
    02712                     //  way to guess that we can continue (the disc may be trash beyond this point).
    02713                     //  Clearly, we also cannot trust the next extent pointed to by a corrupt
    02714                     //  descriptor.
    02715                     //
    02716
    02717                     try_leave( Status = STATUS_DISK_CORRUPT_ERROR );
    02718                 }
    02719
    02720                 if (FSD->Destag.Ident == DESTAG_ID_NSR_TERM) {
    02721
    02722                     //
    02723                     //  This is a way to terminate the sequence.
    02724                     //
    02725
    02726                     break;
    02727                 }
    02728
    02729                 //
    02730                 //  Reset the pointers to the possible next extent
    02731                 //
    02732
    02733                 LongAd = &FSD->NextExtent;
    02734
    02735                 if (LongAd->Length.Length) {
    02736
    02737                     //
    02738                     //  A fileset descriptor containing a nonzero next extent pointer also
    02739                     //  terminates this extent of the FSD sequence. (4/8.3.1)
    02740                     //
    02741                     //  If the extent referred to is not fully recorded, this will
    02742                     //  terminate the sequence.
    02743                     //
    02744
    02745                     if (LongAd->Length.Type != NSRLENGTH_TYPE_RECORDED) {
    02746
    02747                         break;
    02748                     }
    02749
    02750                     Len = LongAd->Length.Length;
    02751
    02752                     //
    02753                     //  The extent must be a multiple of a block size.
    02754                     //
    02755
    02756                     if (BlockOffset( Vcb, Len )) {
    02757
    02758                         DebugTrace(( +0, Dbg,
    02759                                      "UdfFindFileSetDescriptor, interior extent not blocksize in length\n" ));
    02760                         try_leave ( Status = STATUS_DISK_CORRUPT_ERROR );
    02761                     }
    02762
    02763                     Lbn = LongAd->Start.Lbn;
    02764
    02765                     Offset = LlBytesFromBlocks( Vcb, UdfLookupPsnOfExtent( IrpContext,
    02766                                                                            Vcb,
    02767                                                                            LongAd->Start.Partition,
    02768                                                                            Lbn,
    02769                                                                            Len ));
    02770
    02771                 }
    02772
    02773                 UdfStoreFileSetDescriptorIfPrevailing( FileSetDescriptor, &FSD );
    02774             }
    02775
    02776         } finally {
    02777
    02778             //
    02779             //  Free up the buffer space we may have allocated
    02780             //
    02781
    02782             UdfFreePool( &FSD );
    02783
    02784         }
    02785
    02786     } except( UdfExceptionFilter( IrpContext, GetExceptionInformation() )) {
    02787
    02788         //
    02789         //  Transmute raised apparent file corruption to disk corruption - we are not
    02790         //  yet touching the visible filesystem.
    02791         //
    02792
    02793         Status = IrpContext->ExceptionStatus;
    02794
    02795         DebugTrace(( +0, Dbg,
    02796                      "UdfFindFileSetDescriptor, exception %08x thrown\n", Status ));
    02797
    02798         if (Status == STATUS_FILE_CORRUPT_ERROR) {
    02799
    02800             DebugTrace(( +0, Dbg,
    02801                          "UdfFindFileSetDescriptor, translating file corrupt to disk corrupt\n" ));
    02802             Status = STATUS_DISK_CORRUPT_ERROR;
    02803         }
    02804     }
    02805
    02806     //
    02807     //  Success is when we've really found something.  If we failed to find the
    02808     //  descriptor, commute whatever intermediate status was involved and clean up.
    02809     //
    02810
    02811     if (*FileSetDescriptor == NULL) {
    02812
    02813         Status = STATUS_UNRECOGNIZED_VOLUME;
    02814     }
    02815
    02816     if (!NT_SUCCESS( Status )) {
    02817
    02818         UdfFreePool( FileSetDescriptor );
    02819     }
    02820
    02821     DebugTrace(( -1, Dbg,
    02822                  "UdfFindFileSetDescriptor -> %08x\n", Status ));
    02823     return Status;
    02824 }

NTSTATUS UdfFindVolumeDescriptors | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PVCB | Vcb,
|  | IN PEXTENTAD | Extent,
|  | IN OUT PPCB * | Pcb,
|  | IN OUT PNSR_PVD * | PrimaryVolumeDescriptor,
|  | IN OUT PNSR_LVOL * | LogicalVolumeDescriptor
| ) |

Definition at line 2832 of file udfs/fsctrl.c.

References ASSERT_IRP_CONTEXT, ASSERT_OPTIONAL_PCB, ASSERT_VCB, NSR_LVOL::BlockSize, NSR_LVOL::Charset, NSR_PVD::CharsetDesc, NSR_PVD::CharsetExplan, NSR_PVD::CharSetList, NSR_PVD::CharSetListMax, CHARSPEC_T_CS0, NSR_PART::ContentsID, Dbg, DebugTrace, DebugUnwind, NSR_PART::Destag, NSR_VD_GENERIC::Destag, DESTAG_ID_MAXIMUM_PART3, DESTAG_ID_NSR_LVOL, DESTAG_ID_NSR_PART, DESTAG_ID_NSR_PVD, DESTAG_ID_NSR_TERM, DESTAG_ID_NSR_VDP, NSR_LVOL::DomainID, FsRtlAllocatePoolWithTag, DESTAG::Ident, ISONsrLvolSize, LlBytesFromSectors, NSR_LVOL::MapTableCount, NSR_VD_GENERIC, NT_SUCCESS, NTSTATUS(), NULL, Offset, PAGED_CODE, PNSR_VDP, SectorsFromBytes, SectorSize, Status, TAG_NSR_VDSD, TRUE, try_leave, UDF_CHARSETLIST, UDF_VERSION_MINIMUM, UDF_VERSION_RECOGNIZED, UdfAddToPcb(), UdfCS0Identifier, UdfDomainIdentifier, UdfDomainIdentifierContained(), UdfEqualCharspec(), UdfEqualEntityId(), UdfFreePool(), UdfInitializePcb(), UdfNonPagedPool, UdfNSR02Identifier, UdfRawBufferSize(), UdfRawReadSize(), UdfReadSectors(), UdfStoreVolumeDescriptorIfPrevailing(), UdfVerifyDescriptor(), NSR_PVD::VolSetSeq, and NSR_PVD::VolSetSeqMax.

Referenced by UdfMountVolume(), and UdfVerifyVolume().

    02843                    :
    02844
    02845     This routine walks the indicated Volume Descriptor Sequence searching for the
    02846     active descriptors for this volume and generates an initializing Pcb from the
    02847     referenced partitions.  No updating of the Vcb occurs.
    02848
    02849 Arguments:
    02850
    02851     Vcb - Vcb of volume to search
    02852
    02853     Extent - Extent to search
    02854
    02855     Pcb - Address of a caller's pointer to a Pcb
    02856
    02857     PrimaryVolumeDescriptor - Address of caller's pointer to a PVD
    02858
    02859     LogicalVolumeDescriptor - Address of caller's pointer to an LVD
    02860
    02861 Return Value:
    02862
    02863     STATUS_SUCCESS if all descriptors are found, read, and are valid.
    02864
    02865     STATUS_DISK_CORRUPT_ERROR if corrupt descriptors are found.
    02866
    02867     STATUS_UNRECOGNIZED_VOLUME if noncompliant descriptors are found.
    02868
    02869     Descriptors are only returned on success.
    02870
    02871 --*/
    02872
    02873 {
    02874     PNSR_VD_GENERIC GenericVD = NULL;
    02875     ULONGLONG Offset;
    02876     ULONG Len;
    02877     ULONG UnitSize = UdfRawReadSize( Vcb, sizeof(NSR_VD_GENERIC) );
    02878
    02879     NTSTATUS Status = STATUS_SUCCESS;
    02880     ULONG ThisPass = 1;
    02881
    02882     PAGED_CODE();
    02883
    02884     //
    02885     //  Check the input parameters
    02886     //
    02887
    02888     ASSERT_IRP_CONTEXT( IrpContext);
    02889     ASSERT_VCB( Vcb );
    02890     ASSERT_OPTIONAL_PCB( *Pcb );
    02891
    02892     DebugTrace(( +1, Dbg,
    02893                  "UdfFindVolumeDescriptors, Vcb %08x, Extent %08x +%08x\n",
    02894                  Vcb,
    02895                  Extent->Lsn,
    02896                  Extent->Len ));
    02897
    02898     //
    02899     //  If the extent we begin from is not at least the size of an aligned descriptor
    02900     //  or is sized in base units other than aligned descriptors, we can't continue.
    02901     //
    02902
    02903     if (Extent->Len < UnitSize ||
    02904         Extent->Len % UnitSize) {
    02905
    02906         DebugTrace(( 0, Dbg,
    02907                      "UdfFindVolumeDescriptors, Base extent length %08x is mismatched with read size %08x\n",
    02908                      Extent->Len,
    02909                      UnitSize ));
    02910
    02911         DebugTrace(( -1, Dbg,
    02912                      "UdfFindVolumeDescriptors -> STATUS_DISK_CORRUPT_ERROR\n" ));
    02913
    02914         return STATUS_DISK_CORRUPT_ERROR;
    02915     }
    02916
    02917     //
    02918     //  Use a try-finally to facilitate cleanup.
    02919     //
    02920
    02921     try {
    02922
    02923         DebugTrace(( 0, Dbg,
    02924                      "UdfFindVolumeDescriptors, starting pass 1, find LVD/PVD\n" ));
    02925
    02926         //
    02927         //  We will make at least one pass through the Volume Descriptor Sequence to find
    02928         //  the prevailing versions of the two controlling descriptors - the PVD and LVD.
    02929         //  In order to avoid picking up partition descriptors that aren't actually going
    02930         //  to be referenced by the LVD, we will pick them up in a second pass if we find
    02931         //  a PVD and LVD that look reasonable and then stick them in a Pcb.
    02932         //
    02933
    02934         for (ThisPass = 1; ThisPass <= 2; ThisPass++) {
    02935
    02936             for ( //
    02937                   //  Home ourselves in the search and make a pass through the sequence.
    02938                   //
    02939
    02940                   Offset = LlBytesFromSectors( Vcb, Extent->Lsn ),
    02941                   Len = Extent->Len;
    02942
    02943                   //
    02944                   //  If we have reached the end of the extent's indicated valid
    02945                   //  length, we are done. This usually will not happen.
    02946                   //
    02947
    02948                   Len;
    02949
    02950                   //
    02951                   //  Advance to the next descriptor offset in the sequence.
    02952                   //
    02953
    02954                   Offset += UnitSize,
    02955                   Len -= UnitSize ) {
    02956
    02957                 //
    02958                 //  Allocate a buffer to read generic volume descriptors.
    02959                 //
    02960
    02961                 if (GenericVD == NULL) {
    02962
    02963                     GenericVD = (PNSR_VD_GENERIC) FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    02964                                                                             UdfRawBufferSize( Vcb, sizeof(NSR_VD_GENERIC) ),
    02965                                                                             TAG_NSR_VDSD );
    02966                 }
    02967
    02968                 Status = UdfReadSectors( IrpContext,
    02969                                          Offset,
    02970                                          UnitSize,
    02971                                          TRUE,
    02972                                          GenericVD,
    02973                                          Vcb->TargetDeviceObject );
    02974
    02975                 //
    02976                 //  Thise is a decent sign that this is an unrecorded sector and is
    02977                 //  defined to terminate the sequence.
    02978                 //
    02979
    02980                 if (!NT_SUCCESS( Status )) {
    02981
    02982                     break;
    02983                 }
    02984
    02985                 if (GenericVD->Destag.Ident > DESTAG_ID_MAXIMUM_PART3 ||
    02986
    02987                     !UdfVerifyDescriptor( IrpContext,
    02988                                           &GenericVD->Destag,
    02989                                           GenericVD->Destag.Ident,
    02990                                           sizeof(NSR_VD_GENERIC),
    02991                                           (ULONG) SectorsFromBytes( Vcb, Offset ),
    02992                                           TRUE)) {
    02993
    02994                     //
    02995                     //  If we spot an illegal descriptor type in the stream, there is no reasonable
    02996                     //  way to guess that we can continue (the disc may be trash beyond this point).
    02997                     //  Likewise, even if we have a single corrupt descriptor we cannot continue because
    02998                     //  this may be corruption of a descriptor we may have otherwise required for operation
    02999                     //  (i.e., one of the prevailing descriptors).
    03000                     //
    03001
    03002                     DebugTrace(( 0, Dbg,
    03003                                  "UdfFindVolumeDescriptors, descriptor didn't verify\n" ));
    03004
    03005                     try_leave( Status = STATUS_DISK_CORRUPT_ERROR );
    03006                 }
    03007
    03008                 if (GenericVD->Destag.Ident == DESTAG_ID_NSR_TERM) {
    03009
    03010                     //
    03011                     //  The Terminating Descriptor (3/10.9) is the usual way to stop a search.
    03012                     //
    03013
    03014                     break;
    03015                 }
    03016
    03017                 if (GenericVD->Destag.Ident == DESTAG_ID_NSR_VDP) {
    03018
    03019                     //
    03020                     //  Follow a Volume Desciptor Pointer (3/10.3) to the next extent of the sequence.
    03021                     //
    03022
    03023                     Offset = LlBytesFromSectors( Vcb, ((PNSR_VDP) GenericVD)->Next.Lsn );
    03024                     Len = ((PNSR_VDP) GenericVD)->Next.Len;
    03025
    03026                     //
    03027                     //  We cannot do anything if the extent is invalid
    03028                     //
    03029
    03030                     if (Len < UnitSize ||
    03031                         Len % UnitSize) {
    03032
    03033                         DebugTrace(( 0, Dbg,
    03034                                      "UdfFindVolumeDescriptors, following extent length %08x is mismatched with read size %08x\n",
    03035                                      Extent->Len,
    03036                                      UnitSize ));
    03037
    03038                         try_leave( Status = STATUS_DISK_CORRUPT_ERROR );
    03039                     }
    03040                 }
    03041
    03042                 DebugTrace(( 0, Dbg,
    03043                              "UdfFindVolumeDescriptors, descriptor tag %08x\n",
    03044                              GenericVD->Destag.Ident ));
    03045
    03046                 if (ThisPass == 1) {
    03047
    03048                     //
    03049                     //  Our first pass is to find prevailing LVD and PVD.
    03050                     //
    03051
    03052                     switch (GenericVD->Destag.Ident) {
    03053
    03054                         case DESTAG_ID_NSR_PVD:
    03055
    03056                             UdfStoreVolumeDescriptorIfPrevailing( (PNSR_VD_GENERIC *) PrimaryVolumeDescriptor,
    03057                                                                   GenericVD );
    03058                             break;
    03059
    03060                         case DESTAG_ID_NSR_LVOL:
    03061
    03062                             UdfStoreVolumeDescriptorIfPrevailing( (PNSR_VD_GENERIC *) LogicalVolumeDescriptor,
    03063                                                                   GenericVD );
    03064                             break;
    03065
    03066                         default:
    03067
    03068                             break;
    03069                     }
    03070
    03071                 } else {
    03072
    03073                     PNSR_PART PartitionDescriptor = (PNSR_PART) GenericVD;
    03074
    03075                     //
    03076                     //  Our second pass is to pick up all relavent NSR02 PD
    03077                     //
    03078
    03079                     if (PartitionDescriptor->Destag.Ident != DESTAG_ID_NSR_PART ||
    03080                         !UdfEqualEntityId( &PartitionDescriptor->ContentsID, &UdfNSR02Identifier, NULL )) {
    03081
    03082                         continue;
    03083                     }
    03084
    03085                     UdfAddToPcb( *Pcb, (PNSR_PART) GenericVD );
    03086                 }
    03087             }
    03088
    03089             //
    03090             //  Now that a pass through the VDS has been completed, analyze the results.
    03091             //
    03092
    03093             if (ThisPass == 1) {
    03094
    03095                 PNSR_PVD PVD;
    03096                 PNSR_LVOL LVD;
    03097
    03098                 //
    03099                 //  Reference the descriptors for ease of use
    03100                 //
    03101
    03102                 PVD = *PrimaryVolumeDescriptor;
    03103                 LVD = *LogicalVolumeDescriptor;
    03104
    03105                 //
    03106                 //  Check that the descriptors indicate a logical volume which appears to
    03107                 //  be a valid UDF volume.
    03108                 //
    03109
    03110                 if ((PVD == NULL &&
    03111                      DebugTrace(( 0, Dbg,
    03112                                   "UdfFindVolumeDescriptors, don't have a PVD\n" ))) ||
    03113                     (LVD == NULL &&
    03114                      DebugTrace(( 0, Dbg,
    03115                                   "UdfFindVolumeDescriptors, don't have an LVD\n" ))) ||
    03116
    03117                     //
    03118                     //  Now check the PVD
    03119                     //
    03120
    03121                     //
    03122                     //  The Volume Set Sequence fields indicates how many volumes form
    03123                     //  the volume set and what number this volume is in that sequence.
    03124                     //  We are a level 2 implementation, meaning that the volumes we read
    03125                     //  consist of a single volume. (3/11)
    03126                     //
    03127
    03128                     (PVD->VolSetSeq > 1 &&
    03129                      DebugTrace(( 0, Dbg,
    03130                                   "UdfFindVolumeDescriptors, PVD VolSetSeq %08x - not volume 1 of a volume set\n",
    03131                                   PVD->VolSetSeq ))) ||
    03132                     (PVD->VolSetSeqMax > 1 &&
    03133                      DebugTrace(( 0, Dbg,
    03134                                   "UdfFindVolumeDescriptors, PVD VolSetSeqMax %08x - volume in a non-unit volume set\n",
    03135                                   PVD->VolSetSeqMax ))) ||
    03136
    03137
    03138 #ifndef UDF_SUPPORT_NONSTANDARD_ALLSTOR
    03139
    03140                     //
    03141                     //  Disable checking of character set lists.
    03142                     //
    03143                     //  Reason: first drop of Allstor media recorded these fields as 0x0.
    03144                     //
    03145
    03146                     //
    03147                     //  Insure that Character Set Lists conform to UDF
    03148                     //
    03149
    03150                     (PVD->CharSetList != UDF_CHARSETLIST &&
    03151                      DebugTrace(( 0, Dbg,
    03152                                   "UdfFindVolumeDescriptors, PVD CharSetList %08x != CS0 only\n",
    03153                                   PVD->CharSetList ))) ||
    03154                     (PVD->CharSetListMax != UDF_CHARSETLIST &&
    03155                      DebugTrace(( 0, Dbg,
    03156                                   "UdfFindVolumeDescriptors, PVD CharSetListMax %08x != CS0 only\n",
    03157                                   PVD->CharSetListMax ))) ||
    03158
    03159                     //
    03160                     //  Disable checking of character set lists.
    03161                     //
    03162                     //  Reason: first drop of Allstor media misspelled "Compressed" as "Copmressed"
    03163                     //
    03164
    03165                     //
    03166                     //  The two character sets must be UDF CS0.  CS0 is a "by convention"
    03167                     //  character set in ISO 13346, which UDF specifies for our domain.
    03168                     //
    03169
    03170                     (!UdfEqualCharspec( &PVD->CharsetDesc, &UdfCS0Identifier, CHARSPEC_T_CS0 ) &&
    03171                      DebugTrace(( 0, Dbg,
    03172                                  "UdfFindVolumeDescriptors, PVD CharsetDesc != CS0 only\n" ))) ||
    03173                     (!UdfEqualCharspec( &PVD->CharsetExplan, &UdfCS0Identifier, CHARSPEC_T_CS0 ) &&
    03174                      DebugTrace(( 0, Dbg,
    03175                                   "UdfFindVolumeDescriptors, PVD CharsetExplan != CS0 only\n" ))) ||
    03176
    03177 #endif
    03178                     //
    03179                     //  Now check the LVD
    03180                     //
    03181
    03182                     //
    03183                     //  The LVD is a variant sized structure.  Check that the claimed size fits in a single
    03184                     //  logical sector.  Although an LVD may legally exceed a single sector, we will never
    03185                     //  want to deal with such a volume.
    03186                     //
    03187
    03188                     (ISONsrLvolSize( LVD ) > SectorSize( Vcb ) &&
    03189                      DebugTrace(( 0, Dbg,
    03190                                   "UdfFindVolumeDescriptors, LVD is bigger than a sector\n" ))) ||
    03191
    03192 #ifndef UDF_SUPPORT_NONSTANDARD_ALLSTOR
    03193
    03194                     //
    03195                     //  Disable checking of character set lists.
    03196                     //
    03197                     //  Reason: first drop of Allstor media recorded these fields as 0x0.
    03198                     //
    03199
    03200                     //
    03201                     //  The character set used in the LVD must be UDF CS0 as well.
    03202                     //
    03203
    03204                     (!UdfEqualCharspec( &LVD->Charset, &UdfCS0Identifier, CHARSPEC_T_CS0 ) &&
    03205                      DebugTrace(( 0, Dbg,
    03206                                  "UdfFindVolumeDescriptors, LVD Charset != CS0 only\n" ))) ||
    03207 #endif
    03208
    03209                     //
    03210                     //  The specified block size must equal the physical sector size.
    03211                     //
    03212
    03213                     (LVD->BlockSize != SectorSize( Vcb ) &&
    03214                      DebugTrace(( 0, Dbg,
    03215                                   "UdfFindVolumeDescriptors, LVD BlockSize %08x != SectorSize %08x\n" ))) ||
    03216
    03217                     //
    03218                     //  The domain must be within the version we read
    03219                     //
    03220
    03221                     (!UdfDomainIdentifierContained( &LVD->DomainID,
    03222                                                     &UdfDomainIdentifier,
    03223                                                     UDF_VERSION_MINIMUM,
    03224                                                     UDF_VERSION_RECOGNIZED ) &&
    03225                      DebugTrace(( 0, Dbg,
    03226                                   "UdfFindVolumeDescriptors, domain ID indicates unreadable volume\n" ))) ||
    03227
    03228                     //
    03229                     //  Although we can handle any number of partitions, UDF only specifies
    03230                     //  a single partition or special dual partition formats.
    03231                     //
    03232
    03233                     (LVD->MapTableCount > 2 &&
    03234                      DebugTrace(( 0, Dbg,
    03235                                   "UdfFindVolumeDescriptors, LVD MapTableCount %08x greater than allowed (2)\n",
    03236                                   LVD->MapTableCount )))
    03237                     ) {
    03238
    03239                     DebugTrace(( 0, Dbg,
    03240                                  "UdfFindVolumeDescriptors, ... so returning STATUS_UNRECOGNIZED_VOLUME\n" ));
    03241
    03242                     try_leave( Status = STATUS_UNRECOGNIZED_VOLUME );
    03243                 }
    03244
    03245                 //
    03246                 //  Now that we have performed the simple field checks, build a Pcb.
    03247                 //
    03248
    03249                 Status = UdfInitializePcb( IrpContext, Vcb, Pcb, LVD );
    03250
    03251                 if (!NT_SUCCESS(Status)) {
    03252
    03253                     DebugTrace(( 0, Dbg,
    03254                                  "UdfFindVolumeDescriptors, Pcb intialization failed (!)\n" ));
    03255
    03256                     try_leave( Status );
    03257                 }
    03258             }
    03259
    03260             //
    03261             //  Go onto Pass 2 to find the Partition Descriptors
    03262             //
    03263
    03264             DebugTrace(( 0, Dbg,
    03265                          "UdfFindVolumeDescriptors, starting pass 2, find associated PD\n" ));
    03266         }
    03267
    03268     } finally {
    03269
    03270         DebugUnwind( "UdfFindVolumeDescriptors" );
    03271
    03272         //
    03273         //  Free up the buffer space we may have allocated
    03274         //
    03275
    03276         UdfFreePool( &GenericVD );
    03277     }
    03278
    03279     DebugTrace(( -1, Dbg,
    03280                  "UdfFindVolumeDescriptors -> %08x\n", Status ));
    03281
    03282     //
    03283     //  Success is when we've really found something.  If we failed to find both
    03284     //  descriptors, commute whatever intermediate status was involved and clean up.
    03285     //
    03286
    03287     if (*PrimaryVolumeDescriptor == NULL || *LogicalVolumeDescriptor == NULL) {
    03288
    03289         Status = STATUS_UNRECOGNIZED_VOLUME;
    03290     }
    03291
    03292     if (!NT_SUCCESS( Status )) {
    03293
    03294         UdfFreePool(PrimaryVolumeDescriptor);
    03295         UdfFreePool(LogicalVolumeDescriptor);
    03296     }
    03297
    03298     return Status;
    03299 }

NTSTATUS UdfInvalidateVolumes | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 1271 of file udfs/fsctrl.c.

References _IRP::AssociatedIrp, ClearFlag, _FILE_OBJECT::DeviceObject, ExAllocatePoolWithTag, FALSE, FlagOn, _VPB::Flags, Handle, IO_TYPE_VPB, IoAcquireVpbSpinLock(), IoFileObjectType, IoGetCurrentIrpStackLocation, IoReleaseVpbSpinLock(), Irp, IRP_CONTEXT_FLAG_FORCE_POST, IRP_CONTEXT_FLAG_WAIT, KernelMode, NonPagedPoolMustSucceed, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObjectByHandle(), _IO_STACK_LOCATION::Parameters, _VPB::RealDevice, _IRP::RequestorMode, SeSinglePrivilegeCheck(), SetFlag, _VPB::Size, Status, TAG_VPB, TcbPrivilege, _VPB::Type, UdfAcquireUdfData, UdfCheckForDismount(), UdfCompleteRequest(), UdfData, UdfLockVcb, UdfPurgeVolume(), UdfReleaseUdfData, UdfUnlockVcb, VCB, _VCB::VcbCondition, VcbDismountInProgress, VcbInvalid, _UDF_DATA::VcbQueue, _VCB::Vpb, _DEVICE_OBJECT::Vpb, VPB, and VPB_REMOVE_PENDING.

Referenced by UdfUserFsctl().

    01278                    :
    01279
    01280     This routine searches for all the volumes mounted on the same real device
    01281     of the current DASD handle, and marks them all bad.  The only operation
    01282     that can be done on such handles is cleanup and close.
    01283
    01284 Arguments:
    01285
    01286     Irp - Supplies the Irp to process
    01287
    01288 Return Value:
    01289
    01290     NTSTATUS - The return status for the operation
    01291
    01292 --*/
    01293
    01294 {
    01295     NTSTATUS Status;
    01296     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01297     KIRQL SavedIrql;
    01298
    01299     LUID TcbPrivilege = {SE_TCB_PRIVILEGE, 0};
    01300
    01301     HANDLE Handle;
    01302
    01303     PVPB NewVpb;
    01304     PVCB Vcb;
    01305
    01306     PLIST_ENTRY Links;
    01307
    01308     PFILE_OBJECT FileToMarkBad;
    01309     PDEVICE_OBJECT DeviceToMarkBad;
    01310
    01311     //
    01312     //  Check for the correct security access.
    01313     //  The caller must have the SeTcbPrivilege.
    01314     //
    01315
    01316     if (!SeSinglePrivilegeCheck( TcbPrivilege, Irp->RequestorMode )) {
    01317
    01318         UdfCompleteRequest( IrpContext, Irp, STATUS_PRIVILEGE_NOT_HELD );
    01319
    01320         return STATUS_PRIVILEGE_NOT_HELD;
    01321     }
    01322
    01323     //
    01324     //  Try to get a pointer to the device object from the handle passed in.
    01325     //
    01326
    01327     if (IrpSp->Parameters.FileSystemControl.InputBufferLength != sizeof( HANDLE )) {
    01328
    01329         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    01330         return STATUS_INVALID_PARAMETER;
    01331     }
    01332
    01333     Handle = *((PHANDLE) Irp->AssociatedIrp.SystemBuffer);
    01334
    01335     Status = ObReferenceObjectByHandle( Handle,
    01336                                         0,
    01337                                         *IoFileObjectType,
    01338                                         KernelMode,
    01339                                         &FileToMarkBad,
    01340                                         NULL );
    01341
    01342     if (!NT_SUCCESS(Status)) {
    01343
    01344         UdfCompleteRequest( IrpContext, Irp, Status );
    01345         return Status;
    01346     }
    01347
    01348     //
    01349     //  Grab the DeviceObject from the FileObject.
    01350     //
    01351
    01352     DeviceToMarkBad = FileToMarkBad->DeviceObject;
    01353
    01354     //
    01355     //  We only needed the device object involved, not a reference to the file.
    01356     //
    01357
    01358     ObDereferenceObject( FileToMarkBad );
    01359
    01360     //
    01361     //  Create a new Vpb for this device so that any new opens will mount
    01362     //  a new volume.
    01363     //
    01364
    01365     NewVpb = ExAllocatePoolWithTag( NonPagedPoolMustSucceed, sizeof( VPB ), TAG_VPB );
    01366     RtlZeroMemory( NewVpb, sizeof( VPB ) );
    01367
    01368     NewVpb->Type = IO_TYPE_VPB;
    01369     NewVpb->Size = sizeof( VPB );
    01370     NewVpb->RealDevice = DeviceToMarkBad;
    01371     NewVpb->Flags = FlagOn( DeviceToMarkBad->Vpb->Flags, VPB_REMOVE_PENDING );
    01372
    01373     //
    01374     //  Make sure this request can wait.
    01375     //
    01376
    01377     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    01378     ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
    01379
    01380     UdfAcquireUdfData( IrpContext );
    01381
    01382     //
    01383     //  Nothing can go wrong now.
    01384     //
    01385
    01386     IoAcquireVpbSpinLock( &SavedIrql );
    01387     DeviceToMarkBad->Vpb = NewVpb;
    01388     IoReleaseVpbSpinLock( SavedIrql );
    01389
    01390     //
    01391     //  Now walk through all the mounted Vcb's looking for candidates to
    01392     //  mark invalid.
    01393     //
    01394     //  On volumes we mark invalid, check for dismount possibility (which is
    01395     //  why we have to get the next link so early).
    01396     //
    01397
    01398     Links = UdfData.VcbQueue.Flink;
    01399
    01400     while (Links != &UdfData.VcbQueue) {
    01401
    01402         Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks);
    01403
    01404         Links = Links->Flink;
    01405
    01406         //
    01407         //  If we get a match, mark the volume Bad, and also check to
    01408         //  see if the volume should go away.
    01409         //
    01410
    01411         UdfLockVcb( IrpContext, Vcb );
    01412
    01413         if (Vcb->Vpb->RealDevice == DeviceToMarkBad) {
    01414
    01415             if (Vcb->VcbCondition != VcbDismountInProgress) {
    01416
    01417                 Vcb->VcbCondition = VcbInvalid;
    01418             }
    01419
    01420             UdfUnlockVcb( IrpContext, Vcb );
    01421
    01422             UdfPurgeVolume( IrpContext, Vcb, FALSE );
    01423
    01424             UdfCheckForDismount( IrpContext, Vcb, FALSE );
    01425
    01426         } else {
    01427
    01428             UdfUnlockVcb( IrpContext, Vcb );
    01429         }
    01430     }
    01431
    01432     UdfReleaseUdfData( IrpContext );
    01433
    01434     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    01435     return STATUS_SUCCESS;
    01436 }

NTSTATUS UdfIsPathnameValid | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 1236 of file udfs/fsctrl.c.

References Irp, PAGED_CODE, and UdfCompleteRequest().

Referenced by UdfUserFsctl().

    01243                    :
    01244
    01245     This routine determines if pathname is a valid UDFS pathname.
    01246     We always succeed this request.
    01247
    01248 Arguments:
    01249
    01250     Irp - Supplies the Irp to process.
    01251
    01252 Return Value:
    01253
    01254     None
    01255
    01256 --*/
    01257
    01258 {
    01259     PAGED_CODE();
    01260
    01261     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    01262     return STATUS_SUCCESS;
    01263 }

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

Definition at line 2439 of file udfs/fsctrl.c.

References ASSERT_IRP_CONTEXT, ASSERT_VCB, Dbg, DebugTrace, FALSE, PAGED_CODE, _VPB::RealDevice, _VPB::SerialNumber, TRUE, UdfData, VcbNotMounted, _UDF_DATA::VcbQueue, _VPB::VolumeLabel, and _VPB::VolumeLabelLength.

Referenced by UdfMountVolume().

    02447                    :
    02448
    02449     This routine walks through the links of the Vcb chain in the global
    02450     data structure.  The remount condition is met when the following
    02451     conditions are all met:
    02452
    02453             1 - The 32 serial for this VPB matches that in a previous
    02454                 VPB.
    02455
    02456             2 - The volume label for this VPB matches that in the previous
    02457                 VPB.
    02458
    02459             3 - The system pointer to the real device object in the current
    02460                 VPB matches that in the same previous VPB.
    02461
    02462             4 - Finally the previous Vcb cannot be invalid or have a dismount
    02463                 underway.
    02464
    02465     If a VPB is found which matches these conditions, then the address of
    02466     the Vcb for that VPB is returned via the pointer OldVcb.
    02467
    02468     Skip over the current Vcb.
    02469
    02470 Arguments:
    02471
    02472     Vcb - This is the Vcb we are checking for a remount.
    02473
    02474     OldVcb -  A pointer to the address to store the address for the Vcb
    02475               for the volume if this is a remount.  (This is a pointer to
    02476               a pointer)
    02477
    02478 Return Value:
    02479
    02480     BOOLEAN - TRUE if this is in fact a remount, FALSE otherwise.
    02481
    02482 --*/
    02483
    02484 {
    02485     PLIST_ENTRY Link;
    02486
    02487     PVPB Vpb = Vcb->Vpb;
    02488     PVPB OldVpb;
    02489
    02490     BOOLEAN Remount = FALSE;
    02491
    02492     PAGED_CODE();
    02493
    02494     //
    02495     //  Check input.
    02496     //
    02497
    02498     ASSERT_IRP_CONTEXT( IrpContext );
    02499     ASSERT_VCB( Vcb );
    02500
    02501     DebugTrace(( +1, Dbg, "UdfIsRemount, Vcb %08x\n", Vcb ));
    02502
    02503     for (Link = UdfData.VcbQueue.Flink;
    02504          Link != &UdfData.VcbQueue;
    02505          Link = Link->Flink) {
    02506
    02507         *OldVcb = CONTAINING_RECORD( Link, VCB, VcbLinks );
    02508
    02509         //
    02510         //  Skip ourselves.
    02511         //
    02512
    02513         if (Vcb == *OldVcb) { continue; }
    02514
    02515         //
    02516         //  Look at the Vpb and state of the previous Vcb.
    02517         //
    02518
    02519         OldVpb = (*OldVcb)->Vpb;
    02520
    02521         if ((OldVpb != Vpb) &&
    02522             (OldVpb->RealDevice == Vpb->RealDevice) &&
    02523             ((*OldVcb)->VcbCondition == VcbNotMounted)) {
    02524
    02525             //
    02526             //  Go ahead and compare serial numbers and volume label.
    02527             //
    02528
    02529             if ((OldVpb->SerialNumber == Vpb->SerialNumber) &&
    02530                        (Vpb->VolumeLabelLength == OldVpb->VolumeLabelLength) &&
    02531                        (RtlEqualMemory( OldVpb->VolumeLabel,
    02532                                         Vpb->VolumeLabel,
    02533                                         Vpb->VolumeLabelLength ))) {
    02534
    02535                 //
    02536                 //  Got it.
    02537                 //
    02538
    02539                 DebugTrace(( 0, Dbg, "UdfIsRemount, matched OldVcb %08x\n", *OldVcb ));
    02540
    02541                 Remount = TRUE;
    02542                 break;
    02543             }
    02544         }
    02545     }
    02546
    02547     DebugTrace(( -1, Dbg, "UdfIsRemount -> %c\n", (Remount? 'T' : 'F' )));
    02548
    02549     return Remount;
    02550 }

UdfIsVolumeDirty | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 1064 of file udfs/fsctrl.c.

References _IRP::AssociatedIrp, _IO_STACK_LOCATION::FileObject, IoGetCurrentIrpStackLocation, _IRP::IoStatus, Irp, _IRP::MdlAddress, MmGetSystemAddressForMdlSafe, NormalPagePriority, NULL, _IO_STACK_LOCATION::Parameters, TYPE_OF_OPEN, UdfCompleteRequest(), UdfDecodeFileObject(), UserVolumeOpen, _FCB::Vcb, _VCB::VcbCondition, and VcbMounted.

Referenced by UdfUserFsctl().

    01071                    :
    01072
    01073     This routine determines if a volume is currently dirty.
    01074
    01075 Arguments:
    01076
    01077     Irp - Supplies the Irp to process
    01078
    01079 Return Value:
    01080
    01081     NTSTATUS - The return status for the operation
    01082
    01083 --*/
    01084
    01085 {
    01086     PIO_STACK_LOCATION IrpSp;
    01087
    01088     TYPE_OF_OPEN TypeOfOpen;
    01089     PVCB Vcb;
    01090     PFCB Fcb;
    01091     PCCB Ccb;
    01092
    01093     PULONG VolumeState;
    01094
    01095     //
    01096     //  Get the current stack location and extract the output
    01097     //  buffer information.
    01098     //
    01099
    01100     IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01101
    01102     //
    01103     //  Get a pointer to the output buffer.  Look at the system buffer field in the
    01104     //  irp first.  Then the Irp Mdl.
    01105     //
    01106
    01107     if (Irp->AssociatedIrp.SystemBuffer != NULL) {
    01108
    01109         VolumeState = Irp->AssociatedIrp.SystemBuffer;
    01110
    01111     } else if (Irp->MdlAddress != NULL) {
    01112
    01113         VolumeState = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
    01114
    01115         if (NULL == VolumeState)  {
    01116
    01117             UdfCompleteRequest( IrpContext, Irp, STATUS_INSUFFICIENT_RESOURCES );
    01118             return STATUS_INSUFFICIENT_RESOURCES;
    01119         }
    01120     } else {
    01121
    01122         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_USER_BUFFER );
    01123         return STATUS_INVALID_USER_BUFFER;
    01124     }
    01125
    01126     //
    01127     //  Make sure the output buffer is large enough and then initialize
    01128     //  the answer to be that the volume isn't dirty.
    01129     //
    01130
    01131     if (IrpSp->Parameters.FileSystemControl.OutputBufferLength < sizeof(ULONG)) {
    01132
    01133         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    01134         return STATUS_INVALID_PARAMETER;
    01135     }
    01136
    01137     *VolumeState = 0;
    01138
    01139     //
    01140     //  Decode the file object
    01141     //
    01142
    01143     TypeOfOpen = UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    01144
    01145     if (TypeOfOpen != UserVolumeOpen) {
    01146
    01147         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    01148         return STATUS_INVALID_PARAMETER;
    01149     }
    01150
    01151     if (Fcb->Vcb->VcbCondition != VcbMounted) {
    01152
    01153         UdfCompleteRequest( IrpContext, Irp, STATUS_VOLUME_DISMOUNTED );
    01154         return STATUS_VOLUME_DISMOUNTED;
    01155     }
    01156
    01157     //
    01158     //  Now set up to return the clean state.  If we paid attention to the dirty
    01159     //  state of the media we could be more accurate, but since this is a readonly
    01160     //  implementation at the moment we think it is clean all of the time.
    01161     //
    01162
    01163     Irp->IoStatus.Information = sizeof( ULONG );
    01164
    01165     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    01166     return STATUS_SUCCESS;
    01167 }

NTSTATUS UdfIsVolumeMounted | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 1175 of file udfs/fsctrl.c.

References _IO_STACK_LOCATION::FileObject, IoGetCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_DISABLE_POPUPS, NULL, PAGED_CODE, SetFlag, UdfCompleteRequest(), UdfDecodeFileObject(), UdfVerifyVcb(), and _FCB::Vcb.

Referenced by UdfUserFsctl().

    01182                    :
    01183
    01184     This routine determines if a volume is currently mounted.
    01185
    01186 Arguments:
    01187
    01188     Irp - Supplies the Irp to process
    01189
    01190 Return Value:
    01191
    01192     NTSTATUS - The return status for the operation
    01193
    01194 --*/
    01195
    01196 {
    01197     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01198
    01199     PFCB Fcb;
    01200     PCCB Ccb;
    01201
    01202     PAGED_CODE();
    01203
    01204     //
    01205     //  Decode the file object.
    01206     //
    01207
    01208     UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb );
    01209
    01210     if (Fcb != NULL) {
    01211
    01212         //
    01213         //  Disable PopUps, we want to return any error.
    01214         //
    01215
    01216         SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS );
    01217
    01218         //
    01219         //  Verify the Vcb.  This will raise in the error condition.
    01220         //
    01221
    01222         UdfVerifyVcb( IrpContext, Fcb->Vcb );
    01223     }
    01224
    01225     UdfCompleteRequest( IrpContext, Irp, STATUS_SUCCESS );
    01226
    01227     return STATUS_SUCCESS;
    01228 }

NTSTATUS UdfLockVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 780 of file udfs/fsctrl.c.

References FALSE, _IO_STACK_LOCATION::FileObject, FSRTL_VOLUME_LOCK, FSRTL_VOLUME_LOCK_FAILED, FsRtlNotifyVolumeEvent(), IoGetCurrentIrpStackLocation, Irp, NT_SUCCESS, NTSTATUS(), PAGED_CODE, Status, UdfAcquireVcbExclusive, UdfCompleteRequest(), UdfDecodeFileObject(), UdfLockVolumeInternal(), UdfReleaseVcb, UdfVerifyVcb(), UserVolumeOpen, and _FCB::Vcb.

Referenced by UdfUserFsctl().

    00787                    :
    00788
    00789     This routine performs the lock volume operation.  It is responsible for
    00790     either completing of enqueuing the input Irp.
    00791
    00792 Arguments:
    00793
    00794     Irp - Supplies the Irp to process
    00795
    00796 Return Value:
    00797
    00798     NTSTATUS - The return status for the operation
    00799
    00800 --*/
    00801
    00802 {
    00803     NTSTATUS Status;
    00804
    00805     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00806
    00807     PVCB Vcb;
    00808     PFCB Fcb;
    00809     PCCB Ccb;
    00810
    00811     PAGED_CODE();
    00812
    00813     //
    00814     //  Decode the file object, the only type of opens we accept are
    00815     //  user volume opens.
    00816     //
    00817
    00818     if (UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen) {
    00819
    00820         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00821
    00822         return STATUS_INVALID_PARAMETER;
    00823     }
    00824
    00825     //
    00826     //  Send our notification so that folks that like to hold handles on
    00827     //  volumes can get out of the way.
    00828     //
    00829
    00830     FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_LOCK );
    00831
    00832     //
    00833     //  Acquire exclusive access to the Vcb.
    00834     //
    00835
    00836     Vcb = Fcb->Vcb;
    00837     UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00838
    00839     try {
    00840
    00841         //
    00842         //  Verify the Vcb.
    00843         //
    00844
    00845         UdfVerifyVcb( IrpContext, Vcb );
    00846
    00847         Status = UdfLockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
    00848
    00849     } finally {
    00850
    00851         //
    00852         //  Release the Vcb.
    00853         //
    00854
    00855         UdfReleaseVcb( IrpContext, Vcb );
    00856
    00857         if (AbnormalTermination() || !NT_SUCCESS( Status )) {
    00858
    00859             FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_LOCK_FAILED );
    00860         }
    00861     }
    00862
    00863     //
    00864     //  Complete the request if there haven't been any exceptions.
    00865     //
    00866
    00867     UdfCompleteRequest( IrpContext, Irp, Status );
    00868     return Status;
    00869 }

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

Definition at line 621 of file udfs/fsctrl.c.

References ASSERT_EXCLUSIVE_VCB, CcWaitForCurrentLazyWriterActivity(), FALSE, FlagOn, IRP_CONTEXT_FLAG_WAIT, NT_SUCCESS, NTSTATUS(), PAGED_CODE, SetFlag, Status, UdfAcquireVcbExclusive, UdfFspClose(), UdfPurgeVolume(), UdfReleaseVcb, and VCB_STATE_LOCKED.

Referenced by UdfLockVolume(), and UdfPnpQueryRemove().

    00629                    :
    00630
    00631     This routine performs the actual lock volume operation.  It will be called
    00632     by anyone wishing to try to protect the volume for a long duration.  PNP
    00633     operations are such a user.
    00634
    00635     The volume must be held exclusive by the caller.
    00636
    00637 Arguments:
    00638
    00639     Vcb - The volume being locked.
    00640
    00641     FileObject - File corresponding to the handle locking the volume.  If this
    00642         is not specified, a system lock is assumed.
    00643
    00644 Return Value:
    00645
    00646     NTSTATUS - The return status for the operation
    00647
    00648 --*/
    00649
    00650 {
    00651     NTSTATUS Status;
    00652     NTSTATUS FinalStatus = (FileObject? STATUS_ACCESS_DENIED: STATUS_DEVICE_BUSY);
    00653     ULONG RemainingUserReferences = (FileObject? 1: 0);
    00654
    00655     PAGED_CODE();
    00656
    00657     ASSERT_EXCLUSIVE_VCB( Vcb );
    00658
    00659     //
    00660     //  If the volume is already locked then complete with success if this file
    00661     //  object has the volume locked, fail otherwise.
    00662     //
    00663
    00664     if (FlagOn( Vcb->VcbState, VCB_STATE_LOCKED )) {
    00665
    00666         if (FileObject && Vcb->VolumeLockFileObject == FileObject) {
    00667
    00668             FinalStatus = STATUS_SUCCESS;
    00669         }
    00670
    00671     } else if (Vcb->VcbCleanup == RemainingUserReferences) {
    00672
    00673         //
    00674         //  The cleanup count for the volume only reflects the fileobject that
    00675         //  will lock the volume.  Otherwise, we must fail the request.
    00676         //
    00677         //  Since the only cleanup is for the provided fileobject, we will try
    00678         //  to get rid of all of the other user references.  If there is only one
    00679         //  remaining after the purge then we can allow the volume to be locked.
    00680         //
    00681
    00682         UdfPurgeVolume( IrpContext, Vcb, FALSE );
    00683
    00684         //
    00685         //  Now back out of our synchronization and wait for the lazy writer
    00686         //  to finish off any lazy closes that could have been outstanding.
    00687         //
    00688         //  Since we purged, we know that the lazy writer will issue all
    00689         //  possible lazy closes in the next tick - if we hadn't, an otherwise
    00690         //  unopened file with a large amount of dirty data could have hung
    00691         //  around for a while as the data trickled out to the disk.
    00692         //
    00693         //  This is even more important now since we send notification to
    00694         //  alert other folks that this style of check is about to happen so
    00695         //  that they can close their handles.  We don't want to enter a fast
    00696         //  race with the lazy writer tearing down his references to the file.
    00697         //
    00698
    00699         UdfReleaseVcb( IrpContext, Vcb );
    00700
    00701         Status = CcWaitForCurrentLazyWriterActivity();
    00702
    00703         //
    00704         //  This is intentional. If we were able to get the Vcb before, just
    00705         //  wait for it and take advantage of knowing that it is OK to leave
    00706         //  the flag up.
    00707         //
    00708
    00709         SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    00710         UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00711
    00712         if (!NT_SUCCESS( Status )) {
    00713
    00714             return Status;
    00715         }
    00716
    00717         UdfFspClose( Vcb );
    00718
    00719         if (Vcb->VcbUserReference == Vcb->VcbResidualUserReference + RemainingUserReferences) {
    00720
    00721             SetFlag( Vcb->VcbState, VCB_STATE_LOCKED );
    00722             Vcb->VolumeLockFileObject = FileObject;
    00723             FinalStatus = STATUS_SUCCESS;
    00724         }
    00725     }
    00726
    00727     return FinalStatus;
    00728 }

NTSTATUS UdfMountVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 1444 of file udfs/fsctrl.c.

References _DEVICE_OBJECT::AlignmentRequirement, ASSERT, ASSERT_IRP, ASSERT_IRP_CONTEXT, _VCB::BoundN, _VCB::BoundS, ClearFlag, Dbg, DebugTrace, DebugUnwind, DEVICE_OBJECT, _VPB::DeviceObject, _DEVICE_OBJECT::DeviceType, DO_DEVICE_INITIALIZING, DO_VERIFY_VOLUME, _UDF_DATA::DriverObject, FALSE, FlagOn, _DEVICE_OBJECT::Flags, NSR_LVOL::FSD, FSRTL_VOLUME_MOUNT, FsRtlNotifyVolumeEvent(), IoCreateDevice(), IoDeleteDevice(), IoGetCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_WAIT, KeInitializeSpinLock(), NSR_ANCHOR::Main, _VCB::MediaChangeCount, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _VCB::Pcb, PVOLUME_DEVICE_OBJECT, _VPB::RealDevice, _VPB::ReferenceCount, NSR_ANCHOR::Reserve, _VCB::RootIndexFcb, _VPB::SerialNumber, SetFlag, _DEVICE_OBJECT::StackSize, Status, _VCB::TargetDeviceObject, TRUE, try_leave, UdfAcquireUdfData, UdfAcquireVcbExclusive, UdfCompletePcb(), UdfCompleteRequest(), UdfData, UdfDeletePcb(), UdfDetermineVolumeBounding(), UdfDisable, UdfDismountVcb(), UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfFreePool(), UdfHighBit(), UdfInitializeVcb(), UdfIsRemount(), UdfPerformDevIoCtrl(), UdfRecognizeVolume(), UdfReleaseUdfData, UdfReleaseVcb, UdfScanForDismountedVcb(), UdfUpdateVcbPhase0(), UdfUpdateVcbPhase1(), UdfUpdateVolumeLabel(), UdfUpdateVolumeSerialNumber(), VCB_STATE_METHOD_2_FIXUP, VCB_STATE_NOTIFY_REMOUNT, _VCB::VcbCondition, VcbMounted, _VCB::VcbReference, _VCB::VcbResidualReference, _VCB::VcbState, VOLUME_DEVICE_OBJECT, NSR_LVOL::VolumeID, _VPB::VolumeLabel, _VPB::VolumeLabelLength, _DEVICE_OBJECT::Vpb, and _VCB::Vpb.

Referenced by UdfCommonFsControl().

    01451                    :
    01452
    01453     This routine performs the mount volume operation.  It is responsible for
    01454     either completing of enqueuing the input Irp.
    01455
    01456     Its job is to verify that the volume denoted in the IRP is a UDF volume,
    01457     and create the VCB and root directory FCB structures.  The algorithm it
    01458     uses is essentially as follows:
    01459
    01460     1. Create a new Vcb Structure, and initialize it enough to do I/O
    01461        through the on-disk volume descriptors.
    01462
    01463     2. Read the disk and check if it is a UDF volume.
    01464
    01465     3. If it is not a UDF volume then delete the Vcb and
    01466        complete the IRP with STATUS_UNRECOGNIZED_VOLUME
    01467
    01468     4. Check if the volume was previously mounted and if it was then do a
    01469        remount operation.  This involves deleting the VCB, hook in the
    01470        old VCB, and complete the IRP.
    01471
    01472     5. Otherwise create a Vcb and root directory FCB
    01473
    01474 Arguments:
    01475
    01476     Irp - Supplies the Irp to process
    01477
    01478 Return Value:
    01479
    01480     NTSTATUS - The return status for the operation
    01481
    01482 --*/
    01483
    01484 {
    01485     NTSTATUS Status;
    01486
    01487     PVOLUME_DEVICE_OBJECT VolDo = NULL;
    01488     PVCB Vcb = NULL;
    01489     PVCB OldVcb = NULL;
    01490     PPCB Pcb = NULL;
    01491
    01492     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    01493     PDEVICE_OBJECT DeviceObjectWeTalkTo = IrpSp->Parameters.MountVolume.DeviceObject;
    01494     PVPB Vpb = IrpSp->Parameters.MountVolume.Vpb;
    01495
    01496     PFILE_OBJECT FileObjectToNotify = NULL;
    01497
    01498     ULONG MediaChangeCount = 0;
    01499
    01500     DISK_GEOMETRY DiskGeometry;
    01501
    01502     PNSR_ANCHOR AnchorVolumeDescriptor = NULL;
    01503     PNSR_PVD PrimaryVolumeDescriptor = NULL;
    01504     PNSR_LVOL LogicalVolumeDescriptor = NULL;
    01505     PNSR_FSD FileSetDescriptor = NULL;
    01506
    01507     BOOLEAN BridgeMedia;
    01508
    01509     PAGED_CODE();
    01510
    01511     //
    01512     //  Check the input parameters
    01513     //
    01514
    01515     ASSERT_IRP_CONTEXT( IrpContext );
    01516     ASSERT_IRP( Irp );
    01517
    01518     //
    01519     //  Check that we are talking to a Cdrom or Disk device.  This request should
    01520     //  always be waitable.
    01521     //
    01522
    01523     ASSERT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ||
    01524             Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK );
    01525     ASSERT( FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ));
    01526
    01527     DebugTrace(( +1, Dbg, "UdfMountVolume\n" ));
    01528
    01529     //
    01530     //  Update the real device in the IrpContext from the Vpb.  There was no available
    01531     //  file object when the IrpContext was created.
    01532     //
    01533
    01534     IrpContext->RealDevice = Vpb->RealDevice;
    01535
    01536     //
    01537     //  Check if we have disabled the mount process.
    01538     //
    01539
    01540     if (UdfDisable) {
    01541
    01542         UdfCompleteRequest( IrpContext, Irp, STATUS_UNRECOGNIZED_VOLUME );
    01543         DebugTrace(( 0, Dbg, "UdfMountVolume, disabled\n" ));
    01544         DebugTrace(( -1, Dbg, "UdfMountVolume -> STATUS_UNRECOGNIZED_VOLUME\n" ));
    01545
    01546         return STATUS_UNRECOGNIZED_VOLUME;
    01547     }
    01548
    01549     //
    01550     //  Do a CheckVerify here to lift the MediaChange ticker from the driver
    01551     //
    01552
    01553     Status = UdfPerformDevIoCtrl( IrpContext,
    01554                                   ( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
    01555                                     IOCTL_CDROM_CHECK_VERIFY :
    01556                                     IOCTL_DISK_CHECK_VERIFY ),
    01557                                   DeviceObjectWeTalkTo,
    01558                                   &MediaChangeCount,
    01559                                   sizeof(ULONG),
    01560                                   FALSE,
    01561                                   TRUE,
    01562                                   NULL );
    01563
    01564     if (!NT_SUCCESS( Status )) {
    01565
    01566         UdfCompleteRequest( IrpContext, Irp, Status );
    01567         DebugTrace(( 0, Dbg,
    01568                      "UdfMountVolume, CHECK_VERIFY handed back status %08x (so don't continue)\n",
    01569                      Status ));
    01570         DebugTrace(( -1, Dbg,
    01571                      "UdfMountVolume -> %08x\n",
    01572                      Status ));
    01573
    01574         return Status;
    01575     }
    01576
    01577     //
    01578     //  Now let's make Jeff delirious and call to get the disk geometry.  This
    01579     //  will fix the case where the first change line is swallowed.
    01580     //
    01581     //  This IOCTL does not have a generic STORAGE equivalent, so we must figure
    01582     //  our which variant to pass down from the real underlying device object (as
    01583     //  opposed to the top of the driver filter stack we will really be attaching
    01584     //  on top of).
    01585     //
    01586
    01587     Status = UdfPerformDevIoCtrl( IrpContext,
    01588                                   ( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
    01589                                     IOCTL_CDROM_GET_DRIVE_GEOMETRY :
    01590                                     IOCTL_DISK_GET_DRIVE_GEOMETRY ),
    01591                                   DeviceObjectWeTalkTo,
    01592                                   &DiskGeometry,
    01593                                   sizeof( DISK_GEOMETRY ),
    01594                                   FALSE,
    01595                                   TRUE,
    01596                                   NULL );
    01597
    01598     //
    01599     //  If this call failed, we might be able to get away with a heuristic guess as to
    01600     //  what the sector size is (per CDFS), but that is playing with fire.  Nearly every
    01601     //  failure here will be a permanent problem of some form.
    01602     //
    01603
    01604     if (!NT_SUCCESS( Status )) {
    01605
    01606         UdfCompleteRequest( IrpContext, Irp, Status );
    01607         DebugTrace(( 0, Dbg, "UdfMountVolume, GET_DRIVE_GEOMETRY failed\n" ));
    01608         DebugTrace(( -1, Dbg,
    01609                      "UdfMountVolume -> %08x\n",
    01610                      Status ));
    01611
    01612         return Status;
    01613     }
    01614
    01615     //
    01616     //  Acquire the global resource to do mount operations.
    01617     //
    01618
    01619     UdfAcquireUdfData( IrpContext );
    01620
    01621     //
    01622     //  Use a try-finally to facilitate cleanup.
    01623     //
    01624
    01625     try {
    01626
    01627         //
    01628         //  Do a quick check to see if there any Vcb's which can be removed.
    01629         //
    01630
    01631         UdfScanForDismountedVcb( IrpContext );
    01632
    01633         //
    01634         //  Make sure that the driver/drive is not screwing up underneath of us by
    01635         //  feeding us garbage for the sector size.
    01636         //
    01637
    01638         if (DiskGeometry.BytesPerSector == 0 ||
    01639             (DiskGeometry.BytesPerSector & ~( 1 << UdfHighBit( DiskGeometry.BytesPerSector ))) != 0) {
    01640
    01641             DebugTrace(( 0, 0,
    01642                          "UdfMountVolume, bad DiskGeometry (%08x) .BytesPerSector == %08x\n",
    01643                          &DiskGeometry,
    01644                          DiskGeometry.BytesPerSector ));
    01645
    01646             ASSERT( FALSE );
    01647
    01648             try_leave( Status = STATUS_DRIVER_INTERNAL_ERROR );
    01649         }
    01650
    01651         //
    01652         //  Now go confirm that this volume may be a UDF image by looking for a
    01653         //  valid ISO 13346 Volume Recognition Sequence.
    01654         //
    01655
    01656         if (!UdfRecognizeVolume( IrpContext,
    01657                                  DeviceObjectWeTalkTo,
    01658                                  DiskGeometry.BytesPerSector,
    01659                                  &BridgeMedia )) {
    01660
    01661             DebugTrace(( 0, Dbg, "UdfMountVolume, recognition failed so not mounting\n" ));
    01662
    01663             try_leave( Status = STATUS_UNRECOGNIZED_VOLUME );
    01664         }
    01665
    01666         //
    01667         //  Create the DeviceObject for this mount attempt
    01668         //
    01669
    01670         Status = IoCreateDevice( UdfData.DriverObject,
    01671                                  sizeof( VOLUME_DEVICE_OBJECT ) - sizeof( DEVICE_OBJECT ),
    01672                                  NULL,
    01673                                  FILE_DEVICE_CD_ROM_FILE_SYSTEM,
    01674                                  0,
    01675                                  FALSE,
    01676                                  (PDEVICE_OBJECT *) &VolDo );
    01677
    01678         if (!NT_SUCCESS( Status )) {
    01679
    01680             DebugTrace(( 0, Dbg, "UdfMountVolume, couldn't get voldo! (%08x)\n", Status ));
    01681             try_leave( Status );
    01682         }
    01683
    01684         //
    01685         //  Our alignment requirement is the larger of the processor alignment requirement
    01686         //  already in the volume device object and that in the DeviceObjectWeTalkTo
    01687         //
    01688
    01689         if (DeviceObjectWeTalkTo->AlignmentRequirement > VolDo->DeviceObject.AlignmentRequirement) {
    01690
    01691             VolDo->DeviceObject.AlignmentRequirement = DeviceObjectWeTalkTo->AlignmentRequirement;
    01692         }
    01693
    01694         ClearFlag( VolDo->DeviceObject.Flags, DO_DEVICE_INITIALIZING );
    01695
    01696         //
    01697         //  Initialize the overflow queue for the volume
    01698         //
    01699
    01700         VolDo->OverflowQueueCount = 0;
    01701         InitializeListHead( &VolDo->OverflowQueue );
    01702
    01703         VolDo->PostedRequestCount = 0;
    01704         KeInitializeSpinLock( &VolDo->OverflowQueueSpinLock );
    01705
    01706         //
    01707         //  Now before we can initialize the Vcb we need to set up the
    01708         //  device object field in the VPB to point to our new volume device
    01709         //  object.
    01710         //
    01711
    01712         Vpb->DeviceObject = (PDEVICE_OBJECT) VolDo;
    01713
    01714         //
    01715         //  Initialize the Vcb.  This routine will raise on an allocation
    01716         //  failure.
    01717         //
    01718
    01719         UdfInitializeVcb( IrpContext,
    01720                           &VolDo->Vcb,
    01721                           DeviceObjectWeTalkTo,
    01722                           Vpb,
    01723                           &DiskGeometry,
    01724                           MediaChangeCount );
    01725
    01726         //
    01727         //  We must initialize the stack size in our device object before
    01728         //  the following reads, because the I/O system has not done it yet.
    01729         //
    01730
    01731         ((PDEVICE_OBJECT) VolDo)->StackSize = (CCHAR) (DeviceObjectWeTalkTo->StackSize + 1);
    01732
    01733         //
    01734         //  Pick up a local pointer to the new Vcb.  Here is where we start
    01735         //  thinking about cleanup of structures if the mount is failed.
    01736         //
    01737
    01738         Vcb = &VolDo->Vcb;
    01739         Vpb = NULL;
    01740         VolDo = NULL;
    01741
    01742         //
    01743         //  Store the Vcb in the IrpContext as we didn't have one before.
    01744         //
    01745
    01746         IrpContext->Vcb = Vcb;
    01747
    01748         UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    01749
    01750         //
    01751         //  Let's reference the Vpb to make sure we are the one to
    01752         //  have the last dereference.
    01753         //
    01754
    01755         Vcb->Vpb->ReferenceCount += 1;
    01756
    01757         //
    01758         //  Clear the verify bit for the start of mount.
    01759         //
    01760
    01761         ClearFlag( Vcb->Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
    01762
    01763         //
    01764         //  Now find the multi-session bounds on this media.
    01765         //
    01766
    01767         UdfDetermineVolumeBounding( IrpContext,
    01768                                     Vcb,
    01769                                     &Vcb->BoundS,
    01770                                     &Vcb->BoundN );
    01771
    01772         //
    01773         //  Now find the Anchor Volume Descriptor so we can discover the Volume Set
    01774         //  Descriptor Sequence extent.
    01775         //
    01776
    01777         Status = UdfFindAnchorVolumeDescriptor( IrpContext,
    01778                                                 Vcb,
    01779                                                 &AnchorVolumeDescriptor );
    01780
    01781         if (!NT_SUCCESS(Status)) {
    01782
    01783             DebugTrace(( 0, Dbg, "UdfMountVolume, couldn't find anchor descriptors\n" ));
    01784             try_leave( Status );
    01785         }
    01786
    01787         //
    01788         //  Now search for the prevailing copies of the PVD, LVD, and related PD in the
    01789         //  extents indicated by the AVD.
    01790         //
    01791
    01792         Status = UdfFindVolumeDescriptors( IrpContext,
    01793                                            Vcb,
    01794                                            &AnchorVolumeDescriptor->Main,
    01795                                            &Pcb,
    01796                                            &PrimaryVolumeDescriptor,
    01797                                            &LogicalVolumeDescriptor );
    01798
    01799         //
    01800         //  If we discovered invalid structures on the main extent, we may still
    01801         //  be able to use the reserve extent.  By definition the two extents
    01802         //  must be logically equal, so just plow into it on any error.
    01803         //
    01804
    01805         if (!NT_SUCCESS( Status )) {
    01806
    01807             Status = UdfFindVolumeDescriptors( IrpContext,
    01808                                                Vcb,
    01809                                                &AnchorVolumeDescriptor->Reserve,
    01810                                                &Pcb,
    01811                                                &PrimaryVolumeDescriptor,
    01812                                                &LogicalVolumeDescriptor );
    01813         }
    01814
    01815         if (!NT_SUCCESS(Status)) {
    01816
    01817             DebugTrace(( 0, Dbg, "UdfMountVolume, couldn't find good VSD descriptors (PVD/LVD/PD)\n" ));
    01818             try_leave( Status );
    01819         }
    01820
    01821         //
    01822         //  Now go complete initialization of the Pcb.  After this point, we can perform
    01823         //  physical partition mappings and know that the partition table is good.
    01824         //
    01825
    01826         Status = UdfCompletePcb( IrpContext,
    01827                                  Vcb,
    01828                                  Pcb );
    01829
    01830         if (!NT_SUCCESS(Status)) {
    01831
    01832             DebugTrace(( 0, Dbg, "UdfMountVolume, Pcb completion failed\n" ));
    01833             try_leave( Status );
    01834         }
    01835
    01836         Vcb->Pcb = Pcb;
    01837         Pcb = NULL;
    01838
    01839         //
    01840         //  Set up all the support we need to do reads into the volume.
    01841         //
    01842
    01843         UdfUpdateVcbPhase0( IrpContext, Vcb );
    01844
    01845         //
    01846         //  Now go get the fileset descriptor that will finally reveal the location
    01847         //  of the root directory on this volume.
    01848         //
    01849
    01850         Status = UdfFindFileSetDescriptor( IrpContext,
    01851                                            Vcb,
    01852                                            &LogicalVolumeDescriptor->FSD,
    01853                                            &FileSetDescriptor );
    01854
    01855         if (!NT_SUCCESS(Status)) {
    01856
    01857             try_leave( NOTHING );
    01858         }
    01859
    01860         //
    01861         //  Now that we have everything together, update the Vpb with identification
    01862         //  of this volume.
    01863         //
    01864
    01865         UdfUpdateVolumeLabel( IrpContext,
    01866                               Vcb->Vpb->VolumeLabel,
    01867                               &Vcb->Vpb->VolumeLabelLength,
    01868                               LogicalVolumeDescriptor->VolumeID,
    01869                               sizeof( LogicalVolumeDescriptor->VolumeID ));
    01870
    01871         UdfUpdateVolumeSerialNumber( IrpContext,
    01872                                      &Vcb->Vpb->SerialNumber,
    01873                                      FileSetDescriptor );
    01874
    01875         //
    01876         //  Check if this is a remount operation.  If so then clean up
    01877         //  the data structures passed in and created here.
    01878         //
    01879
    01880         if (UdfIsRemount( IrpContext, Vcb, &OldVcb )) {
    01881
    01882             //
    01883             //  Link the old Vcb to point to the new device object that we
    01884             //  should be talking to, dereferencing the previous.
    01885             //
    01886
    01887             ObDereferenceObject( OldVcb->TargetDeviceObject );
    01888
    01889             Vcb->Vpb->RealDevice->Vpb = OldVcb->Vpb;
    01890
    01891             OldVcb->Vpb->RealDevice = Vcb->Vpb->RealDevice;
    01892
    01893             OldVcb->TargetDeviceObject = DeviceObjectWeTalkTo;
    01894             OldVcb->VcbCondition = VcbMounted;
    01895
    01896             OldVcb->MediaChangeCount = Vcb->MediaChangeCount;
    01897
    01898             //
    01899             //  Push the state of the method 2 bit across.  In changing the device,
    01900             //  we may now be on one with a different requirement.
    01901             //
    01902
    01903             ClearFlag( OldVcb->VcbState, VCB_STATE_METHOD_2_FIXUP );
    01904             SetFlag( OldVcb->VcbState, FlagOn( Vcb->VcbState, VCB_STATE_METHOD_2_FIXUP ));
    01905
    01906             //
    01907             //  See if we will need to provide notification of the remount.  This is the readonly
    01908             //  filesystem's form of dismount/mount notification - we promise that whenever a
    01909             //  volume is "dismounted", that a mount notification will occur when it is revalidated.
    01910             //  Note that we do not send mount on normal remounts - that would duplicate the media
    01911             //  arrival notification of the device driver.
    01912             //
    01913
    01914             if (FlagOn( OldVcb->VcbState, VCB_STATE_NOTIFY_REMOUNT )) {
    01915
    01916                 ClearFlag( OldVcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
    01917
    01918                 FileObjectToNotify = OldVcb->RootIndexFcb->FileObject;
    01919                 ObReferenceObject( FileObjectToNotify );
    01920             }
    01921
    01922             DebugTrace(( 0, Dbg, "UdfMountVolume, remounted old Vcb %08x\n", OldVcb ));
    01923
    01924             try_leave( Status = STATUS_SUCCESS );
    01925         }
    01926
    01927         //
    01928         //  Initialize the Vcb and associated structures from our volume descriptors
    01929         //
    01930
    01931         UdfUpdateVcbPhase1( IrpContext,
    01932                             Vcb,
    01933                             FileSetDescriptor );
    01934
    01935         //
    01936         //  Drop an extra reference on the root dir file so we'll be able to send
    01937         //  notification.
    01938         //
    01939
    01940         if (Vcb->RootIndexFcb) {
    01941
    01942             FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
    01943             ObReferenceObject( FileObjectToNotify );
    01944         }
    01945
    01946         //
    01947         //  The new mount is complete.  Remove the additional references on this
    01948         //  Vcb since, at this point, we have added the real references this volume
    01949         //  will have during its lifetime.  We also need to drop the additional
    01950         //  reference on the device we mounted.
    01951         //
    01952
    01953         Vcb->VcbReference -= Vcb->VcbResidualReference;
    01954         ASSERT( Vcb->VcbReference == Vcb->VcbResidualReference );
    01955
    01956         ObDereferenceObject( Vcb->TargetDeviceObject );
    01957
    01958         Vcb->VcbCondition = VcbMounted;
    01959
    01960         UdfReleaseVcb( IrpContext, Vcb );
    01961         Vcb = NULL;
    01962
    01963         Status = STATUS_SUCCESS;
    01964
    01965     } finally {
    01966
    01967         DebugUnwind( "UdfMountVolume" );
    01968
    01969         //
    01970         //  If we didn't complete the mount then cleanup any remaining structures.
    01971         //
    01972
    01973         if (Vpb != NULL) { Vpb->DeviceObject = NULL; }
    01974
    01975         if (Pcb != NULL) {
    01976
    01977             UdfDeletePcb( Pcb );
    01978         }
    01979
    01980         if (Vcb != NULL) {
    01981
    01982             //
    01983             //  Make sure there is no Vcb in the IrpContext since it could go away
    01984             //
    01985
    01986             IrpContext->Vcb = NULL;
    01987
    01988             Vcb->VcbReference -= Vcb->VcbResidualReference;
    01989
    01990             if (UdfDismountVcb( IrpContext, Vcb )) {
    01991
    01992                 UdfReleaseVcb( IrpContext, Vcb );
    01993             }
    01994
    01995         } else if (VolDo != NULL) {
    01996
    01997             IoDeleteDevice( (PDEVICE_OBJECT)VolDo );
    01998             Vpb->DeviceObject = NULL;
    01999         }
    02000
    02001         //
    02002         //  Release the global resource.
    02003         //
    02004
    02005         UdfReleaseUdfData( IrpContext );
    02006
    02007         //
    02008         //  Free any structures we may have been allocated
    02009         //
    02010
    02011         UdfFreePool( &AnchorVolumeDescriptor );
    02012         UdfFreePool( &PrimaryVolumeDescriptor );
    02013         UdfFreePool( &LogicalVolumeDescriptor );
    02014         UdfFreePool( &FileSetDescriptor );
    02015     }
    02016
    02017     //
    02018     //  Now send mount notification.
    02019     //
    02020
    02021     if (FileObjectToNotify) {
    02022
    02023         FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
    02024         ObDereferenceObject( FileObjectToNotify );
    02025     }
    02026
    02027     //
    02028     //  Complete the request if no exception.
    02029     //
    02030
    02031     UdfCompleteRequest( IrpContext, Irp, Status );
    02032     DebugTrace(( -1, Dbg, "UdfMountVolume -> %08x\n", Status ));
    02033
    02034     return Status;
    02035 }

NTSTATUS UdfOplockRequest | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 470 of file udfs/fsctrl.c.

References ClearFlag, FALSE, _FCB::FcbCleanup, _IO_STACK_LOCATION::FileObject, FsRtlAreThereCurrentFileLocks, FsRtlOplockFsctrl(), IoGetCurrentIrpStackLocation, Irp, IRP_CONTEXT_FLAG_FORCE_POST, IRP_CONTEXT_FLAG_WAIT, NTSTATUS(), NULL, PAGED_CODE, _IO_STACK_LOCATION::Parameters, SetFlag, Status, UdfAcquireFcbExclusive, UdfAcquireFcbShared, UdfCompleteRequest(), UdfDecodeFileObject(), UdfIsFastIoPossible, UdfLockFcb, UdfReleaseFcb, UdfUnlockFcb, UdfVerifyFcbOperation(), and UserFileOpen.

Referenced by UdfUserFsctl().

    00477                    :
    00478
    00479     This is the common routine to handle oplock requests made via the
    00480     NtFsControlFile call.
    00481
    00482 Arguments:
    00483
    00484     Irp - Supplies the Irp being processed
    00485
    00486 Return Value:
    00487
    00488     NTSTATUS - The return status for the operation
    00489
    00490 --*/
    00491
    00492 {
    00493     NTSTATUS Status;
    00494     PFCB Fcb;
    00495     PCCB Ccb;
    00496
    00497     ULONG OplockCount = 0;
    00498     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00499
    00500     PAGED_CODE();
    00501
    00502     //
    00503     //  We only permit oplock requests on files.
    00504     //
    00505
    00506     if (UdfDecodeFileObject( IrpSp->FileObject,
    00507                              &Fcb,
    00508                              &Ccb ) != UserFileOpen ) {
    00509
    00510         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00511         return STATUS_INVALID_PARAMETER;
    00512     }
    00513
    00514     //
    00515     //  Make this a waitable Irpcontext so we don't fail to acquire
    00516     //  the resources.
    00517     //
    00518
    00519     SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
    00520     ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST );
    00521
    00522     //
    00523     //  Switch on the function control code.  We grab the Fcb exclusively
    00524     //  for oplock requests, shared for oplock break acknowledgement.
    00525     //
    00526
    00527     switch (IrpSp->Parameters.FileSystemControl.FsControlCode) {
    00528
    00529     case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
    00530     case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
    00531     case FSCTL_REQUEST_BATCH_OPLOCK :
    00532     case FSCTL_REQUEST_FILTER_OPLOCK :
    00533
    00534         UdfAcquireFcbExclusive( IrpContext, Fcb, FALSE );
    00535
    00536         if (IrpSp->Parameters.FileSystemControl.FsControlCode == FSCTL_REQUEST_OPLOCK_LEVEL_2) {
    00537
    00538             if (Fcb->FileLock != NULL) {
    00539
    00540                 OplockCount = (ULONG) FsRtlAreThereCurrentFileLocks( Fcb->FileLock );
    00541             }
    00542
    00543         } else {
    00544
    00545             OplockCount = Fcb->FcbCleanup;
    00546         }
    00547
    00548         break;
    00549
    00550     case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE:
    00551     case FSCTL_OPBATCH_ACK_CLOSE_PENDING:
    00552     case FSCTL_OPLOCK_BREAK_NOTIFY:
    00553     case FSCTL_OPLOCK_BREAK_ACK_NO_2:
    00554
    00555         UdfAcquireFcbShared( IrpContext, Fcb, FALSE );
    00556         break;
    00557
    00558     default:
    00559
    00560         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00561         return STATUS_INVALID_PARAMETER;
    00562     }
    00563
    00564     //
    00565     //  Use a try finally to free the Fcb.
    00566     //
    00567
    00568     try {
    00569
    00570         //
    00571         //  Verify the Fcb.
    00572         //
    00573
    00574         UdfVerifyFcbOperation( IrpContext, Fcb );
    00575
    00576         //
    00577         //  Call the FsRtl routine to grant/acknowledge oplock.
    00578         //
    00579
    00580         Status = FsRtlOplockFsctrl( &Fcb->Oplock,
    00581                                     Irp,
    00582                                     OplockCount );
    00583
    00584         //
    00585         //  Set the flag indicating if Fast I/O is possible
    00586         //
    00587
    00588         UdfLockFcb( IrpContext, Fcb );
    00589         Fcb->IsFastIoPossible = UdfIsFastIoPossible( Fcb );
    00590         UdfUnlockFcb( IrpContext, Fcb );
    00591
    00592         //
    00593         //  The oplock package will complete the Irp.
    00594         //
    00595
    00596         Irp = NULL;
    00597
    00598     } finally {
    00599
    00600         //
    00601         //  Release all of our resources
    00602         //
    00603
    00604         UdfReleaseFcb( IrpContext, Fcb );
    00605     }
    00606
    00607     //
    00608     //  Complete the request if there was no exception.
    00609     //
    00610
    00611     UdfCompleteRequest( IrpContext, Irp, Status );
    00612     return Status;
    00613 }

BOOLEAN UdfRecognizeVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PDEVICE_OBJECT | DeviceObject,
|  | IN ULONG | SectorSize,
|  | IN OUT PBOOLEAN | Bridge
| ) |

Definition at line 3457 of file udfs/fsctrl.c.

References ASSERT_IRP_CONTEXT, Dbg, DebugTrace, DebugUnwind, FALSE, FsRtlAllocatePoolWithTag, VSD_GENERIC::Ident, NT_SUCCESS, NTSTATUS(), Offset, PAGED_CODE, PVSD_GENERIC, SectorAlignN, SectorSize, Status, TAG_NSR_VSD, TRUE, VSD_GENERIC::Type, UdfFindInParseTable(), UdfFreePool(), UdfIsRawDevice, UdfNonPagedPool, UdfRawBufferSizeN(), UdfRawReadSizeN(), UdfReadSectors(), VSD_GENERIC::Version, VRA_BOUNDARY_LOCATION, VSD_GENERIC, VSD_LENGTH_IDENT, VsdIdentBEA01, VsdIdentBOOT2, VsdIdentCD001, VsdIdentCDROM, VsdIdentCDW01, VsdIdentCDW02, VsdIdentNSR01, VsdIdentNSR02, VsdIdentParseTable, and VsdIdentTEA01.

Referenced by UdfMountVolume().

    03466                    :
    03467
    03468     This routine walks the Volume Recognition Sequence to determine
    03469     whether this volume contains an NSR02 (ISO 13346 Section 4) image.
    03470
    03471 Arguments:
    03472
    03473     DeviceObject - device we are checking
    03474
    03475     SectorSize - size of a physical sector on this device
    03476
    03477     Bridge - will return whether there appear to be ISO 9660 structures
    03478         on the media
    03479
    03480 Return Value:
    03481
    03482     Boolean TRUE if we found NSR02, FALSE otherwise.
    03483
    03484 --*/
    03485
    03486 {
    03487     NTSTATUS Status;
    03488
    03489     BOOLEAN FoundBEA = FALSE;
    03490     BOOLEAN FoundNSR = FALSE;
    03491     BOOLEAN Resolved = FALSE;
    03492
    03493     PVSD_GENERIC VolumeStructureDescriptor;
    03494     ULONGLONG Offset = SectorAlignN( SectorSize, VRA_BOUNDARY_LOCATION );
    03495
    03496     PAGED_CODE();
    03497
    03498     //
    03499     //  Check the input parameters
    03500     //
    03501
    03502     ASSERT_IRP_CONTEXT( IrpContext);
    03503
    03504     VolumeStructureDescriptor = (PVSD_GENERIC) FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    03505                                                                          UdfRawBufferSizeN( SectorSize,
    03506                                                                                             sizeof(VSD_GENERIC) ),
    03507                                                                          TAG_NSR_VSD );
    03508
    03509     DebugTrace(( +1, Dbg,
    03510                  "UdfRecognizeVolume, DevObj %08x SectorSize %08x\n",
    03511                  DeviceObject,
    03512                  SectorSize ));
    03513
    03514     //
    03515     //  Use try-finally to facilitate cleanup
    03516     //
    03517
    03518     try {
    03519
    03520 #ifdef UDF_SUPPORT_NONSTANDARD_ADAPTEC
    03521
    03522         //
    03523         //  Disable checking the recognition area.
    03524         //
    03525         //  Reasons:
    03526         //
    03527         //      ADAPTEC - early CDUDF did not bound NSR02 with BEA/TEA, instead
    03528         //              sticking it in the middle of the ISO 9660 sequence.
    03529         //
    03530
    03531         Resolved = TRUE;
    03532 #endif
    03533
    03534         while (!Resolved) {
    03535
    03536             Status = UdfReadSectors( IrpContext,
    03537                                      Offset,
    03538                                      UdfRawReadSizeN( SectorSize,
    03539                                                       sizeof(VSD_GENERIC) ),
    03540                                      FALSE,
    03541                                      VolumeStructureDescriptor,
    03542                                      DeviceObject );
    03543
    03544             if (!NT_SUCCESS( Status )) {
    03545                 break;
    03546             }
    03547
    03548             //
    03549             //  Now check the type of the descriptor. All ISO 13346 VSDs are
    03550             //  of Type 0, 9660 PVDs are Type 1, 9660 SVDs are Type 2, and 9660
    03551             //  terminating descriptors are Type 255.
    03552             //
    03553
    03554             if (VolumeStructureDescriptor->Type == 0) {
    03555
    03556                 //
    03557                 //  In order to properly recognize the volume, we must know all of the
    03558                 //  Structure identifiers in ISO 13346 so that we can terminate if a
    03559                 //  badly formatted (or, shockingly, non 13346) volume is presented to us.
    03560                 //
    03561
    03562                 switch (UdfFindInParseTable( VsdIdentParseTable,
    03563                                              VolumeStructureDescriptor->Ident,
    03564                                              VSD_LENGTH_IDENT )) {
    03565                     case VsdIdentBEA01:
    03566
    03567                         //
    03568                         //  Only one BEA may exist and its version must be 1 (2/9.2.3)
    03569                         //
    03570
    03571                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got a BEA01\n" ));
    03572
    03573
    03574                         if ((FoundBEA &&
    03575                              DebugTrace(( 0, Dbg,
    03576                                           "UdfRecognizeVolume, ... but it is a duplicate!\n" ))) ||
    03577
    03578                             (VolumeStructureDescriptor->Version != 1 &&
    03579                              DebugTrace(( 0, Dbg,
    03580                                           "UdfRecognizeVolume, ... but it has a wacky version number %02x != 1!\n",
    03581                                           VolumeStructureDescriptor->Version )))) {
    03582
    03583                             Resolved = TRUE;
    03584                             break;
    03585                         }
    03586
    03587                         FoundBEA = TRUE;
    03588                         break;
    03589
    03590                     case VsdIdentTEA01:
    03591
    03592                         //
    03593                         //  If we reach the TEA it must be the case that we don't recognize
    03594                         //
    03595
    03596                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got a TEA01\n" ));
    03597                         Resolved = TRUE;
    03598                         break;
    03599
    03600                     case VsdIdentNSR02:
    03601
    03602                         //
    03603                         //  We recognize NSR02 version 1 embedded after a BEA (3/9.1.3).  For
    03604                         //  simplicity we will not bother being a complete nitpick and check
    03605                         //  for a bounding TEA, although we will be optimistic in the case where
    03606                         //  we fail to match the version.
    03607                         //
    03608
    03609                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got an NSR02\n" ));
    03610
    03611                         if ((FoundBEA ||
    03612                              !DebugTrace(( 0, Dbg, "UdfRecognizeVolume, ... but we haven't seen a BEA01 yet!\n" ))) &&
    03613
    03614                             (VolumeStructureDescriptor->Version == 1 ||
    03615                              !DebugTrace(( 0, Dbg, "UdfRecognizeVolume, ... but it has a wacky version number %02x != 1\n",
    03616                                            VolumeStructureDescriptor->Version )))) {
    03617
    03618
    03619                             FoundNSR = Resolved = TRUE;
    03620                             break;
    03621                         }
    03622
    03623                         break;
    03624
    03625                     case VsdIdentCD001:
    03626                     case VsdIdentCDW01:
    03627                     case VsdIdentNSR01:
    03628                     case VsdIdentCDW02:
    03629                     case VsdIdentBOOT2:
    03630
    03631                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got a valid but uninteresting 13346 descriptor\n" ));
    03632
    03633                         //
    03634                         //  Valid but uninteresting (to us) descriptors
    03635                         //
    03636
    03637                         break;
    03638
    03639                     default:
    03640
    03641                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got an invalid 13346 descriptor\n" ));
    03642
    03643                         //
    03644                         //  Stumbling across something we don't know, it must be that this
    03645                         //  is not a valid 13346 image
    03646                         //
    03647
    03648                         Resolved = TRUE;
    03649                         break;
    03650
    03651                 }
    03652
    03653             } else if (!FoundBEA && (VolumeStructureDescriptor->Type < 3 ||
    03654                                      VolumeStructureDescriptor->Type == 255)) {
    03655
    03656                 DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got a 9660 descriptor\n" ));
    03657
    03658                 //
    03659                 //  Only HSG (CDROM) and 9660 (CD001) are possible, and they are only legal
    03660                 //  before the ISO 13346 BEA/TEA extent.  By design, an ISO 13346 VSD precisely
    03661                 //  overlaps a 9660 PVD/SVD in the appropriate fields.
    03662                 //
    03663                 //  Note that we aren't being strict about the structure of the 9660 descriptors
    03664                 //  since that really isn't very interesting.  We care more about the 13346.
    03665                 //
    03666                 //
    03667
    03668                 switch (UdfFindInParseTable( VsdIdentParseTable,
    03669                                              VolumeStructureDescriptor->Ident,
    03670                                              VSD_LENGTH_IDENT )) {
    03671                     case VsdIdentCDROM:
    03672                     case VsdIdentCD001:
    03673
    03674                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, ... seems we have 9660 here\n" ));
    03675
    03676                         //
    03677                         //  Note to our caller that we seem to have ISO 9660 here
    03678                         //
    03679
    03680                         *Bridge = TRUE;
    03681
    03682                         break;
    03683
    03684                     default:
    03685
    03686                         DebugTrace(( 0, Dbg, "UdfRecognizeVolume, ... but it looks wacky\n" ));
    03687
    03688                         //
    03689                         //  This probably was a false alert, but in any case there is nothing
    03690                         //  on this volume for us.
    03691                         //
    03692
    03693                         Resolved = TRUE;
    03694                         break;
    03695                 }
    03696
    03697             } else {
    03698
    03699                 //
    03700                 //  Something else must be recorded on this volume.
    03701                 //
    03702
    03703                 DebugTrace(( 0, Dbg, "UdfRecognizeVolume, got an unrecognizeable descriptor, probably not 13346/9660\n" ));
    03704                 break;
    03705             }
    03706
    03707             //
    03708             //  Align our next read with the sector following the current descriptor
    03709             //
    03710
    03711             Offset += SectorAlignN( SectorSize, sizeof(VSD_GENERIC) );
    03712         }
    03713
    03714     } finally {
    03715
    03716         DebugUnwind( "UdfRecognizeVolume" );
    03717
    03718         //
    03719         //  Free up our temporary buffer
    03720         //
    03721
    03722         UdfFreePool( &VolumeStructureDescriptor );
    03723
    03724         if (AbnormalTermination()) {
    03725
    03726             //
    03727             //  Commute a status we raised for empty devices so that other filesystems
    03728             //  can have a crack at this.
    03729             //
    03730
    03731             if (UdfIsRawDevice(IrpContext, IrpContext->ExceptionStatus)) {
    03732
    03733                 IrpContext->ExceptionStatus = STATUS_UNRECOGNIZED_VOLUME;
    03734             }
    03735         }
    03736     }
    03737
    03738     DebugTrace(( -1, Dbg, "UdfRecognizeVolume -> %u\n", FoundNSR ));
    03739
    03740     return FoundNSR;
    03741 }

VOID UdfScanForDismountedVcb | ( | IN PIRP_CONTEXT | IrpContext | ) |

Definition at line 3749 of file udfs/fsctrl.c.

References ASSERT_EXCLUSIVE_UDFDATA, ASSERT_IRP_CONTEXT, FALSE, PAGED_CODE, UdfCheckForDismount(), UdfData, _VCB::VcbCondition, VcbDismountInProgress, VcbInvalid, VcbNotMounted, _UDF_DATA::VcbQueue, _VCB::VcbReference, and _VCB::VcbResidualReference.

Referenced by UdfMountVolume().

    03755                    :
    03756
    03757     This routine walks through the list of Vcb's looking for any which may
    03758     now be deleted.  They may have been left on the list because there were
    03759     outstanding references.
    03760
    03761 Arguments:
    03762
    03763 Return Value:
    03764
    03765     None
    03766
    03767 --*/
    03768
    03769 {
    03770     PVCB Vcb;
    03771     PLIST_ENTRY Links;
    03772
    03773     PAGED_CODE();
    03774
    03775     //
    03776     //  Check input.
    03777     //
    03778
    03779     ASSERT_IRP_CONTEXT( IrpContext );
    03780
    03781     ASSERT_EXCLUSIVE_UDFDATA;
    03782
    03783     //
    03784     //  Walk through all of the Vcb's attached to the global data.
    03785     //
    03786
    03787     Links = UdfData.VcbQueue.Flink;
    03788
    03789     while (Links != &UdfData.VcbQueue) {
    03790
    03791         Vcb = CONTAINING_RECORD( Links, VCB, VcbLinks );
    03792
    03793         //
    03794         //  Move to the next link now since the current Vcb may be deleted.
    03795         //
    03796
    03797         Links = Links->Flink;
    03798
    03799         //
    03800         //  If dismount is already underway then check if this Vcb can
    03801         //  go away.
    03802         //
    03803
    03804         if ((Vcb->VcbCondition == VcbDismountInProgress) ||
    03805             (Vcb->VcbCondition == VcbInvalid) ||
    03806             ((Vcb->VcbCondition == VcbNotMounted) && (Vcb->VcbReference <= Vcb->VcbResidualReference))) {
    03807
    03808             UdfCheckForDismount( IrpContext, Vcb, FALSE );
    03809         }
    03810     }
    03811
    03812     return;
    03813 }

INLINE VOID UdfStoreFileSetDescriptorIfPrevailing | ( | IN OUT PNSR_FSD * | StoredFSD,
|  | IN OUT PNSR_FSD * | NewFSD
| ) |

Definition at line 48 of file udfs/fsctrl.c.

References NULL, and PNSR_FSD.

Referenced by UdfFindFileSetDescriptor().

    00052 {
    00053     PNSR_FSD TempFSD;
    00054
    00055     //
    00056     //  If we haven't stored a fileset descriptor or the fileset number
    00057     //  of the stored descriptor is less than the new descriptor, swap the
    00058     //  pointers around.
    00059     //
    00060
    00061     if (*StoredFSD == NULL || (*StoredFSD)->FileSet < (*NewFSD)->FileSet) {
    00062
    00063         TempFSD = *StoredFSD;
    00064         *StoredFSD = *NewFSD;
    00065         *NewFSD = TempFSD;
    00066     }
    00067 }

VOID UdfStoreVolumeDescriptorIfPrevailing | ( | IN OUT PNSR_VD_GENERIC * | StoredVD,
|  | IN OUT PNSR_VD_GENERIC | NewVD
| ) |

Definition at line 235 of file udfs/fsctrl.c.

References FsRtlAllocatePoolWithTag, NULL, TAG_NSR_VDSD, and UdfNonPagedPool.

Referenced by UdfAddToPcb(), and UdfFindVolumeDescriptors().

    00242                    :
    00243
    00244     This routine updates Volume Descriptor if the new descriptor
    00245     is more prevailing than the one currently stored.
    00246
    00247 Arguments:
    00248
    00249     StoredVD - pointer to a currently stored descriptor
    00250
    00251     NewVD - pointer to a candidate descriptor
    00252
    00253 Return Value:
    00254
    00255     None.
    00256
    00257 --*/
    00258
    00259 {
    00260     PNSR_VD_GENERIC TempVD;
    00261
    00262     //
    00263     //  If we haven't stored a volume descriptor or the sequence number
    00264     //  of the stored descriptor is less than the new descriptor, make a copy
    00265     //  of it and store it.
    00266     //
    00267
    00268     if ((NULL == *StoredVD) || ((*StoredVD)->Sequence < NewVD->Sequence)) {
    00269
    00270         if ( NULL == *StoredVD)  {
    00271
    00272             *StoredVD = (PNSR_VD_GENERIC) FsRtlAllocatePoolWithTag( UdfNonPagedPool,
    00273                                                                     sizeof(NSR_VD_GENERIC),
    00274                                                                     TAG_NSR_VDSD );
    00275         }
    00276
    00277         RtlCopyMemory( *StoredVD,  NewVD,  sizeof( NSR_VD_GENERIC));
    00278     }
    00279 }

NTSTATUS UdfUnlockVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 877 of file udfs/fsctrl.c.

References FALSE, _IO_STACK_LOCATION::FileObject, FSRTL_VOLUME_UNLOCK, FsRtlNotifyVolumeEvent(), IoGetCurrentIrpStackLocation, Irp, NT_SUCCESS, NTSTATUS(), PAGED_CODE, Status, UdfAcquireVcbExclusive, UdfCompleteRequest(), UdfDecodeFileObject(), UdfReleaseVcb, UdfUnlockVolumeInternal(), UserVolumeOpen, and _FCB::Vcb.

Referenced by UdfUserFsctl().

    00884                    :
    00885
    00886     This routine performs the unlock volume operation.  It is responsible for
    00887     either completing of enqueuing the input Irp.
    00888
    00889 Arguments:
    00890
    00891     Irp - Supplies the Irp to process
    00892
    00893 Return Value:
    00894
    00895     NTSTATUS - The return status for the operation
    00896
    00897 --*/
    00898
    00899 {
    00900     NTSTATUS Status;
    00901
    00902     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00903
    00904     PVCB Vcb;
    00905     PFCB Fcb;
    00906     PCCB Ccb;
    00907
    00908     PAGED_CODE();
    00909
    00910     //
    00911     //  Decode the file object, the only type of opens we accept are
    00912     //  user volume opens.
    00913     //
    00914
    00915     if (UdfDecodeFileObject( IrpSp->FileObject, &Fcb, &Ccb ) != UserVolumeOpen ) {
    00916
    00917         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_PARAMETER );
    00918         return STATUS_INVALID_PARAMETER;
    00919     }
    00920
    00921     //
    00922     //  Acquire exclusive access to the Vcb.
    00923     //
    00924
    00925     Vcb = Fcb->Vcb;
    00926
    00927     UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    00928
    00929     //
    00930     //  We won't check for a valid Vcb for this request.  An unlock will always
    00931     //  succeed on a locked volume.
    00932     //
    00933
    00934     Status = UdfUnlockVolumeInternal( IrpContext, Vcb, IrpSp->FileObject );
    00935
    00936     //
    00937     //  Release all of our resources
    00938     //
    00939
    00940     UdfReleaseVcb( IrpContext, Vcb );
    00941
    00942     //
    00943     //  Send notification that the volume is avaliable.
    00944     //
    00945
    00946     if (NT_SUCCESS( Status )) {
    00947
    00948         FsRtlNotifyVolumeEvent( IrpSp->FileObject, FSRTL_VOLUME_UNLOCK );
    00949     }
    00950
    00951     //
    00952     //  Complete the request if there haven't been any exceptions.
    00953     //
    00954
    00955     UdfCompleteRequest( IrpContext, Irp, Status );
    00956     return Status;
    00957 }

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

Definition at line 732 of file udfs/fsctrl.c.

References ClearFlag, FlagOn, NTSTATUS(), NULL, Status, and VCB_STATE_LOCKED.

Referenced by UdfPnpCancelRemove(), UdfPnpRemove(), and UdfUnlockVolume().

    00740                    :
    00741
    00742     This routine performs the actual unlock volume operation.
    00743
    00744     The volume must be held exclusive by the caller.
    00745
    00746 Arguments:
    00747
    00748     Vcb - The volume being locked.
    00749
    00750     FileObject - File corresponding to the handle locking the volume.  If this
    00751         is not specified, a system lock is assumed.
    00752
    00753 Return Value:
    00754
    00755     NTSTATUS - The return status for the operation
    00756
    00757     Attempting to remove a system lock that did not exist is OK.
    00758
    00759 --*/
    00760
    00761 {
    00762     NTSTATUS Status = STATUS_INVALID_PARAMETER;
    00763
    00764     if (FlagOn(Vcb->VcbState, VCB_STATE_LOCKED) && FileObject == Vcb->VolumeLockFileObject) {
    00765
    00766         ClearFlag( Vcb->VcbState, VCB_STATE_LOCKED );
    00767         Vcb->VolumeLockFileObject = NULL;
    00768         Status = STATUS_SUCCESS;
    00769     }
    00770
    00771     return Status;
    00772 }

VOID UdfUpdateVolumeLabel | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PWCHAR | VolumeLabel,
|  | IN OUT PUSHORT | VolumeLabelLength,
|  | IN PUCHAR | Dstring,
|  | IN UCHAR | FieldLength
| ) |

Definition at line 4056 of file udfs/fsctrl.c.

References ASSERT_IRP_CONTEXT, Dbg, DebugTrace, MAXIMUM_VOLUME_LABEL_LENGTH, PAGED_CODE, TRUE, UdfCheckLegalCS0Dstring(), and UdfConvertCS0DstringToUnicode().

Referenced by UdfMountVolume(), and UdfVerifyVolume().

    04066                    :
    04067
    04068     This routine will retrieve an NT volume label from a logical volume descriptor.
    04069
    04070 Arguments:
    04071
    04072     VolumeLabel - a volume label to fill in.
    04073
    04074     VolumeLabelLength - returns the length of the returned volume label.
    04075
    04076     Dstring - the dstring field containing the volume id.
    04077
    04078     FieldLength - the length of the dstring field.
    04079
    04080 Return Value:
    04081
    04082     None.
    04083
    04084 --*/
    04085
    04086 {
    04087     BOOLEAN Result;
    04088
    04089     PAGED_CODE();
    04090
    04091     //
    04092     //  Check inputs.
    04093     //
    04094
    04095     ASSERT_IRP_CONTEXT( IrpContext );
    04096
    04097     DebugTrace(( +1, Dbg,
    04098                  "UdfUpdateVolumeLabel, Label %08x, Dstring %08x FieldLength %02x\n",
    04099                  VolumeLabel,
    04100                  Dstring,
    04101                  FieldLength ));
    04102
    04103     //
    04104     //  Check that the dstring is usable as a volume identification.
    04105     //
    04106
    04107     Result = UdfCheckLegalCS0Dstring( IrpContext,
    04108                                       Dstring,
    04109                                       0,
    04110                                       FieldLength,
    04111                                       TRUE );
    04112
    04113
    04114     //
    04115     //  Update the label directly if the dstring is good.
    04116     //
    04117
    04118     if (Result) {
    04119
    04120         UNICODE_STRING TemporaryUnicodeString;
    04121
    04122         TemporaryUnicodeString.Buffer = VolumeLabel;
    04123         TemporaryUnicodeString.MaximumLength = MAXIMUM_VOLUME_LABEL_LENGTH;
    04124         TemporaryUnicodeString.Length = 0;
    04125
    04126         UdfConvertCS0DstringToUnicode( IrpContext,
    04127                                        Dstring,
    04128                                        0,
    04129                                        FieldLength,
    04130                                        &TemporaryUnicodeString );
    04131
    04132         //
    04133         //  Now retrieve the name for return to the caller.
    04134         //
    04135
    04136         RtlCopyMemory( VolumeLabel, TemporaryUnicodeString.Buffer, TemporaryUnicodeString.Length );
    04137         *VolumeLabelLength = TemporaryUnicodeString.Length;
    04138
    04139         DebugTrace(( 0, Dbg,
    04140                      "UdfUpdateVolumeLabel, Labeled as \"%wZ\"\n",
    04141                      &TemporaryUnicodeString ));
    04142
    04143     //
    04144     //  Treat as label.
    04145     //
    04146
    04147     } else {
    04148
    04149         *VolumeLabelLength = 0;
    04150
    04151         DebugTrace(( 0, Dbg,
    04152                      "UdfUpdateVolumeLabel, invalid label.\n" ));
    04153     }
    04154
    04155     DebugTrace(( -1, Dbg,
    04156                  "UdfUpdateVolumeLabel -> VOID\n" ));
    04157 }

VOID UdfUpdateVolumeSerialNumber | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN OUT PULONG | VolumeSerialNumber,
|  | IN PNSR_FSD | Fsd
| ) |

Definition at line 4165 of file udfs/fsctrl.c.

References ASSERT_IRP_CONTEXT, PAGED_CODE, SwapCopyUchar4, and UdfSerial32().

Referenced by UdfMountVolume(), and UdfVerifyVolume().

    04173                    :
    04174
    04175     This routine will compute the volume serial number for a set of descriptors.
    04176
    04177 Arguments:
    04178
    04179     VolumeSerialNumber - returns the volume serial number corresponding to these descriptors.
    04180
    04181     Fsd - the fileset descriptor to examine.
    04182
    04183 Return Value:
    04184
    04185     None.
    04186
    04187 --*/
    04188
    04189 {
    04190     ULONG VsnLe;
    04191     PAGED_CODE();
    04192
    04193     //
    04194     //  Check input.
    04195     //
    04196
    04197     ASSERT_IRP_CONTEXT( IrpContext );
    04198
    04199     //
    04200     //  The serial number is just off of the FSD. This matches Win9x.
    04201     //
    04202
    04203     VsnLe = UdfSerial32( (PCHAR) Fsd, sizeof( NSR_FSD ));
    04204     SwapCopyUchar4( VolumeSerialNumber, &VsnLe );
    04205 }

NTSTATUS UdfUserFsctl | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 363 of file udfs/fsctrl.c.

References IoGetCurrentIrpStackLocation, Irp, NTSTATUS(), PAGED_CODE, _IO_STACK_LOCATION::Parameters, Status, UdfCompleteRequest(), UdfDismountVolume(), UdfInvalidateVolumes(), UdfIsPathnameValid(), UdfIsVolumeDirty(), UdfIsVolumeMounted(), UdfLockVolume(), UdfOplockRequest(), and UdfUnlockVolume().

Referenced by UdfCommonFsControl().

    00369                    :
    00370
    00371     This is the common routine for implementing the user's requests made
    00372     through NtFsControlFile.
    00373
    00374 Arguments:
    00375
    00376     Irp - Supplies the Irp being processed
    00377
    00378 Return Value:
    00379
    00380     NTSTATUS - The return status for the operation
    00381
    00382 --*/
    00383
    00384 {
    00385     NTSTATUS Status;
    00386     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    00387
    00388     PAGED_CODE();
    00389
    00390     //
    00391     //  Case on the control code.
    00392     //
    00393
    00394     switch ( IrpSp->Parameters.FileSystemControl.FsControlCode ) {
    00395
    00396     case FSCTL_REQUEST_OPLOCK_LEVEL_1 :
    00397     case FSCTL_REQUEST_OPLOCK_LEVEL_2 :
    00398     case FSCTL_REQUEST_BATCH_OPLOCK :
    00399     case FSCTL_OPLOCK_BREAK_ACKNOWLEDGE :
    00400     case FSCTL_OPBATCH_ACK_CLOSE_PENDING :
    00401     case FSCTL_OPLOCK_BREAK_NOTIFY :
    00402     case FSCTL_OPLOCK_BREAK_ACK_NO_2 :
    00403     case FSCTL_REQUEST_FILTER_OPLOCK :
    00404
    00405         Status = UdfOplockRequest( IrpContext, Irp );
    00406         break;
    00407
    00408     case FSCTL_LOCK_VOLUME :
    00409
    00410         Status = UdfLockVolume( IrpContext, Irp );
    00411         break;
    00412
    00413     case FSCTL_UNLOCK_VOLUME :
    00414
    00415         Status = UdfUnlockVolume( IrpContext, Irp );
    00416         break;
    00417
    00418     case FSCTL_DISMOUNT_VOLUME :
    00419
    00420         Status = UdfDismountVolume( IrpContext, Irp );
    00421         break;
    00422
    00423     case FSCTL_IS_VOLUME_DIRTY :
    00424
    00425         Status = UdfIsVolumeDirty( IrpContext, Irp );
    00426         break;
    00427
    00428     case FSCTL_IS_VOLUME_MOUNTED :
    00429
    00430         Status = UdfIsVolumeMounted( IrpContext, Irp );
    00431         break;
    00432
    00433     case FSCTL_IS_PATHNAME_VALID :
    00434
    00435         Status = UdfIsPathnameValid( IrpContext, Irp );
    00436         break;
    00437
    00438     case FSCTL_INVALIDATE_VOLUMES :
    00439
    00440         Status = UdfInvalidateVolumes( IrpContext, Irp );
    00441         break;
    00442
    00443
    00444     //
    00445     //  We don't support any of the known or unknown requests.
    00446     //
    00447
    00448     case FSCTL_MARK_VOLUME_DIRTY :
    00449     case FSCTL_QUERY_RETRIEVAL_POINTERS :
    00450     case FSCTL_GET_COMPRESSION :
    00451     case FSCTL_SET_COMPRESSION :
    00452     case FSCTL_MARK_AS_SYSTEM_HIVE :
    00453     case FSCTL_QUERY_FAT_BPB :
    00454     default:
    00455
    00456         UdfCompleteRequest( IrpContext, Irp, STATUS_INVALID_DEVICE_REQUEST );
    00457         Status = STATUS_INVALID_DEVICE_REQUEST;
    00458         break;
    00459     }
    00460
    00461     return Status;
    00462 }

NTSTATUS UdfVerifyVolume | ( | IN PIRP_CONTEXT | IrpContext,
|  | IN PIRP | Irp
| ) |

Definition at line 2043 of file udfs/fsctrl.c.

References ASSERT, ASSERT_IRP_CONTEXT, ASSERT_VCB, ClearFlag, Dbg, DebugTrace, _DEVICE_OBJECT::DeviceType, DO_VERIFY_VOLUME, FALSE, FlagOn, _IO_STACK_LOCATION::Flags, _DEVICE_OBJECT::Flags, NSR_LVOL::FSD, FSRTL_VOLUME_MOUNT, FsRtlNotifyVolumeEvent(), Index, IoGetCurrentIrpStackLocation, Irp, NSR_ANCHOR::Main, MAXIMUM_VOLUME_LABEL_LENGTH, _VCB::MediaChangeCount, NT_SUCCESS, NTSTATUS(), NULL, ObDereferenceObject, ObReferenceObject, PAGED_CODE, _IO_STACK_LOCATION::Parameters, _VCB::Pcb, _VPB::RealDevice, NSR_ANCHOR::Reserve, _VCB::RootIndexFcb, _VPB::SerialNumber, SL_ALLOW_RAW_MOUNT, Status, _VCB::TargetDeviceObject, TRUE, try_leave, UdfAcquireUdfData, UdfAcquireVcbExclusive, UdfCheckForDismount(), UdfCompletePcb(), UdfCompleteRequest(), UdfDeletePcb(), UdfEquivalentPcb(), UdfFindAnchorVolumeDescriptor(), UdfFindFileSetDescriptor(), UdfFindVolumeDescriptors(), UdfFreePool(), UdfPerformDevIoCtrl(), UdfPurgeVolume(), UdfReleaseUdfData, UdfReleaseVcb, UdfUpdateVolumeLabel(), UdfUpdateVolumeSerialNumber(), USHORT, VCB_STATE_NOTIFY_REMOUNT, _VCB::VcbCleanup, _VCB::VcbCondition, VcbMounted, VcbNotMounted, _VCB::VcbState, NSR_LVOL::VolumeID, _VPB::VolumeLabel, _VPB::VolumeLabelLength, and _VCB::Vpb.

Referenced by UdfCommonFsControl().

    02050                    :
    02051
    02052     This routine performs the verify volume operation.  It is responsible for
    02053     either completing of enqueuing the input Irp.
    02054
    02055 Arguments:
    02056
    02057     Irp - Supplies the Irp to process
    02058
    02059 Return Value:
    02060
    02061     NTSTATUS - The return status for the operation
    02062
    02063 --*/
    02064
    02065 {
    02066     PIO_STACK_LOCATION IrpSp = IoGetCurrentIrpStackLocation( Irp );
    02067     PVPB Vpb = IrpSp->Parameters.VerifyVolume.Vpb;
    02068     PVCB Vcb = &((PVOLUME_DEVICE_OBJECT) IrpSp->Parameters.VerifyVolume.DeviceObject)->Vcb;
    02069
    02070     PPCB Pcb = NULL;
    02071
    02072     PNSR_ANCHOR AnchorVolumeDescriptor = NULL;
    02073     PNSR_PVD PrimaryVolumeDescriptor = NULL;
    02074     PNSR_LVOL LogicalVolumeDescriptor = NULL;
    02075     PNSR_FSD FileSetDescriptor = NULL;
    02076
    02077     ULONG MediaChangeCount = 0;
    02078     ULONG Index;
    02079
    02080     PFILE_OBJECT FileObjectToNotify = NULL;
    02081
    02082     BOOLEAN ReturnError;
    02083     BOOLEAN ReleaseVcb;
    02084
    02085     IO_STATUS_BLOCK Iosb;
    02086
    02087     WCHAR VolumeLabel[ MAXIMUM_VOLUME_LABEL_LENGTH / sizeof( WCHAR )];
    02088     USHORT VolumeLabelLength;
    02089     ULONG VolumeSerialNumber;
    02090
    02091     NTSTATUS Status;
    02092
    02093     PAGED_CODE();
    02094
    02095     //
    02096     //  Check input.
    02097     //
    02098
    02099     ASSERT_IRP_CONTEXT( IrpContext );
    02100
    02101     //
    02102     //  Check that we are talking to a Cdrom or Disk device.  This request should
    02103     //  always be waitable.
    02104     //
    02105
    02106     ASSERT( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ||
    02107             Vpb->RealDevice->DeviceType == FILE_DEVICE_DISK );
    02108
    02109     ASSERT_VCB( Vcb );
    02110
    02111     //
    02112     //  Update the real device in the IrpContext from the Vpb.  There was no available
    02113     //  file object when the IrpContext was created.
    02114     //
    02115
    02116     IrpContext->RealDevice = Vpb->RealDevice;
    02117
    02118     //
    02119     //  Acquire shared global access, the termination handler for the
    02120     //  following try statement will free the access.
    02121     //
    02122
    02123     UdfAcquireUdfData( IrpContext );
    02124     UdfAcquireVcbExclusive( IrpContext, Vcb, FALSE );
    02125     ReleaseVcb = TRUE;
    02126
    02127     DebugTrace(( +1, Dbg, "UdfVerifyVolume, Vcb %08x\n", Vcb ));
    02128
    02129     try {
    02130
    02131         //
    02132         //  Check if the real device still needs to be verified.  If it doesn't
    02133         //  then obviously someone beat us here and already did the work
    02134         //  so complete the verify irp with success.  Otherwise reenable
    02135         //  the real device and get to work.
    02136         //
    02137
    02138         if (!FlagOn( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME )) {
    02139
    02140             DebugTrace(( 0, Dbg, "UdfVerifyVolume, verify bit was cleared out ahead of us\n" ));
    02141
    02142             MediaChangeCount = Vcb->MediaChangeCount;
    02143             try_leave( Status = STATUS_SUCCESS );
    02144         }
    02145
    02146         //
    02147         //  Verify that there is a disk here.
    02148         //
    02149
    02150         Status = UdfPerformDevIoCtrl( IrpContext,
    02151                                       ( Vpb->RealDevice->DeviceType == FILE_DEVICE_CD_ROM ?
    02152                                         IOCTL_CDROM_CHECK_VERIFY :
    02153                                         IOCTL_DISK_CHECK_VERIFY ),
    02154                                       Vcb->TargetDeviceObject,
    02155                                       &MediaChangeCount,
    02156                                       sizeof(ULONG),
    02157                                       FALSE,
    02158                                       TRUE,
    02159                                       &Iosb );
    02160
    02161         if (!NT_SUCCESS( Status )) {
    02162
    02163             DebugTrace(( 0, Dbg, "UdfVerifyVolume, CHECK_VERIFY failed\n" ));
    02164
    02165             //
    02166             //  If we will allow a raw mount then return WRONG_VOLUME to
    02167             //  allow the volume to be mounted by raw.
    02168             //
    02169
    02170             if (FlagOn( IrpSp->Flags, SL_ALLOW_RAW_MOUNT )) {
    02171
    02172                 DebugTrace(( 0, Dbg, "UdfVerifyVolume, ... allowing raw mount\n" ));
    02173
    02174                 Status = STATUS_WRONG_VOLUME;
    02175             }
    02176
    02177             try_leave( Status );
    02178         }
    02179
    02180         if (Iosb.Information != sizeof(ULONG)) {
    02181
    02182             //
    02183             //  Be safe about the count in case the driver didn't fill it in
    02184             //
    02185
    02186             MediaChangeCount = 0;
    02187         }
    02188
    02189         //
    02190         //  Verify that the device actually saw a change. If the driver does not
    02191         //  support the MCC, then we must verify the volume in any case.
    02192         //
    02193
    02194         if (MediaChangeCount == 0 || Vcb->MediaChangeCount != MediaChangeCount) {
    02195
    02196             //
    02197             //  Now we need to navigate the disc to find the relavent decriptors.  This is
    02198             //  much the same as the mount process.
    02199             //
    02200
    02201             //
    02202             //  Find the AVD.
    02203             //
    02204
    02205             Status = UdfFindAnchorVolumeDescriptor( IrpContext,
    02206                                                     Vcb,
    02207                                                     &AnchorVolumeDescriptor );
    02208
    02209             if (!NT_SUCCESS(Status)) {
    02210
    02211                 DebugTrace(( 0, Dbg, "UdfVerifyVolume, No AVD visible\n" ));
    02212                 try_leave( Status = STATUS_WRONG_VOLUME );
    02213             }
    02214
    02215             //
    02216             //  Get the prevailing descriptors out of the VDS, building a fresh Pcb.
    02217             //
    02218
    02219             Status = UdfFindVolumeDescriptors( IrpContext,
    02220                                                Vcb,
    02221                                                &AnchorVolumeDescriptor->Main,
    02222                                                &Pcb,
    02223                                                &PrimaryVolumeDescriptor,
    02224                                                &LogicalVolumeDescriptor );
    02225
    02226             //
    02227             //  Try the reserve sequence in case of error.
    02228             //
    02229
    02230             if (Status == STATUS_DISK_CORRUPT_ERROR) {
    02231
    02232                 Status = UdfFindVolumeDescriptors( IrpContext,
    02233                                                    Vcb,
    02234                                                    &AnchorVolumeDescriptor->Reserve,
    02235                                                    &Pcb,
    02236                                                    &PrimaryVolumeDescriptor,
    02237                                                    &LogicalVolumeDescriptor );
    02238             }
    02239
    02240             //
    02241             //  If we're totally unable to find a VDS, give up.
    02242             //
    02243
    02244             if (!NT_SUCCESS(Status)) {
    02245
    02246                 DebugTrace(( 0, Dbg, "UdfVerifyVolume, PVD/LVD/PD pickup failed\n" ));
    02247
    02248                 try_leave( Status = STATUS_WRONG_VOLUME );
    02249             }
    02250
    02251             //
    02252             //  Now go complete initialization of the Pcb so we can compare it.
    02253             //
    02254
    02255             Status = UdfCompletePcb( IrpContext,
    02256                                      Vcb,
    02257                                      Pcb );
    02258
    02259             if (!NT_SUCCESS(Status)) {
    02260
    02261                 DebugTrace(( 0, Dbg, "UdfVerifyVolume, Pcb completion failed\n" ));
    02262
    02263                 try_leave( Status = STATUS_WRONG_VOLUME );
    02264             }
    02265
    02266             //
    02267             //  Now let's compare this new Pcb to the previous Vcb's Pcb to see if they
    02268             //  appear to be equivalent.
    02269             //
    02270
    02271             if (!UdfEquivalentPcb( IrpContext,
    02272                                    Pcb,
    02273                                    Vcb->Pcb)) {
    02274
    02275                 DebugTrace(( 0, Dbg, "UdfVerifyVolume, Pcbs are not equivalent\n" ));
    02276
    02277                 try_leave( Status = STATUS_WRONG_VOLUME );
    02278             }
    02279
    02280             //
    02281             //  At this point we know that the Vcb's Pcb is OK for mapping to find the fileset
    02282             //  descriptor, so we can drop the new one we built for comparison purposes.
    02283             //
    02284
    02285             UdfDeletePcb( Pcb );
    02286             Pcb = NULL;
    02287
    02288             //
    02289             //  Go pick up the fileset descriptor.
    02290             //
    02291
    02292             Status = UdfFindFileSetDescriptor( IrpContext,
    02293                                                Vcb,
    02294                                                &LogicalVolumeDescriptor->FSD,
    02295                                                &FileSetDescriptor );
    02296
    02297             if (!NT_SUCCESS(Status)) {
    02298
    02299                 try_leave( Status = STATUS_WRONG_VOLUME );
    02300             }
    02301
    02302             //
    02303             //  Now that everything is in place, build a volume label and serial number from these
    02304             //  descriptors and perform the final check that this Vcb is (or is not) the right one
    02305             //  for the media now in the drive.
    02306             //
    02307
    02308             UdfUpdateVolumeLabel( IrpContext,
    02309                                   VolumeLabel,
    02310                                   &VolumeLabelLength,
    02311                                   LogicalVolumeDescriptor->VolumeID,
    02312                                   sizeof( LogicalVolumeDescriptor->VolumeID ));
    02313
    02314             UdfUpdateVolumeSerialNumber( IrpContext,
    02315                                          &VolumeSerialNumber,
    02316                                          FileSetDescriptor );
    02317
    02318             if (Vcb->Vpb->SerialNumber != VolumeSerialNumber ||
    02319                 Vcb->Vpb->VolumeLabelLength != VolumeLabelLength ||
    02320                 RtlCompareMemory( Vcb->Vpb->VolumeLabel,
    02321                                   VolumeLabel,
    02322                                   VolumeLabelLength )) {
    02323
    02324                 DebugTrace(( 0, Dbg, "UdfVerifyVolume, volume label/sn mismatch\n" ));
    02325
    02326                 try_leave( Status = STATUS_WRONG_VOLUME );
    02327             }
    02328         }
    02329
    02330         //
    02331         //  The volume is OK, clear the verify bit.
    02332         //
    02333
    02334         DebugTrace(( 0, Dbg, "UdfVerifyVolume, looks like the same volume\n" ));
    02335
    02336         Vcb->VcbCondition = VcbMounted;
    02337
    02338         ClearFlag( Vpb->RealDevice->Flags, DO_VERIFY_VOLUME );
    02339
    02340         //
    02341         //  See if we will need to provide notification of the remount.  This is the readonly
    02342         //  filesystem's form of dismount/mount notification.
    02343         //
    02344
    02345         if (FlagOn( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT )) {
    02346
    02347             ClearFlag( Vcb->VcbState, VCB_STATE_NOTIFY_REMOUNT );
    02348
    02349             FileObjectToNotify = Vcb->RootIndexFcb->FileObject;
    02350             ObReferenceObject( FileObjectToNotify );
    02351         }
    02352
    02353     } finally {
    02354
    02355         //
    02356         //  If we did not raise an exception, update the current Vcb.
    02357         //
    02358
    02359         if (!AbnormalTermination()) {
    02360
    02361             //
    02362             //  Update the media change count to note that we have verified the volume
    02363             //  at this value
    02364             //
    02365
    02366             Vcb->MediaChangeCount = MediaChangeCount;
    02367
    02368             //
    02369             //  Mark the Vcb as not mounted.
    02370             //
    02371
    02372             if (Status == STATUS_WRONG_VOLUME) {
    02373
    02374                 Vcb->VcbCondition = VcbNotMounted;
    02375
    02376                 //
    02377                 //  Now, if there are no user handles to the volume, try to spark
    02378                 //  teardown by purging the volume.
    02379                 //
    02380
    02381                 if (Vcb->VcbCleanup == 0) {
    02382
    02383                     if (NT_SUCCESS( UdfPurgeVolume( IrpContext, Vcb, FALSE ))) {
    02384
    02385                         ReleaseVcb = UdfCheckForDismount( IrpContext, Vcb, FALSE );
    02386                     }
    02387                 }
    02388             }
    02389         }
    02390
    02391         DebugTrace(( -1, Dbg, "UdfVerifyVolume -> %08x\n", Status ));
    02392
    02393         if (ReleaseVcb) {
    02394
    02395             UdfReleaseVcb( IrpContext, Vcb );
    02396         }
    02397
    02398         UdfReleaseUdfData( IrpContext );
    02399
    02400         //
    02401         //  Delete the Pcb if built.
    02402         //
    02403
    02404         if (Pcb != NULL) {
    02405
    02406             UdfDeletePcb( Pcb );
    02407         }
    02408
    02409         UdfFreePool( &AnchorVolumeDescriptor );
    02410         UdfFreePool( &PrimaryVolumeDescriptor );
    02411         UdfFreePool( &LogicalVolumeDescriptor );
    02412         UdfFreePool( &FileSetDescriptor );
    02413     }
    02414
    02415     //
    02416     //  Now send mount notification.
    02417     //
    02418
    02419     if (FileObjectToNotify) {
    02420
    02421         FsRtlNotifyVolumeEvent( FileObjectToNotify, FSRTL_VOLUME_MOUNT );
    02422         ObDereferenceObject( FileObjectToNotify );
    02423     }
    02424
    02425     //
    02426     //  Complete the request if no exception.
    02427     //
    02428
    02429     UdfCompleteRequest( IrpContext, Irp, Status );
    02430     return Status;
    02431 }

## Variable Documentation

BOOLEAN UdfDisable = FALSE

| Definition at line 40 of file udfs/fsctrl.c. Referenced by UdfMountVolume().