00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
#include "UdfProcs.h"
00023
00024
00025
00026
00027
00028 #define BugCheckFileId (UDFS_BUG_CHECK_FSCTRL)
00029
00030
00031
00032
00033
00034 #define Dbg (UDFS_DEBUG_LEVEL_FSCTRL)
00035
00036
00037
00038
00039
00040 BOOLEAN
UdfDisable =
FALSE;
00041
00042
00043
00044
00045
00046
INLINE
00047
VOID
00048 UdfStoreFileSetDescriptorIfPrevailing (
00049 IN OUT
PNSR_FSD *StoredFSD,
00050 IN OUT
PNSR_FSD *NewFSD
00051 )
00052 {
00053
PNSR_FSD TempFSD;
00054
00055
00056
00057
00058
00059
00060
00061
if (*StoredFSD ==
NULL || (*StoredFSD)->FileSet < (*NewFSD)->FileSet) {
00062
00063 TempFSD = *StoredFSD;
00064 *StoredFSD = *NewFSD;
00065 *NewFSD = TempFSD;
00066 }
00067 }
00068
00069
00070
00071
00072
00073
VOID
00074
UdfDetermineVolumeBounding (
00075 IN
PIRP_CONTEXT IrpContext,
00076 IN
PVCB Vcb,
00077 IN PULONG S,
00078 IN PULONG N
00079 );
00080
00081
NTSTATUS
00082
UdfDismountVolume (
00083 IN
PIRP_CONTEXT IrpContext,
00084 IN
PIRP Irp
00085 );
00086
00087
NTSTATUS
00088
UdfFindAnchorVolumeDescriptor (
00089 IN
PIRP_CONTEXT IrpContext,
00090 IN
PVCB Vcb,
00091 IN OUT
PNSR_ANCHOR *AnchorVolumeDescriptor
00092 );
00093
00094
NTSTATUS
00095
UdfFindFileSetDescriptor (
00096 IN
PIRP_CONTEXT IrpContext,
00097 IN
PVCB Vcb,
00098 IN
PLONGAD LongAd,
00099 IN OUT
PNSR_FSD *FileSetDescriptor
00100 );
00101
00102
NTSTATUS
00103
UdfFindVolumeDescriptors (
00104 IN
PIRP_CONTEXT IrpContext,
00105 IN
PVCB Vcb,
00106 IN
PEXTENTAD Extent,
00107 IN OUT
PPCB *Pcb,
00108 IN OUT
PNSR_PVD *PrimaryVolumeDescriptor,
00109 IN OUT
PNSR_LVOL *LogicalVolumeDescriptor
00110 );
00111
00112
NTSTATUS
00113
UdfInvalidateVolumes (
00114 IN
PIRP_CONTEXT IrpContext,
00115 IN
PIRP Irp
00116 );
00117
00118
NTSTATUS
00119
UdfIsPathnameValid (
00120 IN
PIRP_CONTEXT IrpContext,
00121 IN
PIRP Irp
00122 );
00123
00124 BOOLEAN
00125
UdfIsRemount (
00126 IN
PIRP_CONTEXT IrpContext,
00127 IN
PVCB Vcb,
00128 OUT
PVCB *OldVcb
00129 );
00130
00131
UdfIsVolumeDirty (
00132 IN
PIRP_CONTEXT IrpContext,
00133 IN
PIRP Irp
00134 );
00135
00136
NTSTATUS
00137
UdfIsVolumeMounted (
00138 IN
PIRP_CONTEXT IrpContext,
00139 IN
PIRP Irp
00140 );
00141
00142
NTSTATUS
00143
UdfLockVolume (
00144 IN
PIRP_CONTEXT IrpContext,
00145 IN
PIRP Irp
00146 );
00147
00148
NTSTATUS
00149
UdfMountVolume(
00150 IN
PIRP_CONTEXT IrpContext,
00151 IN
PIRP Irp
00152 );
00153
00154
NTSTATUS
00155
UdfOplockRequest (
00156 IN
PIRP_CONTEXT IrpContext,
00157 IN
PIRP Irp
00158 );
00159
00160 BOOLEAN
00161
UdfRecognizeVolume (
00162 IN
PIRP_CONTEXT IrpContext,
00163 IN
PDEVICE_OBJECT DeviceObject,
00164 IN ULONG SectorSize,
00165 IN OUT PBOOLEAN Bridge
00166 );
00167
00168
VOID
00169
UdfScanForDismountedVcb (
00170 IN
PIRP_CONTEXT IrpContext
00171 );
00172
00173
NTSTATUS
00174
UdfUnlockVolume (
00175 IN
PIRP_CONTEXT IrpContext,
00176 IN
PIRP Irp
00177 );
00178
00179
VOID
00180
UdfUpdateVolumeLabel (
00181 IN
PIRP_CONTEXT IrpContext,
00182 IN PWCHAR VolumeLabel,
00183 IN OUT PUSHORT VolumeLabelLength,
00184 IN PUCHAR Dstring,
00185 IN UCHAR FieldLength
00186 );
00187
00188
VOID
00189
UdfUpdateVolumeSerialNumber (
00190 IN
PIRP_CONTEXT IrpContext,
00191 IN OUT PULONG VolumeSerialNumber,
00192 IN
PNSR_FSD Fsd
00193 );
00194
00195
NTSTATUS
00196
UdfUserFsctl (
00197 IN
PIRP_CONTEXT IrpContext,
00198 IN
PIRP Irp
00199 );
00200
00201
NTSTATUS
00202
UdfVerifyVolume (
00203 IN
PIRP_CONTEXT IrpContext,
00204 IN
PIRP Irp
00205 );
00206
00207
#ifdef ALLOC_PRAGMA
00208
#pragma alloc_text(PAGE, UdfCommonFsControl)
00209
#pragma alloc_text(PAGE, UdfDetermineVolumeBounding)
00210
#pragma alloc_text(PAGE, UdfDismountVolume)
00211
#pragma alloc_text(PAGE, UdfFindAnchorVolumeDescriptor)
00212
#pragma alloc_text(PAGE, UdfFindFileSetDescriptor)
00213
#pragma alloc_text(PAGE, UdfFindVolumeDescriptors)
00214
#pragma alloc_text(PAGE, UdfIsPathnameValid)
00215
#pragma alloc_text(PAGE, UdfIsRemount)
00216
#pragma alloc_text(PAGE, UdfIsVolumeDirty)
00217
#pragma alloc_text(PAGE, UdfIsVolumeMounted)
00218
#pragma alloc_text(PAGE, UdfLockVolume)
00219
#pragma alloc_text(PAGE, UdfLockVolumeInternal)
00220
#pragma alloc_text(PAGE, UdfMountVolume)
00221
#pragma alloc_text(PAGE, UdfOplockRequest)
00222
#pragma alloc_text(PAGE, UdfRecognizeVolume)
00223
#pragma alloc_text(PAGE, UdfScanForDismountedVcb)
00224
#pragma alloc_text(PAGE, UdfStoreVolumeDescriptorIfPrevailing)
00225
#pragma alloc_text(PAGE, UdfUnlockVolume)
00226
#pragma alloc_text(PAGE, UdfUnlockVolumeInternal)
00227
#pragma alloc_text(PAGE, UdfUpdateVolumeLabel)
00228
#pragma alloc_text(PAGE, UdfUpdateVolumeSerialNumber)
00229
#pragma alloc_text(PAGE, UdfUserFsctl)
00230
#pragma alloc_text(PAGE, UdfVerifyVolume)
00231
#endif
00232
00233
00234
VOID
00235 UdfStoreVolumeDescriptorIfPrevailing (
00236 IN OUT
PNSR_VD_GENERIC *StoredVD,
00237 IN OUT
PNSR_VD_GENERIC NewVD
00238 )
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 {
00260
PNSR_VD_GENERIC TempVD;
00261
00262
00263
00264
00265
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 }
00280
00281
00282
NTSTATUS
00283 UdfCommonFsControl (
00284 IN
PIRP_CONTEXT IrpContext,
00285 IN
PIRP Irp
00286 )
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 {
00306
NTSTATUS Status;
00307
PIO_STACK_LOCATION IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
00308
00309
PAGED_CODE();
00310
00311
00312
00313
00314
00315
ASSERT_IRP_CONTEXT( IrpContext );
00316
ASSERT_IRP(
Irp );
00317
00318
00319
00320
00321
00322 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
00323
00324
00325
00326
00327
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 }
00356
00357
00358
00359
00360
00361
00362
NTSTATUS
00363 UdfUserFsctl (
00364 IN
PIRP_CONTEXT IrpContext,
00365 IN
PIRP Irp
00366 )
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384 {
00385
NTSTATUS Status;
00386
PIO_STACK_LOCATION IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
00387
00388
PAGED_CODE();
00389
00390
00391
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
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 }
00463
00464
00465
00466
00467
00468
00469
NTSTATUS
00470 UdfOplockRequest (
00471 IN
PIRP_CONTEXT IrpContext,
00472 IN
PIRP Irp
00473 )
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
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
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
00516
00517
00518
00519
SetFlag( IrpContext->Flags,
IRP_CONTEXT_FLAG_WAIT );
00520
ClearFlag( IrpContext->Flags,
IRP_CONTEXT_FLAG_FORCE_POST );
00521
00522
00523
00524
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
00566
00567
00568
try {
00569
00570
00571
00572
00573
00574
UdfVerifyFcbOperation( IrpContext, Fcb );
00575
00576
00577
00578
00579
00580
Status =
FsRtlOplockFsctrl( &Fcb->Oplock,
00581
Irp,
00582 OplockCount );
00583
00584
00585
00586
00587
00588
UdfLockFcb( IrpContext, Fcb );
00589 Fcb->IsFastIoPossible =
UdfIsFastIoPossible( Fcb );
00590
UdfUnlockFcb( IrpContext, Fcb );
00591
00592
00593
00594
00595
00596
Irp =
NULL;
00597
00598 } finally {
00599
00600
00601
00602
00603
00604
UdfReleaseFcb( IrpContext, Fcb );
00605 }
00606
00607
00608
00609
00610
00611
UdfCompleteRequest( IrpContext,
Irp,
Status );
00612
return Status;
00613 }
00614
00615
00616
00617
00618
00619
00620
NTSTATUS
00621 UdfLockVolumeInternal (
00622 IN
PIRP_CONTEXT IrpContext,
00623 IN
PVCB Vcb,
00624 IN
PFILE_OBJECT FileObject OPTIONAL
00625 )
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
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
00661
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
00675
00676
00677
00678
00679
00680
00681
00682
UdfPurgeVolume( IrpContext, Vcb,
FALSE );
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
UdfReleaseVcb( IrpContext, Vcb );
00700
00701
Status =
CcWaitForCurrentLazyWriterActivity();
00702
00703
00704
00705
00706
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 }
00729
00730
00731
NTSTATUS
00732 UdfUnlockVolumeInternal (
00733 IN
PIRP_CONTEXT IrpContext,
00734 IN
PVCB Vcb,
00735 IN
PFILE_OBJECT FileObject OPTIONAL
00736 )
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755
00756
00757
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 }
00773
00774
00775
00776
00777
00778
00779
NTSTATUS
00780 UdfLockVolume (
00781 IN
PIRP_CONTEXT IrpContext,
00782 IN
PIRP Irp
00783 )
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
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
00815
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
00827
00828
00829
00830
FsRtlNotifyVolumeEvent( IrpSp->
FileObject,
FSRTL_VOLUME_LOCK );
00831
00832
00833
00834
00835
00836 Vcb = Fcb->
Vcb;
00837
UdfAcquireVcbExclusive( IrpContext, Vcb,
FALSE );
00838
00839
try {
00840
00841
00842
00843
00844
00845
UdfVerifyVcb( IrpContext, Vcb );
00846
00847
Status =
UdfLockVolumeInternal( IrpContext, Vcb, IrpSp->
FileObject );
00848
00849 } finally {
00850
00851
00852
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
00865
00866
00867
UdfCompleteRequest( IrpContext,
Irp,
Status );
00868
return Status;
00869 }
00870
00871
00872
00873
00874
00875
00876
NTSTATUS
00877 UdfUnlockVolume (
00878 IN
PIRP_CONTEXT IrpContext,
00879 IN
PIRP Irp
00880 )
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
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
00912
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
00923
00924
00925 Vcb = Fcb->
Vcb;
00926
00927
UdfAcquireVcbExclusive( IrpContext, Vcb,
FALSE );
00928
00929
00930
00931
00932
00933
00934
Status =
UdfUnlockVolumeInternal( IrpContext, Vcb, IrpSp->
FileObject );
00935
00936
00937
00938
00939
00940
UdfReleaseVcb( IrpContext, Vcb );
00941
00942
00943
00944
00945
00946
if (
NT_SUCCESS(
Status )) {
00947
00948
FsRtlNotifyVolumeEvent( IrpSp->
FileObject,
FSRTL_VOLUME_UNLOCK );
00949 }
00950
00951
00952
00953
00954
00955
UdfCompleteRequest( IrpContext,
Irp,
Status );
00956
return Status;
00957 }
00958
00959
00960
00961
00962
00963
00964
00965
NTSTATUS
00966 UdfDismountVolume (
00967 IN
PIRP_CONTEXT IrpContext,
00968 IN
PIRP Irp
00969 )
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
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
01009
01010
01011
FsRtlNotifyVolumeEvent( IrpSp->
FileObject,
FSRTL_VOLUME_DISMOUNT );
01012
01013
01014
01015
01016
01017 Vcb = Fcb->
Vcb;
01018
01019
UdfAcquireVcbExclusive( IrpContext, Vcb,
FALSE );
01020
01021
01022
01023
01024
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
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
01053
01054
01055
UdfCompleteRequest( IrpContext,
Irp,
Status );
01056
return Status;
01057 }
01058
01059
01060
01061
01062
01063
01064 UdfIsVolumeDirty (
01065 IN
PIRP_CONTEXT IrpContext,
01066 IN
PIRP Irp
01067 )
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
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
01097
01098
01099
01100 IrpSp =
IoGetCurrentIrpStackLocation(
Irp );
01101
01102
01103
01104
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
01128
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
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
01159
01160
01161
01162
01163
Irp->
IoStatus.Information =
sizeof( ULONG );
01164
01165
UdfCompleteRequest( IrpContext,
Irp, STATUS_SUCCESS );
01166
return STATUS_SUCCESS;
01167 }
01168
01169
01170
01171
01172
01173
01174
NTSTATUS
01175 UdfIsVolumeMounted (
01176 IN
PIRP_CONTEXT IrpContext,
01177 IN
PIRP Irp
01178 )
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
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
01206
01207
01208
UdfDecodeFileObject( IrpSp->
FileObject, &Fcb, &Ccb );
01209
01210
if (Fcb !=
NULL) {
01211
01212
01213
01214
01215
01216
SetFlag( IrpContext->Flags,
IRP_CONTEXT_FLAG_DISABLE_POPUPS );
01217
01218
01219
01220
01221
01222
UdfVerifyVcb( IrpContext, Fcb->
Vcb );
01223 }
01224
01225
UdfCompleteRequest( IrpContext,
Irp, STATUS_SUCCESS );
01226
01227
return STATUS_SUCCESS;
01228 }
01229
01230
01231
01232
01233
01234
01235
NTSTATUS
01236 UdfIsPathnameValid (
01237 IN
PIRP_CONTEXT IrpContext,
01238 IN
PIRP Irp
01239 )
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258 {
01259
PAGED_CODE();
01260
01261
UdfCompleteRequest( IrpContext,
Irp, STATUS_SUCCESS );
01262
return STATUS_SUCCESS;
01263 }
01264
01265
01266
01267
01268
01269
01270
NTSTATUS
01271 UdfInvalidateVolumes (
01272 IN
PIRP_CONTEXT IrpContext,
01273 IN
PIRP Irp
01274 )
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
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
01313
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
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
01350
01351
01352 DeviceToMarkBad = FileToMarkBad->
DeviceObject;
01353
01354
01355
01356
01357
01358
ObDereferenceObject( FileToMarkBad );
01359
01360
01361
01362
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
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
01384
01385
01386
IoAcquireVpbSpinLock( &SavedIrql );
01387 DeviceToMarkBad->
Vpb = NewVpb;
01388
IoReleaseVpbSpinLock( SavedIrql );
01389
01390
01391
01392
01393
01394
01395
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
01408
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 }
01437
01438
01439
01440
01441
01442
01443
NTSTATUS
01444 UdfMountVolume (
01445 IN
PIRP_CONTEXT IrpContext,
01446 IN
PIRP Irp
01447 )
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
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
01513
01514
01515
ASSERT_IRP_CONTEXT( IrpContext );
01516
ASSERT_IRP(
Irp );
01517
01518
01519
01520
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
01531
01532
01533
01534 IrpContext->RealDevice = Vpb->
RealDevice;
01535
01536
01537
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
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
01579
01580
01581
01582
01583
01584
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
01600
01601
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
01617
01618
01619
UdfAcquireUdfData( IrpContext );
01620
01621
01622
01623
01624
01625
try {
01626
01627
01628
01629
01630
01631
UdfScanForDismountedVcb( IrpContext );
01632
01633
01634
01635
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
01653
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
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
01686
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
01698
01699
01700 VolDo->OverflowQueueCount = 0;
01701 InitializeListHead( &VolDo->OverflowQueue );
01702
01703 VolDo->PostedRequestCount = 0;
01704
KeInitializeSpinLock( &VolDo->OverflowQueueSpinLock );
01705
01706
01707
01708
01709
01710
01711
01712 Vpb->
DeviceObject = (
PDEVICE_OBJECT) VolDo;
01713
01714
01715
01716
01717
01718
01719
UdfInitializeVcb( IrpContext,
01720 &VolDo->Vcb,
01721 DeviceObjectWeTalkTo,
01722 Vpb,
01723 &DiskGeometry,
01724 MediaChangeCount );
01725
01726
01727
01728
01729
01730
01731 ((
PDEVICE_OBJECT) VolDo)->StackSize = (CCHAR) (DeviceObjectWeTalkTo->
StackSize + 1);
01732
01733
01734
01735
01736
01737
01738 Vcb = &VolDo->Vcb;
01739 Vpb =
NULL;
01740 VolDo =
NULL;
01741
01742
01743
01744
01745
01746 IrpContext->Vcb = Vcb;
01747
01748
UdfAcquireVcbExclusive( IrpContext, Vcb,
FALSE );
01749
01750
01751
01752
01753
01754
01755 Vcb->
Vpb->
ReferenceCount += 1;
01756
01757
01758
01759
01760
01761
ClearFlag( Vcb->
Vpb->
RealDevice->
Flags,
DO_VERIFY_VOLUME );
01762
01763
01764
01765
01766
01767
UdfDetermineVolumeBounding( IrpContext,
01768 Vcb,
01769 &Vcb->
BoundS,
01770 &Vcb->
BoundN );
01771
01772
01773
01774
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
01789
01790
01791
01792
Status =
UdfFindVolumeDescriptors( IrpContext,
01793 Vcb,
01794 &AnchorVolumeDescriptor->
Main,
01795 &Pcb,
01796 &PrimaryVolumeDescriptor,
01797 &LogicalVolumeDescriptor );
01798
01799
01800
01801
01802
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
01823
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
01841
01842
01843
UdfUpdateVcbPhase0( IrpContext, Vcb );
01844
01845
01846
01847
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
01862
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
01877
01878
01879
01880
if (
UdfIsRemount( IrpContext, Vcb, &OldVcb )) {
01881
01882
01883
01884
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
01900
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
01908
01909
01910
01911
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
01929
01930
01931
UdfUpdateVcbPhase1( IrpContext,
01932 Vcb,
01933 FileSetDescriptor );
01934
01935
01936
01937
01938
01939
01940
if (Vcb->
RootIndexFcb) {
01941
01942 FileObjectToNotify = Vcb->
RootIndexFcb->FileObject;
01943
ObReferenceObject( FileObjectToNotify );
01944 }
01945
01946
01947
01948
01949
01950
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
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
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
02003
02004
02005
UdfReleaseUdfData( IrpContext );
02006
02007
02008
02009
02010
02011
UdfFreePool( &AnchorVolumeDescriptor );
02012
UdfFreePool( &PrimaryVolumeDescriptor );
02013
UdfFreePool( &LogicalVolumeDescriptor );
02014
UdfFreePool( &FileSetDescriptor );
02015 }
02016
02017
02018
02019
02020
02021
if (FileObjectToNotify) {
02022
02023
FsRtlNotifyVolumeEvent( FileObjectToNotify,
FSRTL_VOLUME_MOUNT );
02024
ObDereferenceObject( FileObjectToNotify );
02025 }
02026
02027
02028
02029
02030
02031
UdfCompleteRequest( IrpContext,
Irp,
Status );
02032
DebugTrace(( -1,
Dbg,
"UdfMountVolume -> %08x\n",
Status ));
02033
02034
return Status;
02035 }
02036
02037
02038
02039
02040
02041
02042
NTSTATUS
02043 UdfVerifyVolume (
02044 IN
PIRP_CONTEXT IrpContext,
02045 IN
PIRP Irp
02046 )
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
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
02097
02098
02099
ASSERT_IRP_CONTEXT( IrpContext );
02100
02101
02102
02103
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
02113
02114
02115
02116 IrpContext->RealDevice = Vpb->
RealDevice;
02117
02118
02119
02120
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
02133
02134
02135
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
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
02167
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
02184
02185
02186 MediaChangeCount = 0;
02187 }
02188
02189
02190
02191
02192
02193
02194
if (MediaChangeCount == 0 || Vcb->
MediaChangeCount != MediaChangeCount) {
02195
02196
02197
02198
02199
02200
02201
02202
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
02217
02218
02219
Status =
UdfFindVolumeDescriptors( IrpContext,
02220 Vcb,
02221 &AnchorVolumeDescriptor->
Main,
02222 &Pcb,
02223 &PrimaryVolumeDescriptor,
02224 &LogicalVolumeDescriptor );
02225
02226
02227
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
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
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
02268
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
02282
02283
02284
02285
UdfDeletePcb( Pcb );
02286 Pcb =
NULL;
02287
02288
02289
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
02304
02305
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
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
02342
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
02357
02358
02359
if (!AbnormalTermination()) {
02360
02361
02362
02363
02364
02365
02366 Vcb->
MediaChangeCount = MediaChangeCount;
02367
02368
02369
02370
02371
02372
if (
Status == STATUS_WRONG_VOLUME) {
02373
02374 Vcb->
VcbCondition =
VcbNotMounted;
02375
02376
02377
02378
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
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
02417
02418
02419
if (FileObjectToNotify) {
02420
02421
FsRtlNotifyVolumeEvent( FileObjectToNotify,
FSRTL_VOLUME_MOUNT );
02422
ObDereferenceObject( FileObjectToNotify );
02423 }
02424
02425
02426
02427
02428
02429
UdfCompleteRequest( IrpContext,
Irp,
Status );
02430
return Status;
02431 }
02432
02433
02434
02435
02436
02437
02438 BOOLEAN
02439 UdfIsRemount (
02440 IN
PIRP_CONTEXT IrpContext,
02441 IN
PVCB Vcb,
02442 OUT
PVCB *OldVcb
02443 )
02444
02445
02446
02447
02448
02449
02450
02451
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
02477
02478
02479
02480
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
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
02511
02512
02513
if (Vcb == *OldVcb) {
continue; }
02514
02515
02516
02517
02518
02519 OldVpb = (*OldVcb)->Vpb;
02520
02521
if ((OldVpb != Vpb) &&
02522 (OldVpb->
RealDevice == Vpb->
RealDevice) &&
02523 ((*OldVcb)->VcbCondition ==
VcbNotMounted)) {
02524
02525
02526
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
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 }
02551
02552
02553
02554
02555
02556
02557
NTSTATUS
02558 UdfFindFileSetDescriptor (
02559 IN
PIRP_CONTEXT IrpContext,
02560 IN
PVCB Vcb,
02561 IN
PLONGAD LongAd,
02562 IN OUT
PNSR_FSD *FileSetDescriptor
02563 )
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
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
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
02616
02617
02618
02619
#ifndef UDF_SUPPORT_NONSTANDARD_ALLSTOR
02620
02621
02622
02623
02624
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
02643
02644
02645
try {
02646
02647
try {
02648
02649
for (
02650
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
02665
02666
02667 Len -=
BlockSize( Vcb ),
02668 Lbn++,
02669
Offset +=
BlockSize( Vcb )) {
02670
02671
02672
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
02694
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
02712
02713
02714
02715
02716
02717
try_leave(
Status = STATUS_DISK_CORRUPT_ERROR );
02718 }
02719
02720
if (FSD->
Destag.
Ident ==
DESTAG_ID_NSR_TERM) {
02721
02722
02723
02724
02725
02726
break;
02727 }
02728
02729
02730
02731
02732
02733 LongAd = &FSD->
NextExtent;
02734
02735
if (LongAd->Length.Length) {
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
if (LongAd->Length.Type !=
NSRLENGTH_TYPE_RECORDED) {
02746
02747
break;
02748 }
02749
02750 Len = LongAd->
Length.
Length;
02751
02752
02753
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
02780
02781
02782
UdfFreePool( &FSD );
02783
02784 }
02785
02786 } except(
UdfExceptionFilter( IrpContext, GetExceptionInformation() )) {
02787
02788
02789
02790
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
02808
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 }
02825
02826
02827
02828
02829
02830
02831
NTSTATUS
02832 UdfFindVolumeDescriptors (
02833 IN
PIRP_CONTEXT IrpContext,
02834 IN
PVCB Vcb,
02835 IN
PEXTENTAD Extent,
02836 IN OUT
PPCB *Pcb,
02837 IN OUT
PNSR_PVD *PrimaryVolumeDescriptor,
02838 IN OUT
PNSR_LVOL *LogicalVolumeDescriptor
02839 )
02840
02841
02842
02843
02844
02845
02846
02847
02848
02849
02850
02851
02852
02853
02854
02855
02856
02857
02858
02859
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
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
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
02900
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
02919
02920
02921
try {
02922
02923
DebugTrace(( 0,
Dbg,
02924
"UdfFindVolumeDescriptors, starting pass 1, find LVD/PVD\n" ));
02925
02926
02927
02928
02929
02930
02931
02932
02933
02934
for (ThisPass = 1; ThisPass <= 2; ThisPass++) {
02935
02936
for (
02937
02938
02939
02940
Offset =
LlBytesFromSectors( Vcb, Extent->Lsn ),
02941 Len = Extent->Len;
02942
02943
02944
02945
02946
02947
02948 Len;
02949
02950
02951
02952
02953
02954
Offset += UnitSize,
02955 Len -= UnitSize ) {
02956
02957
02958
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
02977
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
02996
02997
02998
02999
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
03012
03013
03014
break;
03015 }
03016
03017
if (GenericVD->
Destag.
Ident ==
DESTAG_ID_NSR_VDP) {
03018
03019
03020
03021
03022
03023
Offset =
LlBytesFromSectors( Vcb, ((
PNSR_VDP) GenericVD)->Next.Lsn );
03024 Len = ((
PNSR_VDP) GenericVD)->Next.Len;
03025
03026
03027
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
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
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
03091
03092
03093
if (ThisPass == 1) {
03094
03095
PNSR_PVD PVD;
03096
PNSR_LVOL LVD;
03097
03098
03099
03100
03101
03102 PVD = *PrimaryVolumeDescriptor;
03103 LVD = *LogicalVolumeDescriptor;
03104
03105
03106
03107
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
03119
03120
03121
03122
03123
03124
03125
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
03142
03143
03144
03145
03146
03147
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
03161
03162
03163
03164
03165
03166
03167
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
03180
03181
03182
03183
03184
03185
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
03196
03197
03198
03199
03200
03201
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
03211
03212
03213 (LVD->
BlockSize !=
SectorSize( Vcb ) &&
03214
DebugTrace(( 0,
Dbg,
03215
"UdfFindVolumeDescriptors, LVD BlockSize %08x != SectorSize %08x\n" ))) ||
03216
03217
03218
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
03230
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
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
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
03274
03275
03276
UdfFreePool( &GenericVD );
03277 }
03278
03279
DebugTrace(( -1,
Dbg,
03280
"UdfFindVolumeDescriptors -> %08x\n",
Status ));
03281
03282
03283
03284
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 }
03300
03301
03302
03303
03304
03305
03306
NTSTATUS
03307 UdfFindAnchorVolumeDescriptor (
03308 IN
PIRP_CONTEXT IrpContext,
03309 IN
PVCB Vcb,
03310 IN OUT
PNSR_ANCHOR *AnchorVolumeDescriptor
03311 )
03312
03313
03314
03315
03316
03317
03318
03319
03320
03321
03322
03323
03324
03325
03326
03327
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
03342
03343
03344
ASSERT_IRP_CONTEXT( IrpContext);
03345
ASSERT_VCB( Vcb );
03346
03347
ASSERT(*AnchorVolumeDescriptor ==
NULL);
03348
03349
03350
03351
03352
03353
03354
03355 *AnchorVolumeDescriptor = (
PNSR_ANCHOR)
FsRtlAllocatePoolWithTag(
UdfNonPagedPool,
03356
UdfRawBufferSize( Vcb,
sizeof(
NSR_ANCHOR) ),
03357
TAG_NSR_VDSD );
03358
03359
03360
03361
03362
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
03375
03376
03377
03378
03379
03380 ReadLsn =
UdfMethod2TransformSector( Vcb,
ANCHOR_SECTOR );
03381 Lsn =
ANCHOR_SECTOR;
03382
03383 }
else if (ThisPass == 3) {
03384
03385
03386
03387
03388
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
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
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 }
03450
03451
03452
03453
03454
03455
03456 BOOLEAN
03457 UdfRecognizeVolume (
03458 IN
PIRP_CONTEXT IrpContext,
03459 IN
PDEVICE_OBJECT DeviceObject,
03460 IN ULONG SectorSize,
03461 IN OUT PBOOLEAN Bridge
03462 )
03463
03464
03465
03466
03467
03468
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
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
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
03516
03517
03518
try {
03519
03520
#ifdef UDF_SUPPORT_NONSTANDARD_ADAPTEC
03521
03522
03523
03524
03525
03526
03527
03528
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
03550
03551
03552
03553
03554
if (VolumeStructureDescriptor->
Type == 0) {
03555
03556
03557
03558
03559
03560
03561
03562
switch (
UdfFindInParseTable(
VsdIdentParseTable,
03563 VolumeStructureDescriptor->
Ident,
03564
VSD_LENGTH_IDENT )) {
03565
case VsdIdentBEA01:
03566
03567
03568
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
03594
03595
03596
DebugTrace(( 0,
Dbg,
"UdfRecognizeVolume, got a TEA01\n" ));
03597 Resolved =
TRUE;
03598
break;
03599
03600
case VsdIdentNSR02:
03601
03602
03603
03604
03605
03606
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
03635
03636
03637
break;
03638
03639
default:
03640
03641
DebugTrace(( 0,
Dbg,
"UdfRecognizeVolume, got an invalid 13346 descriptor\n" ));
03642
03643
03644
03645
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
03660
03661
03662
03663
03664
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
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
03690
03691
03692
03693 Resolved =
TRUE;
03694
break;
03695 }
03696
03697 }
else {
03698
03699
03700
03701
03702
03703
DebugTrace(( 0,
Dbg,
"UdfRecognizeVolume, got an unrecognizeable descriptor, probably not 13346/9660\n" ));
03704
break;
03705 }
03706
03707
03708
03709
03710
03711
Offset +=
SectorAlignN(
SectorSize,
sizeof(
VSD_GENERIC) );
03712 }
03713
03714 } finally {
03715
03716
DebugUnwind(
"UdfRecognizeVolume" );
03717
03718
03719
03720
03721
03722
UdfFreePool( &VolumeStructureDescriptor );
03723
03724
if (AbnormalTermination()) {
03725
03726
03727
03728
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 }
03742
03743
03744
03745
03746
03747
03748
VOID
03749 UdfScanForDismountedVcb (
03750 IN
PIRP_CONTEXT IrpContext
03751 )
03752
03753
03754
03755
03756
03757
03758
03759
03760
03761
03762
03763
03764
03765
03766
03767
03768
03769 {
03770
PVCB Vcb;
03771 PLIST_ENTRY Links;
03772
03773
PAGED_CODE();
03774
03775
03776
03777
03778
03779
ASSERT_IRP_CONTEXT( IrpContext );
03780
03781
ASSERT_EXCLUSIVE_UDFDATA;
03782
03783
03784
03785
03786
03787 Links =
UdfData.
VcbQueue.Flink;
03788
03789
while (Links != &
UdfData.
VcbQueue) {
03790
03791 Vcb = CONTAINING_RECORD( Links,
VCB, VcbLinks );
03792
03793
03794
03795
03796
03797 Links = Links->Flink;
03798
03799
03800
03801
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 }
03814
03815
03816
VOID
03817 UdfDetermineVolumeBounding (
03818 IN
PIRP_CONTEXT IrpContext,
03819 IN
PVCB Vcb,
03820 IN PULONG S,
03821 IN PULONG N
03822 )
03823
03824
03825
03826
03827
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839
03840
03841
03842
03843
03844
03845
03846
03847
03848
03849
03850
03851
03852 {
03853
NTSTATUS Status;
03854 PCDROM_TOC CdromToc;
03855 PTRACK_DATA TrackData;
03856
03857
PAGED_CODE();
03858
03859
03860
03861
03862
03863
ASSERT_IRP_CONTEXT( IrpContext );
03864
ASSERT_VCB( Vcb );
03865
03866
03867
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
03884
03885
03886 *S = *N = 0;
03887
03888
03889
03890
03891
03892
try {
03893
03894
03895
03896
03897
03898
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
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
03922
03923
03924
03925
if (!
NT_SUCCESS(
Status )) {
03926
03927
try_leave( NOTHING );
03928 }
03929
03930
03931
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
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
03956
03957
03958
03959
03960
03961
03962
03963
03964
03965
03966 *N = (TrackData->Address[3] + (TrackData->Address[2] + TrackData->Address[1] * 60) * 75) - 1;
03967
03968
03969
03970
03971
03972
03973
if (*N <= 150) {
03974
03975 *N = 0;
03976
try_leave( NOTHING );
03977 }
03978
03979 *N -= 150;
03980
03981
03982
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
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
04006
04007
04008
04009
04010
04011
04012
if (
NT_SUCCESS(
Status ) &&
04013 CdromToc->FirstTrack != CdromToc->LastTrack) {
04014
04015
04016
04017
04018
04019
04020
SwapCopyUchar4( S, &CdromToc->TrackData[0].Address );
04021
04022
04023
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 }
04049
04050
04051
04052
04053
04054
04055
VOID
04056 UdfUpdateVolumeLabel (
04057 IN
PIRP_CONTEXT IrpContext,
04058 IN PWCHAR VolumeLabel,
04059 IN OUT PUSHORT VolumeLabelLength,
04060 IN PUCHAR Dstring,
04061 IN UCHAR FieldLength
04062 )
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085
04086 {
04087 BOOLEAN Result;
04088
04089
PAGED_CODE();
04090
04091
04092
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
04105
04106
04107 Result =
UdfCheckLegalCS0Dstring( IrpContext,
04108 Dstring,
04109 0,
04110 FieldLength,
04111
TRUE );
04112
04113
04114
04115
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
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
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 }
04158
04159
04160
04161
04162
04163
04164
VOID
04165 UdfUpdateVolumeSerialNumber (
04166 IN
PIRP_CONTEXT IrpContext,
04167 IN OUT PULONG VolumeSerialNumber,
04168 IN
PNSR_FSD Fsd
04169 )
04170
04171
04172
04173
04174
04175
04176
04177
04178
04179
04180
04181
04182
04183
04184
04185
04186
04187
04188
04189 {
04190 ULONG VsnLe;
04191
PAGED_CODE();
04192
04193
04194
04195
04196
04197
ASSERT_IRP_CONTEXT( IrpContext );
04198
04199
04200
04201
04202
04203 VsnLe =
UdfSerial32( (PCHAR) Fsd,
sizeof(
NSR_FSD ));
04204
SwapCopyUchar4( VolumeSerialNumber, &VsnLe );
04205 }
04206