00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
#include "UdfProcs.h"
00024
00025
00026
00027
00028
00029 #define BugCheckFileId (UDFS_BUG_CHECK_ALLOCSUP)
00030
00031
00032
00033
00034
00035 #define Dbg (UDFS_DEBUG_LEVEL_ALLOCSUP)
00036
00037
00038
00039
00040
00041
PPCB
00042
UdfCreatePcb (
00043 IN ULONG NumberOfPartitions
00044 );
00045
00046
NTSTATUS
00047
UdfLoadSparingTables(
00048
PIRP_CONTEXT IrpContext,
00049
PVCB Vcb,
00050
PPCB Pcb,
00051 ULONG Reference
00052 );
00053
00054
00055
#ifdef ALLOC_PRAGMA
00056
#pragma alloc_text(PAGE, UdfAddToPcb)
00057
#pragma alloc_text(PAGE, UdfCompletePcb)
00058
#pragma alloc_text(PAGE, UdfCreatePcb)
00059
#pragma alloc_text(PAGE, UdfDeletePcb)
00060
#pragma alloc_text(PAGE, UdfEquivalentPcb)
00061
#pragma alloc_text(PAGE, UdfInitializePcb)
00062
#pragma alloc_text(PAGE, UdfLookupAllocation)
00063
#pragma alloc_text(PAGE, UdfLookupMetaVsnOfExtent)
00064
#pragma alloc_text(PAGE, UdfLookupPsnOfExtent)
00065
#endif
00066
00067
00068 BOOLEAN
00069 UdfLookupAllocation (
00070 IN
PIRP_CONTEXT IrpContext,
00071 IN
PFCB Fcb,
00072 IN LONGLONG FileOffset,
00073 OUT PLONGLONG DiskOffset,
00074 OUT PULONG ByteCount
00075 )
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 {
00105
PVCB Vcb;
00106
00107 BOOLEAN Recorded =
TRUE;
00108
00109 BOOLEAN Result;
00110
00111 LARGE_INTEGER LocalPsn;
00112 LARGE_INTEGER LocalSectorCount;
00113
00114
PAGED_CODE();
00115
00116
00117
00118
00119
00120
ASSERT_IRP_CONTEXT( IrpContext );
00121
ASSERT_FCB( Fcb );
00122
00123
00124
00125
00126
00127
ASSERT( !
FlagOn( Fcb->FcbState,
FCB_STATE_EMBEDDED_DATA ));
00128
00129 Vcb = Fcb->Vcb;
00130
00131 LocalPsn.QuadPart = LocalSectorCount.QuadPart = 0;
00132
00133
00134
00135
00136
00137
if (
FlagOn( Fcb->FcbState,
FCB_STATE_VMCB_MAPPING )) {
00138
00139
00140
00141
00142
00143
ASSERT(
SectorOffset( Vcb, FileOffset ) == 0 );
00144
00145 Result =
UdfVmcbVbnToLbn( &Vcb->
Vmcb,
00146
SectorsFromBytes( Vcb, FileOffset ),
00147 &LocalPsn.LowPart,
00148 &LocalSectorCount.LowPart );
00149
00150
ASSERT( Result );
00151
00152 }
else {
00153
00154
00155
00156
00157
00158
ASSERT(
FlagOn( Fcb->FcbState,
FCB_STATE_MCB_INITIALIZED ));
00159
00160 Result =
FsRtlLookupLargeMcbEntry( &Fcb->Mcb,
00161
LlSectorsFromBytes( Vcb, FileOffset ),
00162 &LocalPsn.QuadPart,
00163 &LocalSectorCount.QuadPart,
00164
NULL,
00165
NULL,
00166
NULL );
00167 }
00168
00169
00170
00171
00172
00173
if (Result) {
00174
00175
if ( LocalPsn.QuadPart == -1 ) {
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185 *DiskOffset = 0;
00186
00187 Recorded =
FALSE;
00188
00189 }
else {
00190
00191
00192
00193
00194
00195
00196
ASSERT( LocalPsn.HighPart == 0 );
00197
00198
if (Vcb->
Pcb->
SparingMcb) {
00199
00200 LONGLONG SparingPsn;
00201 LONGLONG SparingSectorCount;
00202
00203
if (
FsRtlLookupLargeMcbEntry( Vcb->
Pcb->
SparingMcb,
00204 LocalPsn.LowPart,
00205 &SparingPsn,
00206 &SparingSectorCount,
00207
NULL,
00208
NULL,
00209
NULL )) {
00210
00211
00212
00213
00214
00215
00216
if (SparingPsn != -1 ||
00217 SparingSectorCount < LocalSectorCount.QuadPart) {
00218
00219
DebugTrace(( 0,
Dbg,
"UdfLookupAllocation, spared [%x, +%x) onto [%x, +%x)\n",
00220 LocalPsn.LowPart,
00221 LocalSectorCount.LowPart,
00222 (ULONG) SparingPsn,
00223 (ULONG) SparingSectorCount ));
00224 }
00225
00226
00227
00228
00229
00230
if (SparingPsn != -1) {
00231
00232 LocalPsn.QuadPart = SparingPsn;
00233 }
00234
00235
00236
00237
00238
00239
00240
00241
00242
if (SparingSectorCount < LocalSectorCount.QuadPart) {
00243
00244 LocalSectorCount.QuadPart = SparingSectorCount;
00245 }
00246 }
00247 }
00248
00249 *DiskOffset =
LlBytesFromSectors( Vcb, LocalPsn.QuadPart ) +
SectorOffset( Vcb, FileOffset );
00250
00251
00252
00253
00254
00255
if (
FlagOn( Vcb->
VcbState,
VCB_STATE_METHOD_2_FIXUP )) {
00256
00257 LARGE_INTEGER SectorsToRunout;
00258
00259 SectorsToRunout.QuadPart=
UdfMethod2NextRunoutInSectors( Vcb, *DiskOffset );
00260
00261
if (SectorsToRunout.QuadPart < LocalSectorCount.QuadPart) {
00262
00263 LocalSectorCount.QuadPart = SectorsToRunout.QuadPart;
00264 }
00265
00266 *DiskOffset =
UdfMethod2TransformByteOffset( Vcb, *DiskOffset );
00267 }
00268 }
00269
00270 }
else {
00271
00272
00273
00274
00275
00276
00277
00278
ASSERT( FileOffset < Fcb->FileSize.QuadPart );
00279
00280 *DiskOffset = 0;
00281
00282 LocalSectorCount.QuadPart =
LlSectorsFromBytes( Vcb, Fcb->FileSize.QuadPart ) -
00283
LlSectorsFromBytes( Vcb, FileOffset ) +
00284 1;
00285
00286 Recorded =
FALSE;
00287 }
00288
00289
00290
00291
00292
00293
if (LocalSectorCount.QuadPart >
SectorsFromBytes( Vcb, MAXULONG )) {
00294
00295 *ByteCount = MAXULONG;
00296
00297 }
else {
00298
00299 *ByteCount =
BytesFromSectors( Vcb, LocalSectorCount.LowPart );
00300 }
00301
00302 *ByteCount -=
SectorOffset( Vcb, FileOffset );
00303
00304
return Recorded;
00305 }
00306
00307
00308
VOID
00309 UdfDeletePcb (
00310 IN
PPCB Pcb
00311 )
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329 {
00330
PPARTITION Partition;
00331
00332
if (Pcb->SparingMcb) {
00333
00334
FsRtlUninitializeLargeMcb( Pcb->SparingMcb );
00335
UdfFreePool( &Pcb->SparingMcb );
00336 }
00337
00338
for (Partition = Pcb->Partition;
00339 Partition < &Pcb->Partition[Pcb->Partitions];
00340 Partition++) {
00341
00342
switch (Partition->Type) {
00343
00344
case Physical:
00345
00346
UdfFreePool( &Partition->Physical.PartitionDescriptor );
00347
UdfFreePool( &Partition->Physical.SparingMap );
00348
00349
break;
00350
00351
case Virtual:
00352
case Uninitialized:
00353
break;
00354
00355
default:
00356
00357
ASSERT(
FALSE );
00358
break;
00359 }
00360 }
00361
00362
ExFreePool( Pcb );
00363 }
00364
00365
00366
NTSTATUS
00367 UdfInitializePcb (
00368 IN
PIRP_CONTEXT IrpContext,
00369 IN
PVCB Vcb,
00370 IN OUT
PPCB *Pcb,
00371 IN
PNSR_LVOL LVD
00372 )
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400 {
00401
PPARTMAP_UDF_GENERIC Map;
00402
PPARTITION Partition;
00403
00404 BOOLEAN Found;
00405
00406
PAGED_CODE();
00407
00408
00409
00410
00411
00412
ASSERT_OPTIONAL_PCB( *Pcb );
00413
00414
DebugTrace(( +1,
Dbg,
00415
"UdfInitializePcb, Lvd %08x\n",
00416 LVD ));
00417
00418
00419
00420
00421
00422
00423
if (*Pcb !=
NULL) {
00424
00425
UdfDeletePcb( *Pcb );
00426 *Pcb =
NULL;
00427 }
00428
00429 *Pcb =
UdfCreatePcb( LVD->MapTableCount );
00430
00431
00432
00433
00434
00435
00436
for (Map = (
PPARTMAP_UDF_GENERIC) LVD->MapTable,
00437 Partition = (*Pcb)->Partition;
00438
00439 Partition < &(*Pcb)->Partition[(*Pcb)->Partitions];
00440
00441 Map =
Add2Ptr( Map, Map->
Length,
PPARTMAP_UDF_GENERIC ),
00442 Partition++) {
00443
00444
00445
00446
00447
00448
00449
00450
if (
Add2Ptr( Map,
sizeof(
PARTMAP_GENERIC ), PCHAR ) >
Add2Ptr( LVD,
ISONsrLvolSize( LVD ), PCHAR ) ||
00451
Add2Ptr( Map, Map->
Length, PCHAR ) >
Add2Ptr( LVD,
ISONsrLvolSize( LVD ), PCHAR )) {
00452
00453
DebugTrace(( 0,
Dbg,
00454
"UdfInitializePcb, map at +%04x beyond Lvd size %04x\n",
00455 (PCHAR) Map - (PCHAR) LVD,
00456
ISONsrLvolSize( LVD )));
00457
00458
DebugTrace(( -1,
Dbg,
00459
"UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
00460
00461
return STATUS_DISK_CORRUPT_ERROR;
00462 }
00463
00464
00465
00466
00467
00468
switch (Map->
Type) {
00469
00470
case PARTMAP_TYPE_PHYSICAL:
00471
00472 {
00473
PPARTMAP_PHYSICAL MapPhysical = (
PPARTMAP_PHYSICAL) Map;
00474
00475
00476
00477
00478
00479
DebugTrace(( 0,
Dbg,
00480
"UdfInitializePcb, map reference %02x is Physical (Partition # %08x)\n",
00481 (Partition - (*Pcb)->Partition)/
sizeof(
PARTITION),
00482 MapPhysical->
Partition ));
00483
00484
00485
00486
00487
00488
00489
00490
if (MapPhysical->
VolSetSeq > 1) {
00491
00492
DebugTrace(( 0,
Dbg,
00493
"UdfInitializePcb, ... but physical partition resides on volume set volume # %08x (> 1)!\n",
00494 MapPhysical->
VolSetSeq ));
00495
00496
DebugTrace(( -1,
Dbg,
00497
"UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
00498
00499
return STATUS_DISK_CORRUPT_ERROR;
00500 }
00501
00502
SetFlag( (*Pcb)->Flags,
PCB_FLAG_PHYSICAL_PARTITION );
00503 Partition->Type =
Physical;
00504 Partition->Physical.
PartitionNumber = MapPhysical->
Partition;
00505 }
00506
00507
break;
00508
00509
case PARTMAP_TYPE_PROXY:
00510
00511
00512
00513
00514
00515
DebugTrace(( 0,
Dbg,
00516
"UdfInitializePcb, map reference %02x is a proxy\n",
00517 (Partition - (*Pcb)->Partition)/
sizeof(
PARTITION)));
00518
00519
00520
00521
00522
00523
if (
UdfDomainIdentifierContained( &Map->
PartID,
00524 &
UdfVirtualPartitionDomainIdentifier,
00525
UDF_VERSION_150,
00526
UDF_VERSION_RECOGNIZED )) {
00527
00528 {
00529
PPARTMAP_VIRTUAL MapVirtual = (
PPARTMAP_VIRTUAL) Map;
00530
00531
00532
00533
00534
00535
if (
FlagOn( (*Pcb)->Flags,
PCB_FLAG_VIRTUAL_PARTITION )) {
00536
00537
DebugTrace(( 0,
Dbg,
00538
"UdfInitializePcb, ... but this is a second virtual partition!?!!\n" ));
00539
00540
DebugTrace(( -1,
Dbg,
00541
"UdfInitializePcb -> STATUS_UNCRECOGNIZED_VOLUME\n" ));
00542
00543
return STATUS_UNRECOGNIZED_VOLUME;
00544 }
00545
00546
DebugTrace(( 0,
Dbg,
00547
"UdfInitializePcb, ... Virtual (Partition # %08x)\n",
00548 MapVirtual->
Partition ));
00549
00550
SetFlag( (*Pcb)->Flags,
PCB_FLAG_VIRTUAL_PARTITION );
00551 Partition->Type =
Virtual;
00552
00553
00554
00555
00556
00557
00558 Partition->Virtual.RelatedReference = MapVirtual->
Partition;
00559 }
00560
00561 }
else if (
UdfDomainIdentifierContained( &Map->
PartID,
00562 &
UdfSparablePartitionDomainIdentifier,
00563
UDF_VERSION_150,
00564
UDF_VERSION_RECOGNIZED )) {
00565
00566 {
00567
NTSTATUS Status;
00568
PPARTMAP_SPARABLE MapSparable = (
PPARTMAP_SPARABLE) Map;
00569
00570
00571
00572
00573
00574
00575
00576
if (MapSparable->
VolSetSeq > 1) {
00577
00578
DebugTrace(( 0,
Dbg,
00579
"UdfInitializePcb, ... but sparable partition resides on volume set volume # %08x (> 1)!\n",
00580 MapSparable->
VolSetSeq ));
00581
00582
DebugTrace(( -1,
Dbg,
00583
"UdfInitializePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
00584
00585
return STATUS_DISK_CORRUPT_ERROR;
00586 }
00587
00588
DebugTrace(( 0,
Dbg,
00589
"UdfInitializePcb, ... Sparable (Partition # %08x)\n",
00590 MapSparable->
Partition ));
00591
00592
00593
00594
00595
00596
00597
00598
00599
SetFlag( (*Pcb)->Flags,
PCB_FLAG_SPARABLE_PARTITION );
00600 Partition->Type =
Physical;
00601 Partition->Physical.
PartitionNumber = MapSparable->
Partition;
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620 Partition->Physical.SparingMap =
FsRtlAllocatePoolWithTag(
PagedPool,
00621
sizeof(
PARTMAP_SPARABLE),
00622
TAG_NSR_FSD);
00623 RtlCopyMemory( Partition->Physical.SparingMap,
00624 MapSparable,
00625
sizeof(
PARTMAP_SPARABLE));
00626 }
00627
00628 }
else {
00629
00630
DebugTrace(( 0,
Dbg,
00631
"UdfInitializePcb, ... but we don't recognize this proxy!\n" ));
00632
00633
DebugTrace(( -1,
Dbg,
00634
"UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
00635
00636
return STATUS_UNRECOGNIZED_VOLUME;
00637 }
00638
00639
break;
00640
00641
default:
00642
00643
DebugTrace(( 0,
Dbg,
00644
"UdfInitializePcb, map reference %02x is of unknown type %02x\n",
00645 Map->
Type ));
00646
00647
DebugTrace(( -1,
Dbg,
00648
"UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
00649
00650
return STATUS_UNRECOGNIZED_VOLUME;
00651
break;
00652 }
00653 }
00654
00655
if (!
FlagOn( (*Pcb)->Flags,
PCB_FLAG_PHYSICAL_PARTITION |
PCB_FLAG_SPARABLE_PARTITION )) {
00656
00657
DebugTrace(( 0,
Dbg,
00658
"UdfInitializePcb, no physical partition seen on this logical volume!\n" ));
00659
00660
DebugTrace(( -1,
Dbg,
00661
"UdfInitializePcb -> STATUS_UNRECOGNIZED_VOLUME\n" ));
00662
00663
return STATUS_UNRECOGNIZED_VOLUME;
00664 }
00665
00666
if (
FlagOn( (*Pcb)->Flags,
PCB_FLAG_VIRTUAL_PARTITION )) {
00667
00668
PPARTITION Host;
00669
00670
00671
00672
00673
00674
00675
00676
for (Partition = (*Pcb)->Partition;
00677 Partition < &(*Pcb)->Partition[(*Pcb)->Partitions];
00678 Partition++) {
00679
00680
if (Partition->Type ==
Virtual) {
00681
00682
00683
00684
00685
00686 Found =
FALSE;
00687
00688
for (Host = (*Pcb)->Partition;
00689 Host < &(*Pcb)->Partition[(*Pcb)->Partitions];
00690 Host++) {
00691
00692
if (Host->Type ==
Physical &&
00693 Host->Physical.
PartitionNumber ==
00694 Partition->Virtual.RelatedReference) {
00695
00696 Partition->Virtual.RelatedReference =
00697 (
USHORT)(Host - (*Pcb)->Partition)/
sizeof(
PARTITION);
00698 Found =
TRUE;
00699
break;
00700 }
00701 }
00702
00703
00704
00705
00706
00707
00708
if (!Found) {
00709
00710
return STATUS_DISK_CORRUPT_ERROR;
00711 }
00712 }
00713 }
00714 }
00715
00716
DebugTrace(( -1,
Dbg,
00717
"UdfInitializePcb -> STATUS_SUCCESS\n" ));
00718
00719
return STATUS_SUCCESS;
00720 }
00721
00722
00723
VOID
00724 UdfAddToPcb (
00725 IN
PPCB Pcb,
00726 IN
PNSR_PART PartitionDescriptor
00727 )
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745
00746
00747
00748
00749
00750 {
00751
USHORT Reference;
00752
00753
PAGED_CODE();
00754
00755
00756
00757
00758
00759
ASSERT_PCB( Pcb );
00760
ASSERT( PartitionDescriptor );
00761
00762
for (Reference = 0;
00763 Reference < Pcb->Partitions;
00764 Reference++) {
00765
00766
DebugTrace(( 0,
Dbg,
"UdfAddToPcb, considering partition reference %d (type %d)\n", (ULONG)Reference, Pcb->Partition[Reference].Type));
00767
00768
switch (Pcb->Partition[Reference].Type) {
00769
00770
case Physical:
00771
00772
00773
00774
00775
00776
00777
if (Pcb->Partition[Reference].Physical.PartitionNumber == PartitionDescriptor->Number) {
00778
00779
00780
00781
00782
00783
00784
00785
UdfStoreVolumeDescriptorIfPrevailing( (
PNSR_VD_GENERIC *) &Pcb->Partition[Reference].Physical.PartitionDescriptor,
00786 (
PNSR_VD_GENERIC) PartitionDescriptor );
00787 }
00788
00789
break;
00790
00791
case Virtual:
00792
break;
00793
00794
default:
00795
00796
ASSERT(
FALSE);
00797
break;
00798 }
00799 }
00800 }
00801
00802
00803
NTSTATUS
00804 UdfCompletePcb (
00805 IN
PIRP_CONTEXT IrpContext,
00806 IN
PVCB Vcb,
00807 IN
PPCB Pcb
00808 )
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830 {
00831 ULONG Reference;
00832
00833
NTSTATUS Status;
00834
00835
PAGED_CODE();
00836
00837
00838
00839
00840
00841
ASSERT_IRP_CONTEXT( IrpContext );
00842
ASSERT_VCB( Vcb );
00843
ASSERT_PCB( Pcb );
00844
00845
DebugTrace(( +1,
Dbg,
"UdfCompletePcb, Vcb %08x Pcb %08x\n", Vcb, Pcb ));
00846
00847
00848
00849
00850
00851
for (Reference = 0;
00852 Reference < Pcb->Partitions;
00853 Reference++) {
00854
00855
DebugTrace(( 0,
Dbg,
"UdfCompletePcb, Examining Ref %u (type %u)!\n", Reference, Pcb->Partition[Reference].Type));
00856
00857
switch (Pcb->Partition[Reference].Type) {
00858
00859
case Physical:
00860
00861
if (Pcb->Partition[Reference].Physical.PartitionDescriptor ==
NULL) {
00862
00863
DebugTrace(( 0,
Dbg,
00864
"UdfCompletePcb, ... but didn't find Partition# %u!\n",
00865 Pcb->Partition[Reference].Physical.PartitionNumber ));
00866
00867
DebugTrace(( -1,
Dbg,
"UdfCompletePcb -> STATUS_DISK_CORRUPT_ERROR\n" ));
00868
00869
return STATUS_DISK_CORRUPT_ERROR;
00870 }
00871
00872 Pcb->Partition[Reference].Physical.Start =
00873 Pcb->Partition[Reference].Physical.PartitionDescriptor->Start;
00874 Pcb->Partition[Reference].Physical.Length =
00875 Pcb->Partition[Reference].Physical.PartitionDescriptor->Length;
00876
00877
00878
00879
00880
00881
00882
00883
if (Pcb->Partition[Reference].Physical.SparingMap) {
00884
00885
Status =
UdfLoadSparingTables( IrpContext,
00886 Vcb,
00887 Pcb,
00888 Reference );
00889
00890
if (!
NT_SUCCESS(
Status )) {
00891
00892
DebugTrace(( -1,
Dbg,
00893
"UdfCompletePcb -> %08x\n",
Status ));
00894
return Status;
00895 }
00896 }
00897
00898
00899
00900
00901
00902
UdfFreePool( &Pcb->Partition[Reference].Physical.PartitionDescriptor );
00903
UdfFreePool( &Pcb->Partition[Reference].Physical.SparingMap );
00904
break;
00905
00906
case Virtual:
00907
break;
00908
00909
default:
00910
00911
ASSERT(
FALSE);
00912
break;
00913 }
00914 }
00915
00916
DebugTrace(( -1,
Dbg,
"UdfCompletePcb -> STATUS_SUCCESS\n" ));
00917
00918
return STATUS_SUCCESS;
00919 }
00920
00921
00922 BOOLEAN
00923 UdfEquivalentPcb (
00924 IN
PIRP_CONTEXT IrpContext,
00925 IN
PPCB Pcb1,
00926 IN
PPCB Pcb2
00927 )
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947 {
00948 ULONG
Index;
00949
00950
PAGED_CODE();
00951
00952
00953
00954
00955
00956
ASSERT_IRP_CONTEXT( IrpContext );
00957
00958
if (Pcb1->Partitions != Pcb2->Partitions) {
00959
00960
return FALSE;
00961 }
00962
00963
for (
Index = 0;
00964
Index < Pcb1->Partitions;
00965
Index++) {
00966
00967
00968
00969
00970
00971
if (Pcb1->Partition[
Index].Type != Pcb2->Partition[
Index].Type) {
00972
00973
return FALSE;
00974 }
00975
00976
00977
00978
00979
00980
switch (Pcb1->Partition[
Index].Type) {
00981
00982
case Physical:
00983
00984
if (Pcb1->Partition[
Index].Physical.PartitionNumber != Pcb2->Partition[
Index].Physical.PartitionNumber ||
00985 Pcb1->Partition[
Index].Physical.Length != Pcb2->Partition[
Index].Physical.Length ||
00986 Pcb1->Partition[
Index].Physical.Start != Pcb2->Partition[
Index].Physical.Start) {
00987
00988
return FALSE;
00989 }
00990
break;
00991
00992
case Virtual:
00993
00994
if (Pcb1->Partition[
Index].Virtual.RelatedReference != Pcb2->Partition[
Index].Virtual.RelatedReference) {
00995
00996
return FALSE;
00997 }
00998
break;
00999
01000
default:
01001
01002
ASSERT(
FALSE);
01003
return FALSE;
01004
break;
01005 }
01006 }
01007
01008
01009
01010
01011
01012
return TRUE;
01013 }
01014
01015
01016 ULONG
01017 UdfLookupPsnOfExtent (
01018 IN
PIRP_CONTEXT IrpContext,
01019 IN
PVCB Vcb,
01020 IN USHORT Reference,
01021 IN ULONG Lbn,
01022 IN ULONG Len
01023 )
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048
01049
01050 {
01051
PPCB Pcb = Vcb->Pcb;
01052 ULONG Psn;
01053
01054
PBCB Bcb;
01055 LARGE_INTEGER
Offset;
01056 PULONG MappedLbn;
01057
01058
PAGED_CODE();
01059
01060
01061
01062
01063
01064
ASSERT_IRP_CONTEXT( IrpContext );
01065
ASSERT_VCB( Vcb );
01066
ASSERT_PCB( Pcb );
01067
01068
DebugTrace(( +1,
Dbg,
"UdfLookupPsnOfExtent, [%04x/%08x, +%08x)\n", Reference, Lbn, Len ));
01069
01070
if (Reference < Pcb->
Partitions) {
01071
01072
while (
TRUE) {
01073
01074
switch (Pcb->
Partition[Reference].Type) {
01075
01076
case Physical:
01077
01078
01079
01080
01081
01082
01083
if (
SectorsFromBlocks( Vcb, Lbn ) +
SectorsFromBytes( Vcb, Len ) >
01084 Pcb->
Partition[Reference].Physical.
Length) {
01085
01086
goto NoGood;
01087 }
01088
01089 Psn = Pcb->
Partition[Reference].Physical.Start +
SectorsFromBlocks( Vcb, Lbn );
01090
01091
DebugTrace(( -1,
Dbg,
"UdfLookupPsnOfExtent -> %08x\n", Psn ));
01092
return Psn;
01093
01094
case Virtual:
01095
01096
01097
01098
01099
01100
01101
if (Lbn +
BlocksFromBytes( Vcb, Len ) > Pcb->
Partition[Reference].Virtual.
Length ||
01102 Len >
BlockSize( Vcb )) {
01103
01104
goto NoGood;
01105 }
01106
01107
try {
01108
01109
01110
01111
01112
01113
01114
Offset.QuadPart = Lbn *
sizeof(ULONG);
01115
01116
CcMapData( Vcb->VatFcb->FileObject,
01117 &
Offset,
01118
sizeof(ULONG),
01119
TRUE,
01120 &Bcb,
01121 &MappedLbn );
01122
01123
01124
01125
01126
01127
01128
DebugTrace(( 0,
Dbg,
01129
"UdfLookupPsnOfExtent, Mapping V %04x/%08x -> L %04x/%08x\n",
01130 Reference,
01131 Lbn,
01132 Pcb->
Partition[Reference].Virtual.RelatedReference,
01133 *MappedLbn ));
01134
01135 Lbn = *MappedLbn;
01136 Reference = Pcb->
Partition[Reference].Virtual.RelatedReference;
01137
01138 } finally {
01139
01140
DebugUnwind(
UdfLookupPsnOfExtent );
01141
01142
UdfUnpinData( IrpContext, &Bcb );
01143 }
01144
01145
01146
01147
01148
01149
01150
if (Lbn == ~0) {
01151
01152
goto NoGood;
01153 }
01154
01155
break;
01156
01157
default:
01158
01159
ASSERT(
FALSE);
01160
break;
01161 }
01162 }
01163 }
01164
01165 NoGood:
01166
01167
01168
01169
01170
01171
01172
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
01173 }
01174
01175
01176 ULONG
01177 UdfLookupMetaVsnOfExtent (
01178 IN
PIRP_CONTEXT IrpContext,
01179 IN
PVCB Vcb,
01180 IN USHORT Reference,
01181 IN ULONG Lbn,
01182 IN ULONG Len,
01183 IN BOOLEAN ExactEnd
01184 )
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214 {
01215 ULONG Vsn;
01216 ULONG Psn;
01217 ULONG SectorCount;
01218
01219 BOOLEAN Result;
01220
01221 BOOLEAN UnwindExtension =
FALSE;
01222 LONGLONG UnwindAllocationSize;
01223
01224
PFCB Fcb =
NULL;
01225
01226
01227
01228
01229
01230
ASSERT_IRP_CONTEXT( IrpContext );
01231
ASSERT_VCB( Vcb );
01232
01233
01234
01235
01236
01237
if (Len == 0 ||
BlockOffset( Vcb, Len )) {
01238
01239
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
01240 }
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250 Psn =
UdfLookupPsnOfExtent( IrpContext,
01251 Vcb,
01252 Reference,
01253 Lbn,
01254 Len );
01255
01256
01257
01258
01259
01260
try {
01261
01262
01263
01264
01265
01266
01267 Fcb = Vcb->MetadataFcb;
01268
UdfLockFcb( IrpContext, Fcb );
01269
01270 Result =
UdfVmcbLbnToVbn( &Vcb->Vmcb,
01271 Psn,
01272 &Vsn,
01273 &SectorCount );
01274
01275
if (Result) {
01276
01277
01278
01279
01280
01281
if (
BlocksFromSectors( Vcb, SectorCount ) >=
BlocksFromBytes( Vcb, Len )) {
01282
01283
try_leave( NOTHING );
01284
01285 }
01286
01287
01288
01289
01290
01291
01292
01293
UdfRaiseStatus( IrpContext, STATUS_FILE_CORRUPT_ERROR );
01294 }
01295
01296
01297
01298
01299
01300
UdfAddVmcbMapping( &Vcb->Vmcb,
01301 Psn,
01302
SectorsFromBytes( Vcb, Len ),
01303 ExactEnd,
01304 &Vsn,
01305 &SectorCount );
01306
01307 UnwindAllocationSize = Fcb->AllocationSize.QuadPart;
01308 UnwindExtension =
TRUE;
01309
01310 Fcb->AllocationSize.QuadPart =
01311 Fcb->FileSize.QuadPart =
01312 Fcb->ValidDataLength.QuadPart =
LlBytesFromSectors( Vcb, Vsn + SectorCount);
01313
01314
CcSetFileSizes( Fcb->FileObject, (
PCC_FILE_SIZES) &Fcb->AllocationSize );
01315 UnwindExtension =
FALSE;
01316
01317
01318
01319
01320
01321
01322 } finally {
01323
01324
if (UnwindExtension) {
01325
01326 ULONG FirstZappedVsn;
01327
01328
01329
01330
01331
01332 Fcb->AllocationSize.QuadPart =
01333 Fcb->FileSize.QuadPart =
01334 Fcb->ValidDataLength.QuadPart = UnwindAllocationSize;
01335
01336 FirstZappedVsn =
SectorsFromBytes( Vcb, UnwindAllocationSize );
01337
01338
UdfRemoveVmcbMapping( &Vcb->Vmcb,
01339 FirstZappedVsn,
01340 Vsn + SectorCount - FirstZappedVsn );
01341
01342
CcSetFileSizes( Fcb->FileObject, (
PCC_FILE_SIZES) &Fcb->AllocationSize );
01343 }
01344
01345
if (Fcb) {
UdfUnlockFcb( IrpContext, Fcb ); }
01346 }
01347
01348
return Vsn;
01349 }
01350
01351
01352
01353
01354
01355
01356
PPCB
01357 UdfCreatePcb (
01358 IN ULONG NumberOfPartitions
01359 )
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377 {
01378
PPCB Pcb;
01379 ULONG
Size =
sizeof(
PCB) +
sizeof(
PARTITION)*NumberOfPartitions;
01380
01381
PAGED_CODE();
01382
01383
ASSERT( NumberOfPartitions );
01384
ASSERT( NumberOfPartitions < MAXUSHORT );
01385
01386 Pcb = (
PPCB)
FsRtlAllocatePoolWithTag(
UdfPagedPool,
01387
Size,
01388
TAG_PCB );
01389
01390 RtlZeroMemory( Pcb,
Size );
01391
01392 Pcb->
NodeTypeCode =
UDFS_NTC_PCB;
01393 Pcb->
NodeByteSize = (
USHORT)
Size;
01394
01395 Pcb->
Partitions = (
USHORT)NumberOfPartitions;
01396
01397
return Pcb;
01398 }
01399
01400
01401
01402
01403
01404
01405
NTSTATUS
01406 UdfLoadSparingTables(
01407
PIRP_CONTEXT IrpContext,
01408
PVCB Vcb,
01409
PPCB Pcb,
01410 ULONG Reference
01411 )
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434 {
01435
NTSTATUS Status;
01436
01437 ULONG SparingTable;
01438 PULONG SectorBuffer;
01439 ULONG Psn;
01440
01441 ULONG RemainingBytes;
01442 ULONG ByteOffset;
01443 ULONG TotalBytes;
01444
01445 BOOLEAN Complete;
01446
01447
PSPARING_TABLE_HEADER Header;
01448
PSPARING_TABLE_ENTRY Entry;
01449
01450
PPARTITION Partition = &Pcb->
Partition[Reference];
01451
PPARTMAP_SPARABLE Map = Partition->Physical.SparingMap;
01452
01453
ASSERT_IRP_CONTEXT( IrpContext );
01454
ASSERT_VCB( Vcb );
01455
01456
ASSERT( Map !=
NULL );
01457
01458
DebugTrace(( +1,
Dbg,
"UdfLoadSparingTables, Vcb %08x, PcbPartition %08x, Map @ %08x\n", Vcb, Partition, Map ));
01459
01460
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, Map sez: PacketLen %u, NTables %u, TableSize %u\n",
01461 Map->
PacketLength,
01462 Map->
NumSparingTables,
01463 Map->
TableSize));
01464
01465
01466
01467
01468
01469
01470
01471
if (Map->
NumSparingTables == 0) {
01472
01473
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, no sparing tables claimed!\n" ));
01474
DebugTrace(( -1,
Dbg,
"UdfLoadSparingTables -> STATUS_SUCCESS\n" ));
01475
return STATUS_SUCCESS;
01476 }
01477
01478
if (Map->
NumSparingTables >
sizeof(Map->
TableLocation)/
sizeof(ULONG)) {
01479
01480
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, too many claimed tables to fit! (max %u)\n",
01481
sizeof(Map->
TableLocation)/
sizeof(ULONG)));
01482
DebugTrace(( -1,
Dbg,
"UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" ));
01483
return STATUS_DISK_CORRUPT_ERROR;
01484 }
01485
01486
if (Map->
PacketLength !=
UDF_SPARING_PACKET_LENGTH) {
01487
01488
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, packet size is %u (not %u!\n",
01489 Map->
PacketLength,
01490
UDF_SPARING_PACKET_LENGTH ));
01491
DebugTrace(( -1,
Dbg,
"UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" ));
01492
return STATUS_DISK_CORRUPT_ERROR;
01493 }
01494
01495
if (Map->
TableSize <
sizeof(
SPARING_TABLE_HEADER) ||
01496 (Map->
TableSize -
sizeof(
SPARING_TABLE_HEADER)) %
sizeof(
SPARING_TABLE_ENTRY) != 0) {
01497
01498
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, sparing table size is too small or unaligned!\n" ));
01499
DebugTrace(( -1,
Dbg,
"UdfLoadSparingTables -> STATUS_DISK_CORRUPT_ERROR\n" ));
01500
return STATUS_DISK_CORRUPT_ERROR;
01501 }
01502
01503
#ifdef UDF_SANITY
01504
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables" ));
01505
for (SparingTable = 0; SparingTable < Map->
NumSparingTables; SparingTable++) {
01506
01507
DebugTrace(( 0,
Dbg,
", Table %u @ %x", SparingTable, Map->
TableLocation[SparingTable] ));
01508 }
01509
DebugTrace(( 0,
Dbg,
"\n" ));
01510
#endif
01511
01512
01513
01514
01515
01516
if (Pcb->
SparingMcb ==
NULL) {
01517
01518 Pcb->
SparingMcb =
FsRtlAllocatePoolWithTag(
PagedPool,
sizeof(
LARGE_MCB),
TAG_SPARING_MCB );
01519
FsRtlInitializeLargeMcb( Pcb->
SparingMcb,
PagedPool );
01520 }
01521
01522 SectorBuffer =
FsRtlAllocatePoolWithTag(
PagedPool,
PAGE_SIZE,
TAG_NSR_FSD );
01523
01524
01525
01526
01527
01528
try {
01529
01530
for (Complete =
FALSE, SparingTable = 0;
01531
01532 SparingTable < Map->
NumSparingTables;
01533
01534 SparingTable++) {
01535
01536
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, loading sparing table %u!\n",
01537 SparingTable ));
01538
01539 ByteOffset = 0;
01540 TotalBytes = 0;
01541 RemainingBytes = 0;
01542
01543
do {
01544
01545
if (RemainingBytes == 0) {
01546
01547 (
VOID)
UdfReadSectors( IrpContext,
01548
BytesFromSectors( Vcb, Map->
TableLocation[SparingTable] ) + ByteOffset,
01549
SectorSize( Vcb ),
01550
FALSE,
01551 SectorBuffer,
01552 Vcb->
TargetDeviceObject );
01553
01554
01555
01556
01557
01558
01559
if (ByteOffset == 0) {
01560
01561
Header = (
PSPARING_TABLE_HEADER) SectorBuffer;
01562
01563
if (!
UdfVerifyDescriptor( IrpContext,
01564 &
Header->Destag,
01565 0,
01566
SectorSize( Vcb ),
01567
Header->Destag.Lbn,
01568
TRUE )) {
01569
01570
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, sparing table %u didn't verify destag!\n",
01571 SparingTable ));
01572
break;
01573 }
01574
01575
if (!
UdfUdfIdentifierContained( &
Header->RegID,
01576 &
UdfSparingTableIdentifier,
01577
UDF_VERSION_150,
01578
UDF_VERSION_RECOGNIZED,
01579
OSCLASS_INVALID,
01580
OSIDENTIFIER_INVALID)) {
01581
01582
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, sparing table %u didn't verify regid!\n",
01583 SparingTable ));
01584
break;
01585 }
01586
01587
01588
01589
01590
01591
01592
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, Sparing table %u has %u entries\n",
01593 SparingTable,
01594
Header->TableEntries ));
01595
01596 TotalBytes =
sizeof(
SPARING_TABLE_HEADER) +
Header->TableEntries *
sizeof(
SPARING_TABLE_ENTRY);
01597
01598
if (Map->
TableSize < TotalBytes) {
01599
01600
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, sparing table #ents %u overflows allocation!\n",
01601
Header->TableEntries ));
01602
break;
01603 }
01604
01605
01606
01607
01608
01609 ByteOffset =
sizeof(
SPARING_TABLE_HEADER);
01610 Entry =
Add2Ptr( SectorBuffer,
sizeof(
SPARING_TABLE_HEADER),
PSPARING_TABLE_ENTRY );
01611
01612 }
else {
01613
01614
01615
01616
01617
01618 Entry = (
PSPARING_TABLE_ENTRY) SectorBuffer;
01619 }
01620
01621 RemainingBytes =
Min(
SectorSize( Vcb ), TotalBytes - ByteOffset );
01622 }
01623
01624
01625
01626
01627
01628
01629
01630
if (Entry->
Original !=
UDF_SPARING_AVALIABLE &&
01631 Entry->
Original !=
UDF_SPARING_DEFECTIVE) {
01632
01633 Psn = Partition->Physical.Start +
SectorsFromBlocks( Vcb, Entry->
Original );
01634
01635
DebugTrace(( 0,
Dbg,
"UdfLoadSparingTables, mapping from Psn %x (Lbn %x) -> Psn %x\n",
01636 Psn,
01637 Entry->
Original,
01638 Entry->
Mapped ));
01639
01640
FsRtlAddLargeMcbEntry( Pcb->
SparingMcb,
01641 Psn,
01642 Entry->
Mapped,
01643
UDF_SPARING_PACKET_LENGTH );
01644 }
01645
01646
01647
01648
01649
01650 ByteOffset +=
sizeof(
SPARING_TABLE_ENTRY);
01651 RemainingBytes -=
sizeof(
SPARING_TABLE_ENTRY);
01652 Entry++;
01653
01654 }
while ( ByteOffset < TotalBytes );
01655 }
01656
01657 } finally {
01658
01659
DebugUnwind(
UdfLoadSparingTables );
01660
01661
UdfFreePool( &SectorBuffer );
01662 }
01663
01664
DebugTrace(( -1,
Dbg,
"UdfLoadSparingTables -> STATUS_SUCCESS\n" ));
01665
01666
return STATUS_SUCCESS;
01667 }