1 ////////////////////////////////////////////////////////////////////
2 // Copyright (C) Alexander Telyatnikov, Ivan Keliukh, Yegor Anchishkin, SKIF Software, 1999-2013. Kiev, Ukraine
3 // All rights reserved
4 // This file was released under the GPLv2 on June 2015.
5 ////////////////////////////////////////////////////////////////////
6 /*
7         Module name:
8 
9    mount.cpp
10 
11         Abstract:
12 
13    This file contains filesystem-specific routines
14    responsible for Mount/Umount
15 
16 */
17 
18 #include "udf.h"
19 
20 /* FIXME */
21 #ifdef XCHG_DD
22 #undef XCHG_DD
23 #endif
24 
25 #define XCHG_DD(a,b)              \
26 {                                 \
27     ULONG  _temp_;                \
28     PULONG _from_, _to_;          \
29     _from_ = ((PULONG)&(b));      \
30     _to_ =   ((PULONG)&(a));      \
31     _temp_ = *_from_;             \
32     *_from_ = *_to_;              \
33     *_to_ = _temp_;               \
34 }
35 
36 #define         UDF_BUG_CHECK_ID                UDF_FILE_UDF_INFO_MOUNT
37 
38 OSSTATUS
39 __fastcall
40 UDFSetDstring(
41     IN PUNICODE_STRING UName,
42     IN dstring* Dest,
43     IN uint32 Length
44     );
45 
46 #ifndef UDF_READ_ONLY_BUILD
47 /*
48     This routine loads specified bitmap.
49     It is also allocate space if the bitmap is not allocated.
50  */
51 OSSTATUS
52 UDFPrepareXSpaceBitmap(
53     IN PVCB Vcb,
54  IN OUT PSHORT_AD XSpaceBitmap,
55  IN OUT PEXTENT_INFO XSBMExtInfo,
56  IN OUT int8** XSBM,
57  IN OUT uint32* XSl
58     )
59 {
60     uint32 BS, j, LBS;
61     uint32 plen;
62     OSSTATUS status;
63     EXTENT_MAP TmpExt;
64     lb_addr locAddr;
65     int8* _XSBM;
66     uint16 Ident;
67     SIZE_T ReadBytes;
68     uint32 PartNum;
69 
70     if(!(XSpaceBitmap->extLength)) {
71         *XSl = 0;
72         *XSBM = NULL;
73         return STATUS_SUCCESS;
74     }
75 
76     PartNum = UDFGetPartNumByPartNdx(Vcb, Vcb->PartitionMaps-1);
77     locAddr.partitionReferenceNum = (uint16)PartNum;
78     plen = UDFPartStart(Vcb, PartNum) + UDFPartLen(Vcb, PartNum);
79 
80     BS = Vcb->BlockSize;
81     LBS = Vcb->LBlockSize;
82 
83     *XSl = sizeof(SPACE_BITMAP_DESC) + ((plen+7)>>3);
84     _XSBM = (int8*)DbgAllocatePool(NonPagedPool, (*XSl + BS - 1) & ~(BS-1) );
85     *XSBM = _XSBM;
86 
87     switch (XSpaceBitmap->extLength >> 30) {
88     case EXTENT_RECORDED_ALLOCATED: {
89         locAddr.logicalBlockNum = XSpaceBitmap->extPosition;
90         *XSl = min(XSpaceBitmap->extLength, *XSl);
91         TmpExt.extLength = XSpaceBitmap->extLength = *XSl;
92         TmpExt.extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
93         if(TmpExt.extLocation == LBA_OUT_OF_EXTENT) {
94             BrutePoint();
95         }
96         XSBMExtInfo->Mapping = UDFExtentToMapping(&TmpExt);
97         XSBMExtInfo->Offset = 0;
98         XSBMExtInfo->Length = *XSl;
99         break;
100     }
101     case EXTENT_NEXT_EXTENT_ALLOCDESC:
102     case EXTENT_NOT_RECORDED_NOT_ALLOCATED: {
103         // allocate space for bitmap
104         if(!OS_SUCCESS(status = UDFAllocFreeExtent(Vcb, *XSl,
105                UDFPartStart(Vcb, PartNum), UDFPartEnd(Vcb, PartNum), XSBMExtInfo, EXTENT_FLAG_ALLOC_SEQUENTIAL) ))
106             return status;
107         if(XSBMExtInfo->Mapping[1].extLength) {
108             UDFPrint(("Can't allocate space for Freed Space bitmap\n"));
109             *XSl = 0;
110         } else {
111             *XSl = (uint32)(XSBMExtInfo->Length);
112             XSpaceBitmap->extPosition = UDFPhysLbaToPart(Vcb, PartNum, XSBMExtInfo->Mapping[0].extLocation);
113         }
114         break;
115     }
116     case EXTENT_NOT_RECORDED_ALLOCATED: {
117         // record Alloc-Not-Rec
118         locAddr.logicalBlockNum = XSpaceBitmap->extPosition;
119         *XSl = min((XSpaceBitmap->extLength & UDF_EXTENT_LENGTH_MASK), *XSl);
120         TmpExt.extLength = XSpaceBitmap->extLength = *XSl;
121         TmpExt.extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
122         if(TmpExt.extLocation == LBA_OUT_OF_EXTENT) {
123             BrutePoint();
124         }
125         XSBMExtInfo->Mapping = UDFExtentToMapping(&TmpExt);
126         XSBMExtInfo->Offset = 0;
127         XSBMExtInfo->Length = *XSl;
128         break;
129     }
130     }
131 
132     if(!_XSBM) {
133         BrutePoint();
134         return STATUS_INSUFFICIENT_RESOURCES;
135     }
136 
137     switch (XSpaceBitmap->extLength >> 30) {
138     case EXTENT_RECORDED_ALLOCATED: {
139         // read descriptor & bitmap
140         if((!OS_SUCCESS(status = UDFReadTagged(Vcb, *XSBM, (j = TmpExt.extLocation),
141                              locAddr.logicalBlockNum, &Ident))) ||
142            (Ident != TID_SPACE_BITMAP_DESC) ||
143            (!OS_SUCCESS(status = UDFReadExtent(Vcb, XSBMExtInfo, 0, *XSl, FALSE, *XSBM, &ReadBytes))) ) {
144             if(OS_SUCCESS(status)) {
145                 BrutePoint();
146                 status = STATUS_FILE_CORRUPT_ERROR;
147             }
148             if(XSBMExtInfo->Mapping) {
149                 MyFreePool__(XSBMExtInfo->Mapping);
150                 XSBMExtInfo->Mapping = NULL;
151             }
152             DbgFreePool(*XSBM);
153             *XSl = 0;
154             *XSBM = NULL;
155             return status;
156         } else {
157 //            BrutePoint();
158         }
159         return STATUS_SUCCESS;
160     }
161 #if 0
162     case EXTENT_NEXT_EXTENT_ALLOCDESC:
163     case EXTENT_NOT_RECORDED_NOT_ALLOCATED:
164     case EXTENT_NOT_RECORDED_ALLOCATED: {
165         break;
166     }
167 #endif
168     }
169 
170     PSPACE_BITMAP_DESC XSDesc = (PSPACE_BITMAP_DESC)(*XSBM);
171 
172     XSpaceBitmap->extLength = (*XSl + LBS -1) & ~(LBS-1);
173     RtlZeroMemory(*XSBM, *XSl);
174     XSDesc->descTag.tagIdent = TID_SPACE_BITMAP_DESC;
175     UDFSetUpTag(Vcb, &(XSDesc->descTag), 0, XSpaceBitmap->extPosition);
176     XSDesc->numOfBits = plen;
177     XSDesc->numOfBytes = (*XSl)-sizeof(SPACE_BITMAP_DESC);
178 
179     return STATUS_SUCCESS;
180 } // end UDFPrepareXSpaceBitmap()
181 
182 /*
183     This routine updates Freed & Unallocated space bitmaps
184  */
185 OSSTATUS
186 UDFUpdateXSpaceBitmaps(
187     IN PVCB Vcb,
188     IN uint32 PartNum,
189     IN PPARTITION_HEADER_DESC phd // partition header pointing to Bitmaps
190     )
191 {
192     uint32 i,j,d;
193     uint32 plen, pstart, pend;
194     int8* bad_bm;
195     int8* old_bm;
196     int8* new_bm;
197     int8* fpart_bm;
198     int8* upart_bm;
199     OSSTATUS status, status2;
200     int8* USBM=NULL;
201     int8* FSBM=NULL;
202     uint32 USl, FSl;
203     EXTENT_INFO FSBMExtInfo, USBMExtInfo;
204 //    lb_addr locAddr;
205     SIZE_T WrittenBytes;
206 
207     UDF_CHECK_BITMAP_RESOURCE(Vcb);
208 
209     plen = UDFPartLen(Vcb, PartNum);
210 //    locAddr.partitionReferenceNum = (uint16)PartNum;
211     // prepare bitmaps for updating
212 
213     status =  UDFPrepareXSpaceBitmap(Vcb, &(phd->unallocatedSpaceBitmap), &USBMExtInfo, &USBM, &USl);
214     status2 = UDFPrepareXSpaceBitmap(Vcb, &(phd->freedSpaceBitmap), &FSBMExtInfo, &FSBM, &FSl);
215     if(!OS_SUCCESS(status) ||
216        !OS_SUCCESS(status2)) {
217         BrutePoint();
218     }
219 
220     pstart = UDFPartStart(Vcb, PartNum);
221     new_bm = Vcb->FSBM_Bitmap;
222     old_bm = Vcb->FSBM_OldBitmap;
223     bad_bm = Vcb->BSBM_Bitmap;
224 
225     if((status  == STATUS_INSUFFICIENT_RESOURCES) ||
226        (status2 == STATUS_INSUFFICIENT_RESOURCES)) {
227         // try to recover insufficient resources
228         if(USl && USBMExtInfo.Mapping) {
229             USl -= sizeof(SPACE_BITMAP_DESC);
230             status  = UDFWriteExtent(Vcb, &USBMExtInfo, sizeof(SPACE_BITMAP_DESC), USl, FALSE, new_bm, &WrittenBytes);
231 #ifdef UDF_DBG
232         } else {
233             UDFPrint(("Can't update USBM\n"));
234 #endif // UDF_DBG
235         }
236         if(USBMExtInfo.Mapping) MyFreePool__(USBMExtInfo.Mapping);
237 
238         if(FSl && FSBMExtInfo.Mapping) {
239             FSl -= sizeof(SPACE_BITMAP_DESC);
240             status2 = UDFWriteExtent(Vcb, &FSBMExtInfo, sizeof(SPACE_BITMAP_DESC), FSl, FALSE, new_bm, &WrittenBytes);
241         } else {
242             status2 = status;
243             UDFPrint(("Can't update FSBM\n"));
244         }
245         if(FSBMExtInfo.Mapping) MyFreePool__(FSBMExtInfo.Mapping);
246     } else {
247         // normal way to record BitMaps
248         if(USBM) upart_bm =  USBM + sizeof(SPACE_BITMAP_DESC);
249         if(FSBM) fpart_bm =  FSBM + sizeof(SPACE_BITMAP_DESC);
250         pend = min(pstart + plen, Vcb->FSBM_BitCount);
251 
252         d=1<<Vcb->LB2B_Bits;
253         // if we have some bad bits, mark corresponding area as BAD
254         if(bad_bm) {
255             for(i=pstart; i<pend; i++) {
256                 if(UDFGetBadBit(bad_bm, i)) {
257                     // TODO: would be nice to add these blocks to unallocatable space
258                     UDFSetUsedBits(new_bm, i & ~(d-1), d);
259                 }
260             }
261         }
262         j=0;
263         for(i=pstart; i<pend; i+=d) {
264             if(UDFGetUsedBit(old_bm, i) && UDFGetFreeBit(new_bm, i)) {
265                 // sector was deallocated during last session
266                 if(USBM) UDFSetFreeBit(upart_bm, j);
267                 if(FSBM) UDFSetFreeBit(fpart_bm, j);
268             } else if(UDFGetUsedBit(new_bm, i)) {
269                 // allocated
270                 if(USBM) UDFSetUsedBit(upart_bm, j);
271                 if(FSBM) UDFSetUsedBit(fpart_bm, j);
272             }
273             j++;
274         }
275         // flush updates
276         if(USBM) {
277             status  = UDFWriteExtent(Vcb, &USBMExtInfo, 0, USl, FALSE, USBM, &WrittenBytes);
278             DbgFreePool(USBM);
279             MyFreePool__(USBMExtInfo.Mapping);
280         }
281         if(FSBM) {
282             status2 = UDFWriteExtent(Vcb, &FSBMExtInfo, 0, FSl, FALSE, FSBM, &WrittenBytes);
283             DbgFreePool(FSBM);
284             MyFreePool__(FSBMExtInfo.Mapping);
285         } else {
286             status2 = status;
287         }
288     }
289 
290     if(!OS_SUCCESS(status))
291         return status;
292     return status2;
293 } // end UDFUpdateXSpaceBitmaps()
294 
295 /*
296     This routine updates Partition Desc & associated data structures
297  */
298 OSSTATUS
299 UDFUpdatePartDesc(
300     PVCB Vcb,
301     int8* Buf
302     )
303 {
304     PartitionDesc *p = (PartitionDesc *)Buf;
305     uint32 i; // PartNdx
306     tag* PTag;
307     SIZE_T WrittenBytes;
308 
309     for(i=0; i<Vcb->PartitionMaps; i++)
310     {
311         if((UDFGetPartNumByPartNdx(Vcb,i) == p->partitionNumber) &&
312            (!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
313             !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03)))
314         {
315             PPARTITION_HEADER_DESC phd;
316 
317             phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
318 #ifdef UDF_DBG
319             if(phd->unallocatedSpaceTable.extLength) {
320                 // rebuild unallocatedSpaceTable
321                 UDFPrint(("unallocatedSpaceTable (part %d)\n", i));
322             }
323             if(phd->freedSpaceTable.extLength) {
324                 // rebuild freedSpaceTable
325                 UDFPrint(("freedSpaceTable (part %d)\n", i));
326             }
327 #endif // UDF_DBG
328             UDFUpdateXSpaceBitmaps(Vcb, p->partitionNumber, phd);
329             PTag = (tag*)Buf;
330             UDFSetUpTag(Vcb, PTag, PTag->descCRCLength, PTag->tagLocation);
331             UDFWriteSectors(Vcb, TRUE, PTag->tagLocation, 1, FALSE, Buf, &WrittenBytes);
332         }
333     }
334     return STATUS_SUCCESS;
335 } // end UDFUpdatePartDesc()
336 
337 /*
338     This routine blanks Unalloc Space Desc
339  *//*
340 OSSTATUS
341 UDFUpdateUSpaceDesc(
342     IN PVCB Vcb,
343     int8* Buf
344     )
345 {
346     PUNALLOC_SPACE_DESC usd;
347     SIZE_T WrittenBytes;
348 
349     usd = (PUNALLOC_SPACE_DESC)Buf;
350     usd->numAllocDescs = 0;
351     RtlZeroMemory(Buf+sizeof(UNALLOC_SPACE_DESC), Vcb->BlockSize - sizeof(UNALLOC_SPACE_DESC));
352     UDFSetUpTag(Vcb, &(usd->descTag), 0, usd->descTag.tagLocation);
353     UDFWriteSectors(Vcb, TRUE, usd->descTag.tagLocation, 1, FALSE, Buf, &WrittenBytes);
354     return STATUS_SUCCESS;
355 }*/
356 
357 /*
358    update Logical volume integrity descriptor
359  */
360 OSSTATUS
361 UDFUpdateLogicalVolInt(
362     PVCB            Vcb,
363     BOOLEAN         Close
364     )
365 {
366     OSSTATUS    RC = STATUS_SUCCESS;
367     uint32      i, len;
368     SIZE_T      WrittenBytes;
369 //    uint32      lvid_count = 0;
370     uint32      pSize;
371     tag*        PTag;
372     LogicalVolIntegrityDesc *lvid;
373     LogicalVolIntegrityDescImpUse* LVID_iUse;
374     LogicalVolHeaderDesc* LVID_hd;
375     uint32*     partFreeSpace;
376     BOOLEAN     equal = FALSE;
377 
378     if(Vcb->CDR_Mode)
379         return STATUS_SUCCESS;
380     if(!Vcb->LVid) {
381         return STATUS_UNSUCCESSFUL;
382     }
383 
384     UDFPrint(("UDF: Updating LVID @%x (%x)\n", Vcb->LVid_loc.extLocation, Vcb->LVid_loc.extLength));
385     len = max(Vcb->LVid_loc.extLength, Vcb->BlockSize);
386     lvid = Vcb->LVid;
387     if(lvid->descTag.tagSerialNum > UDF_LVID_TTL) {
388         // TODO: allocate space for new LVID
389     }
390 
391     LVID_iUse = UDFGetLVIDiUse(Vcb);
392 
393     if((LVID_iUse->minUDFReadRev  == Vcb->minUDFReadRev) &&
394        (LVID_iUse->minUDFWriteRev == Vcb->minUDFWriteRev) &&
395        (LVID_iUse->maxUDFWriteRev == Vcb->maxUDFWriteRev) &&
396        (LVID_iUse->numFiles == Vcb->numFiles) &&
397        (LVID_iUse->numDirs  == Vcb->numDirs))
398         equal = TRUE;
399 
400     LVID_iUse->minUDFReadRev  = Vcb->minUDFReadRev;
401     LVID_iUse->minUDFWriteRev = Vcb->minUDFWriteRev;
402     LVID_iUse->maxUDFWriteRev = Vcb->maxUDFWriteRev;
403 
404     LVID_iUse->numFiles = Vcb->numFiles;
405     LVID_iUse->numDirs  = Vcb->numDirs;
406 
407 #if 0
408     UDFSetEntityID_imp(&(LVID_iUse->impIdent), UDF_ID_DEVELOPER);
409 #endif
410 
411     if(Close){
412         UDFPrint(("UDF: Opening LVID\n"));
413         lvid->integrityType = INTEGRITY_TYPE_CLOSE;
414     } else {
415         UDFPrint(("UDF: Closing LVID\n"));
416         lvid->integrityType = INTEGRITY_TYPE_OPEN;
417     }
418 
419     equal = equal && (Vcb->IntegrityType == lvid->integrityType);
420 
421     // update Free Space Table
422     partFreeSpace = (uint32*)(lvid+1);
423     for(i=0; i<lvid->numOfPartitions; i++) {
424         pSize = UDFGetPartFreeSpace(Vcb, i) >> Vcb->LB2B_Bits;
425         equal = equal && (partFreeSpace[i] == pSize);
426         partFreeSpace[i] = pSize;
427     }
428 
429     // Update LVID Header Descriptor
430     LVID_hd = (LogicalVolHeaderDesc*)&(lvid->logicalVolContentsUse);
431     equal = equal && (LVID_hd->uniqueID == Vcb->NextUniqueId);
432     LVID_hd->uniqueID = Vcb->NextUniqueId;
433 
434     if(equal) {
435         UDFPrint(("UDF: equal Ids\n"));
436         return STATUS_SUCCESS;
437     }
438 
439     PTag = &(lvid->descTag);
440     lvid->lengthOfImpUse =
441         sizeof(LogicalVolIntegrityDescImpUse);
442     UDFSetUpTag(Vcb, PTag,
443         sizeof(LogicalVolIntegrityDesc) +
444         sizeof(uint32)*2*lvid->numOfPartitions +
445         sizeof(LogicalVolIntegrityDescImpUse),
446         PTag->tagLocation);
447 
448     Vcb->IntegrityType = INTEGRITY_TYPE_OPEN; // make happy auto-dirty
449     RC = UDFWriteSectors(Vcb, TRUE, PTag->tagLocation, len >> Vcb->BlockSizeBits, FALSE, (int8*)(lvid), &WrittenBytes);
450     WCacheFlushBlocks__(&(Vcb->FastCache), Vcb, PTag->tagLocation, len >> Vcb->BlockSizeBits);
451     // update it here to prevent recursion
452     Vcb->IntegrityType = lvid->integrityType;
453 
454     return RC;
455 } // end UDFUpdateLogicalVolInt()
456 
457 /*
458     This routine reads all sparing tables & stores them in contiguos memory
459     space
460  */
461 OSSTATUS
462 UDFUpdateSparingTable(
463     IN PVCB Vcb
464     )
465 {
466     PSPARING_MAP RelocMap;
467 //    PSPARING_MAP NewRelocMap;
468     OSSTATUS status = STATUS_SUCCESS;
469     OSSTATUS status2 = STATUS_SUCCESS;
470     uint32 i=0, BC, BC2;
471     PSPARING_TABLE SparTable;
472     SIZE_T ReadBytes;
473 //    uint32 n,m;
474 //    BOOLEAN merged;
475     BOOLEAN sorted;
476 
477     UDFPrint(("UDF: Updating Sparable Part Map:\n"));
478     if(!Vcb->SparingTableModified) return STATUS_SUCCESS;
479     if(!Vcb->SparingTable) return STATUS_SUCCESS;
480 
481     BC = (Vcb->SparingTableLength >> Vcb->BlockSizeBits) + 1;
482     SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize);
483     if(!SparTable) return STATUS_INSUFFICIENT_RESOURCES;
484     // if a part of Sparing Table is already loaded,
485     // update it with data from another one
486     RelocMap = Vcb->SparingTable;
487     // sort sparing table
488     //merged = FALSE;
489     do {
490         sorted = FALSE;
491         for(i=1;i<Vcb->SparingCount;i++) {
492             if(RelocMap[i-1].origLocation > RelocMap[i].origLocation) {
493                 XCHG_DD(RelocMap[i-1].origLocation,   RelocMap[i].origLocation);
494 swp_loc:
495                 XCHG_DD(RelocMap[i-1].mappedLocation, RelocMap[i].mappedLocation);
496                 //merged = TRUE;
497                 sorted = TRUE;
498             } else
499             if(RelocMap[i-1].origLocation == SPARING_LOC_AVAILABLE &&
500                RelocMap[i].origLocation   == SPARING_LOC_AVAILABLE &&
501                RelocMap[i-1].mappedLocation > RelocMap[i].mappedLocation) {
502                 goto swp_loc;
503             }
504         }
505     } while(sorted);
506 
507     for(i=0;i<Vcb->SparingCount;i++) {
508         UDFPrint(("  @%x -> %x \n",
509             RelocMap[i].origLocation, RelocMap[i].mappedLocation));
510     }
511 
512     Vcb->SparingTableModified = FALSE;
513 //    if(!merged) {
514 //        UDFPrint(("  sparing table unchanged\n"));
515 //        MyFreePool__(SparTable);
516 //        return STATUS_SUCCESS;
517 //    }
518 
519     // walk through all available Sparing Tables
520     for(i=0;i<Vcb->SparingTableCount;i++) {
521         // read (next) table
522         UDFPrint(("  sparing table @%x\n", Vcb->SparingTableLoc[i]));
523         status = UDFReadSectors(Vcb, FALSE, Vcb->SparingTableLoc[i], 1, FALSE, (int8*)SparTable, &ReadBytes);
524         // tag should be set to TID_UNUSED_DESC
525         if(OS_SUCCESS(status) && (SparTable->descTag.tagIdent == TID_UNUSED_DESC)) {
526 
527             BC2 = ((sizeof(SPARING_TABLE) +
528                     SparTable->reallocationTableLen*sizeof(SparingEntry) +
529                     Vcb->BlockSize-1)
530                                       >> Vcb->BlockSizeBits);
531             if(BC2 > BC) {
532                 UDFPrint((" sizeSparingTable @%x too long: %x > %x\n",
533                     Vcb->SparingTableLoc[i], BC2, BC
534                     ));
535                 continue;
536             }
537             status = UDFReadSectors(Vcb, FALSE, Vcb->SparingTableLoc[i],
538                 BC2, FALSE, (int8*)SparTable, &ReadBytes);
539 
540             if(!OS_SUCCESS(status)) {
541                 UDFPrint((" Error reading sizeSparingTable @%x (%x)\n",
542                     Vcb->SparingTableLoc[i], BC2
543                     ));
544                 continue;
545             }
546 
547             BC2 = ((sizeof(SPARING_TABLE) +
548                     Vcb->SparingCount*sizeof(SparingEntry) +
549                     Vcb->BlockSize-1)
550                                       >> Vcb->BlockSizeBits);
551             if(BC2 > BC) {
552                 UDFPrint((" new sizeSparingTable @%x too long: %x > %x\n",
553                     Vcb->SparingTableLoc[i], BC2, BC
554                     ));
555                 continue;
556             }
557 
558             SparTable->reallocationTableLen = (USHORT)Vcb->SparingCount;
559             RtlCopyMemory((SparTable+1), RelocMap, Vcb->SparingCount*sizeof(SparingEntry));
560 /*
561             merged = FALSE;
562             NewRelocMap = (PSPARING_MAP)(SparTable+1);
563             for(n=0; n<SparTable->reallocationTableLen; n++) {
564                 for(m=0; m<Vcb->SparingCount; m++) {
565                     if(RelocMap[m].mappedLocation == NewRelocMap[n].mappedLocation) {
566                         if(RelocMap[m].origLocation != NewRelocMap[n].origLocation) {
567                             UDFPrint(("  update @%x (%x) -> @%x (%x)\n",
568                                 NewRelocMap[m].origLocation, NewRelocMap[m].mappedLocation,
569                                 RelocMap[m].origLocation, RelocMap[m].mappedLocation));
570                             merged = TRUE;
571                         }
572                     }
573                 }
574             }
575 */
576 //            if(merged) {
577             UDFPrint(("UDF: record updated\n"));
578             status = UDFWriteSectors(Vcb, FALSE, Vcb->SparingTableLoc[i], BC2, FALSE, (int8*)SparTable, &ReadBytes);
579             if(!OS_SUCCESS(status)) {
580                 if(!OS_SUCCESS(status2)) {
581                     status2 = status;
582                 }
583 //                }
584             }
585         }
586     }
587     MyFreePool__(SparTable);
588     if(!OS_SUCCESS(status2)) {
589         status = status2;
590     }
591     return status;
592 } // end UDFUpdateSparingTable()
593 
594 /*
595     update Logical volume descriptor
596  */
597 OSSTATUS
598 UDFUpdateLogicalVol(
599     IN PVCB            Vcb,
600     IN UDF_VDS_RECORD  Lba,
601     IN PUNICODE_STRING VolIdent
602     )
603 {
604     LogicalVolDesc* lvd = NULL;
605 #define CUR_IDENT_SZ (sizeof(lvd->logicalVolIdent))
606     dstring CS0[CUR_IDENT_SZ];
607     uint16 ident;
608     SIZE_T WrittenBytes;
609     OSSTATUS status = STATUS_SUCCESS;
610 //    OSSTATUS status2 = STATUS_SUCCESS;
611 
612     status = UDFUpdateSparingTable(Vcb);
613 
614     if(!(Vcb->CompatFlags & UDF_VCB_IC_W2K_COMPAT_VLABEL)) {
615         goto Err_SetVI;
616     }
617 
618     lvd = (LogicalVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->BlockSize, sizeof(LogicalVolDesc)) );
619 
620     if(!lvd) {
621         status = STATUS_INSUFFICIENT_RESOURCES;
622         goto Err_SetVI;
623     }
624 
625     UDFPrint(("UDF: Updating LVD @%x (%x)\n", Lba.block, Vcb->BlockSize));
626 
627     status = UDFSetDstring(&(Vcb->VolIdent), (dstring*)&CS0, CUR_IDENT_SZ);
628     if(!OS_SUCCESS(status)) {
629         if(status == STATUS_INVALID_PARAMETER) {
630             status = STATUS_INVALID_VOLUME_LABEL;
631         }
632         goto Err_SetVI;
633     }
634 
635     if(!Lba.block) {
636         status = STATUS_INVALID_PARAMETER;
637         goto Err_SetVI;
638     }
639     status = UDFReadTagged(Vcb, (int8*)lvd, Lba.block, Lba.block, &ident);
640     if(!OS_SUCCESS(status)) goto Err_SetVI;
641     if(ident != TID_LOGICAL_VOL_DESC) {
642         status = STATUS_FILE_CORRUPT_ERROR;
643         goto Err_SetVI;
644     }
645 
646     if(RtlCompareMemory(lvd->logicalVolIdent, CS0, CUR_IDENT_SZ) == CUR_IDENT_SZ) {
647         // no changes
648         UDFPrint(("UDF: equal VolIds\n"));
649         status = STATUS_SUCCESS;
650         goto Err_SetVI;
651     }
652     RtlCopyMemory(lvd->logicalVolIdent, CS0, CUR_IDENT_SZ);
653 
654     lvd->descTag.tagSerialNum --;
655     UDFSetUpTag(Vcb, (tag*)lvd, lvd->descTag.descCRCLength, Lba.block);
656 
657     status = UDFWriteSectors(Vcb, TRUE, Lba.block, 1, FALSE, (int8*)lvd, &WrittenBytes);
658 
659 Err_SetVI:
660     if(lvd)
661         MyFreePool__(lvd);
662 
663 #undef CUR_IDENT_SZ
664 //#endif //0
665 
666     return status;
667 } // end UDFUpdateLogicalVol()
668 
669 /*
670     This routine updates volume descriptor sequence
671  */
672 OSSTATUS
673 UDFUpdateVDS(
674     IN PVCB Vcb,
675     IN uint32 block,
676     IN uint32 lastblock,
677     IN uint32 flags
678     )
679 {
680     OSSTATUS status;
681     int8*    Buf = (int8*)DbgAllocatePool(NonPagedPool,Vcb->LBlockSize);
682     UDF_VDS_RECORD vds[VDS_POS_LENGTH];
683     uint32 i,j;
684     uint16 ident;
685 
686     if (!Buf) return STATUS_INSUFFICIENT_RESOURCES;
687     RtlZeroMemory(vds, sizeof(UDF_VDS_RECORD) * VDS_POS_LENGTH);
688     if(!OS_SUCCESS(status = UDFReadVDS(Vcb, block, lastblock, (PUDF_VDS_RECORD)&vds, Buf))) {
689         DbgFreePool(Buf);
690         return status;
691     }
692 
693 /*
694     // update USD (if any)
695     for (i=0; i<VDS_POS_LENGTH; i++) {
696         if (vds[i].block) {
697             status = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident);
698             if(OS_SUCCESS(status) && (i == VDS_POS_PARTITION_DESC)) {
699                 // load partition descriptor(s)
700                 int8*  Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->BlockSize);
701                 if (!Buf2) {
702                     DbgFreePool(Buf);
703                     return STATUS_INSUFFICIENT_RESOURCES;
704                 }
705                 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++) {
706                     UDFReadTagged(Vcb,Buf2, j, j, &ident);
707                     if (ident == TID_UNALLOC_SPACE_DESC)
708                         // This implememtation doesn't support USD ;) recording
709                         // So, we'll make'em blank, but record all bitmaps
710                         UDFUpdateUSpaceDesc(Vcb,Buf2);
711                 }
712                 DbgFreePool(Buf2);
713                 break;
714             }
715         }
716     }*/
717     for (i=0; i<VDS_POS_LENGTH; i++) {
718         if (vds[i].block) {
719             status = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident);
720             if(!OS_SUCCESS(status))
721                 continue;
722             // update XBMs
723             if(i == VDS_POS_PARTITION_DESC) {
724                 if(!(flags & 1))
725                     continue;
726                 // update partition descriptor(s)
727                 int8*  Buf2 = (int8*)DbgAllocatePool(NonPagedPool,Vcb->BlockSize);
728                 if (!Buf2) {
729                     DbgFreePool(Buf);
730                     return STATUS_INSUFFICIENT_RESOURCES;
731                 }
732                 UDFUpdatePartDesc(Vcb,Buf);
733                 for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++) {
734                     UDFReadTagged(Vcb,Buf2, j, j, &ident);
735                     if (ident == TID_PARTITION_DESC)
736                         UDFUpdatePartDesc(Vcb,Buf2);
737                 }
738                 DbgFreePool(Buf2);
739 //                continue;
740             } else
741             // update Vol Ident Desc
742             if(i == VDS_POS_LOGICAL_VOL_DESC) {
743                 status = UDFUpdateLogicalVol(Vcb, vds[VDS_POS_LOGICAL_VOL_DESC], &(Vcb->VolIdent));
744                 if(!OS_SUCCESS(status))
745                     continue;
746             }
747         }
748     }
749 
750     DbgFreePool(Buf);
751     return status;
752 } // end UDFUpdateVDS()
753 #endif //UDF_READ_ONLY_BUILD
754 
755 OSSTATUS
756 __fastcall
757 UDFSetDstring(
758     IN PUNICODE_STRING UName,
759     IN dstring* Dest,
760     IN uint32 Length
761     )
762 {
763     uint8* CS0;
764     SIZE_T len = Length-1;
765 
766     UDFCompressUnicode(UName, &CS0, &len);
767     if(!CS0)
768         return STATUS_INSUFFICIENT_RESOURCES;
769     if(len > Length-1) {
770         MyFreePool__(CS0);
771         return STATUS_INVALID_PARAMETER;
772     }
773     RtlCopyMemory(Dest, CS0, len);
774     MyFreePool__(CS0);
775     if(len < Length-1)
776         RtlZeroMemory(Dest+len, Length-1-len);
777     Dest[Length-1] = (uint8)len;
778     return TRUE;
779 } // end UDFSetDstring()
780 
781 void
782 __fastcall
783 UDFGetDstring(
784     IN OUT PUNICODE_STRING UName,
785     IN dstring* Dest,
786     IN uint32 Length
787     )
788 {
789     uint32 len = Dest[Length-1];
790 
791     UDFDecompressUnicode(UName, Dest, len, NULL);
792     return;
793 } // end UDFGetDstring()
794 
795 #ifndef UDF_READ_ONLY_BUILD
796 /*
797     This routine updates Volume Label & some other features stored in
798     VolIdentDesc
799  */
800 OSSTATUS
801 UDFUpdateVolIdent(
802     IN PVCB Vcb,
803     IN UDF_VDS_RECORD Lba,
804     IN PUNICODE_STRING VolIdent
805     )
806 {
807 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
808     PrimaryVolDesc* pvoldesc = (PrimaryVolDesc*)MyAllocatePool__(NonPagedPool, max(Vcb->BlockSize, sizeof(PrimaryVolDesc)) );
809     OSSTATUS status;
810     dstring CS0[CUR_IDENT_SZ];
811     uint16 ident;
812     SIZE_T WrittenBytes;
813 
814     if(!pvoldesc) return STATUS_INSUFFICIENT_RESOURCES;
815 
816     UDFPrint(("UDF: Updating PVD @%x (%x)\n", Lba.block, Vcb->BlockSize));
817 
818     status = UDFSetDstring(&(Vcb->VolIdent), (dstring*)&CS0, CUR_IDENT_SZ);
819     if(!OS_SUCCESS(status)) {
820         if(status == STATUS_INVALID_PARAMETER) {
821             status = STATUS_INVALID_VOLUME_LABEL;
822         }
823         goto Err_SetVI;
824     }
825 
826     if(!Lba.block) {
827         status = STATUS_INVALID_PARAMETER;
828         goto Err_SetVI;
829     }
830     status = UDFReadTagged(Vcb, (int8*)pvoldesc, Lba.block, Lba.block, &ident);
831     if(!OS_SUCCESS(status)) goto Err_SetVI;
832     if(ident != TID_PRIMARY_VOL_DESC) {
833         status = STATUS_FILE_CORRUPT_ERROR;
834         goto Err_SetVI;
835     }
836 
837     if(RtlCompareMemory(pvoldesc->volIdent, CS0, CUR_IDENT_SZ) == CUR_IDENT_SZ) {
838         // no changes
839         status = STATUS_SUCCESS;
840         goto Err_SetVI;
841     }
842     RtlCopyMemory(pvoldesc->volIdent, CS0, CUR_IDENT_SZ);
843 
844     pvoldesc->descTag.tagSerialNum --;
845     UDFSetUpTag(Vcb, (tag*)pvoldesc, pvoldesc->descTag.descCRCLength, Lba.block);
846 
847     status = UDFWriteSectors(Vcb, TRUE, Lba.block, 1, FALSE, (int8*)pvoldesc, &WrittenBytes);
848 Err_SetVI:
849     MyFreePool__(pvoldesc);
850     return status;
851 
852 #undef CUR_IDENT_SZ
853 } // end UDFUpdateVolIdent()
854 #endif //UDF_READ_ONLY_BUILD
855 
856 OSSTATUS
857 UDFUpdateNonAllocated(
858     IN PVCB Vcb
859     )
860 {
861     uint32 PartNum;
862     uint32 i;
863     uint32 plen, pstart, pend;
864     int8* bad_bm;
865     EXTENT_AD Ext;
866     PEXTENT_MAP Map = NULL;
867     PEXTENT_INFO DataLoc;
868 
869     UDFPrint(("UDFUpdateNonAllocated:\n"));
870     if(!Vcb->NonAllocFileInfo) {
871         return STATUS_SUCCESS;
872     }
873     if(!(bad_bm = Vcb->BSBM_Bitmap)) {
874         return STATUS_SUCCESS;
875     }
876 
877     DataLoc = &(Vcb->NonAllocFileInfo->Dloc->DataLoc);
878     ASSERT(!DataLoc->Offset);
879     if(Vcb->NonAllocFileInfo->Dloc->DataLoc.Offset) {
880         UDFPrint(("NonAllocFileInfo in IN_ICB mode !!!\n"));
881         return STATUS_SUCCESS;
882     }
883     PartNum = UDFGetPartNumByPhysLba(Vcb, Vcb->NonAllocFileInfo->Dloc->FELoc.Mapping[0].extLocation);
884     pstart = UDFPartStart(Vcb, PartNum);
885     plen = UDFPartLen(Vcb, PartNum);
886     pend = min(pstart + plen, Vcb->FSBM_BitCount);
887 
888     //BrutePoint();
889     for(i=pstart; i<pend; i++) {
890         if(!UDFGetBadBit(bad_bm, i))
891             continue;
892         // add BAD blocks to unallocatable space
893         // if the block is already in NonAllocatable, ignore it
894         if(UDFLocateLbaInExtent(Vcb, DataLoc->Mapping, i) != LBA_OUT_OF_EXTENT) {
895             UDFPrint(("lba %#x is already in NonAllocFileInfo\n", i));
896             continue;
897         }
898         UDFPrint(("add lba %#x to NonAllocFileInfo\n", i));
899         DataLoc->Modified = TRUE;
900         Ext.extLength = Vcb->LBlockSize;
901         // align lba on LogicalBlock boundary
902         Ext.extLocation = i & ~((1<<Vcb->LB2B_Bits) - 1);
903         Map = UDFExtentToMapping(&Ext);
904         DataLoc->Mapping = UDFMergeMappings(DataLoc->Mapping, Map);
905     }
906     UDFPackMapping(Vcb, DataLoc);
907     DataLoc->Length = UDFGetExtentLength(DataLoc->Mapping);
908     UDFFlushFile__(Vcb, Vcb->NonAllocFileInfo);
909 
910     // ensure that BAD space is marked as USED
911     UDFMarkSpaceAsXXX(Vcb, 0, &(DataLoc->Mapping[0]), AS_USED); // mark as used
912 
913     UDFPrint(("UDFUpdateNonAllocated: done\n"));
914     return STATUS_SUCCESS;
915 } // end UDFUpdateNonAllocated()
916 
917 /*
918     This routine rebuilds & flushes all system areas
919  */
920 OSSTATUS
921 UDFUmount__(
922     IN PVCB Vcb
923     )
924 {
925 #ifndef UDF_READ_ONLY_BUILD
926     uint32 flags = 0;
927 
928     if((Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY)
929         || !Vcb->Modified)
930         return STATUS_SUCCESS;
931     // prevent discarding metadata
932     Vcb->VCBFlags |= UDF_VCB_ASSUME_ALL_USED;
933     if(Vcb->CDR_Mode) {
934         // flush internal cache
935         if(WCacheGetWriteBlockCount__(&(Vcb->FastCache)) >= (Vcb->WriteBlockSize >> Vcb->BlockSizeBits) )
936             WCacheFlushAll__(&(Vcb->FastCache), Vcb);
937         // record VAT
938         return UDFRecordVAT(Vcb);
939     }
940 
941     UDFFlushAllCachedAllocations(Vcb, UDF_PREALLOC_CLASS_FE);
942     UDFFlushAllCachedAllocations(Vcb, UDF_PREALLOC_CLASS_DIR);
943 
944     if(Vcb->VerifyOnWrite) {
945         UDFPrint(("UDF: Flushing cache for verify\n"));
946         //WCacheFlushAll__(&(Vcb->FastCache), Vcb);
947         WCacheFlushBlocks__(&(Vcb->FastCache), Vcb, 0, Vcb->LastLBA);
948         UDFVFlush(Vcb);
949     }
950 
951     // synchronize BAD Block bitmap and NonAllocatable
952     UDFUpdateNonAllocated(Vcb);
953 
954     UDFAcquireResourceExclusive(&(Vcb->BitMapResource1),TRUE);
955 
956     // RAM mode
957 #ifdef UDF_DBG
958     if(!OS_SUCCESS(UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr, &(Vcb->VolIdent))))
959         UDFPrint(("Error updating VolIdent (1)\n"));
960     if(!OS_SUCCESS(UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr2, &(Vcb->VolIdent))))
961         UDFPrint(("Error updating VolIdent (2)\n"));
962 #else
963     UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr, &(Vcb->VolIdent));
964     UDFUpdateVolIdent(Vcb, Vcb->PVolDescAddr2, &(Vcb->VolIdent));
965 #endif // UDF_DBG
966 
967     UDF_CHECK_BITMAP_RESOURCE(Vcb);
968     // check if we should update BM
969     if(Vcb->FSBM_ByteCount == RtlCompareMemory(Vcb->FSBM_Bitmap, Vcb->FSBM_OldBitmap, Vcb->FSBM_ByteCount)) {
970         flags &= ~1;
971     } else {
972         flags |= 1;
973     }
974 
975 #ifdef UDF_DBG
976     if(!OS_SUCCESS(UDFUpdateVDS(Vcb, Vcb->VDS1, Vcb->VDS1 + Vcb->VDS1_Len, flags)))
977         UDFPrint(("Error updating Main VDS\n"));
978     if(!OS_SUCCESS(UDFUpdateVDS(Vcb, Vcb->VDS2, Vcb->VDS2 + Vcb->VDS2_Len, flags)))
979         UDFPrint(("Error updating Reserve VDS\n"));
980 #else
981     UDFUpdateVDS(Vcb, Vcb->VDS1, Vcb->VDS1 + Vcb->VDS1_Len, flags);
982     UDFUpdateVDS(Vcb, Vcb->VDS2, Vcb->VDS2 + Vcb->VDS2_Len, flags);
983 #endif // UDF_DBG
984 
985     // Update Integrity Desc if any
986     if(Vcb->LVid && Vcb->origIntegrityType == INTEGRITY_TYPE_CLOSE) {
987         UDFUpdateLogicalVolInt(Vcb, TRUE);
988     }
989 
990     if(flags & 1)
991         RtlCopyMemory(Vcb->FSBM_OldBitmap, Vcb->FSBM_Bitmap, Vcb->FSBM_ByteCount);
992 
993 //skip_update_bitmap:
994 
995     Vcb->VCBFlags &= ~UDF_VCB_ASSUME_ALL_USED;
996 
997     UDFReleaseResource(&(Vcb->BitMapResource1));
998 #endif //UDF_READ_ONLY_BUILD
999 
1000     return STATUS_SUCCESS;
1001 } // end UDFUmount__()
1002 
1003 /*************************************************************************/
1004 
1005 /*
1006     Find an anchor volume descriptor.
1007     The UDFGetDiskInfoAndVerify() will invoke this routine to find & check
1008     Anchor Volume Descriptors on the target device
1009 */
1010 lba_t
1011 UDFFindAnchor(
1012     PVCB           Vcb           // Volume control block
1013     )
1014 {
1015 //    OSSTATUS    RC = STATUS_SUCCESS;
1016 
1017     uint16 ident;
1018     uint32 i;
1019     uint32 LastBlock;
1020     OSSTATUS status;
1021     int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
1022     BOOLEAN MRW_candidate;
1023     BOOLEAN IsMRW = (Vcb->MRWStatus != 0);
1024     if(!Buf)
1025         return 0;
1026 
1027     UDFPrint(("UDFFindAnchor\n"));
1028     // init probable locations...
1029     RtlZeroMemory(&(Vcb->Anchor), sizeof(Vcb->Anchor));
1030     Vcb->Anchor[0] = 256 + Vcb->FirstLBALastSes;
1031     Vcb->Anchor[1] = 512 + Vcb->FirstLBALastSes;
1032     Vcb->Anchor[2] = 256 + Vcb->TrackMap[Vcb->LastTrackNum].FirstLba;
1033     Vcb->Anchor[3] = 512 + Vcb->TrackMap[Vcb->LastTrackNum].FirstLba;
1034     Vcb->Anchor[4] = Vcb->LastLBA - 256;
1035     Vcb->Anchor[5] = Vcb->LastLBA - 256 + 1;
1036     Vcb->Anchor[6] = Vcb->LastLBA - 256 - 2;
1037     // vat locations
1038     Vcb->Anchor[7] = Vcb->LastLBA - 2;
1039     Vcb->Anchor[8] = Vcb->LastLBA;
1040     Vcb->Anchor[9] = Vcb->LastLBA - 512;
1041 //    Vcb->Anchor[7] = Vcb->LastLBA - 256 - 7;
1042 //    Vcb->Anchor[8] = Vcb->LastLBA - 512 - 2;
1043 //    Vcb->Anchor[9] = Vcb->LastLBA - 512 - 7;
1044 
1045     LastBlock = 0;
1046     // ... and check them
1047     for (i=0; i<sizeof(Vcb->Anchor)/sizeof(int); i++) {
1048         if(Vcb->Anchor[i] > Vcb->LastLBA)
1049             Vcb->Anchor[i] = 0;
1050         MRW_candidate = FALSE;
1051         if(Vcb->Anchor[i]) {
1052             UDFPrint(("check Anchor %x\n", Vcb->Anchor[i]));
1053             if(!OS_SUCCESS(status = UDFReadTagged(Vcb,Buf,
1054                 Vcb->Anchor[i], Vcb->Anchor[i], &ident))) {
1055 
1056                 // Fucking MRW...
1057                 if(!IsMRW && (i<2) &&
1058                    (Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM)) {
1059                     if(OS_SUCCESS(status = UDFReadTagged(Vcb,Buf,
1060                         Vcb->Anchor[i]+MRW_DMA_OFFSET, Vcb->Anchor[i], &ident))) {
1061                         // do MRW workaround.....
1062                         UDFPrint(("UDF: looks like we have MRW....\n"));
1063                         MRW_candidate = TRUE;
1064                         goto MRW_workaround;
1065                     }
1066                 }
1067 
1068                 Vcb->Anchor[i] = 0;
1069                 if(status == STATUS_NONEXISTENT_SECTOR) {
1070                     UDFPrint(("UDF: disk seems to be incomplete\n"));
1071                     break;
1072                 }
1073             } else {
1074 MRW_workaround:
1075                 if((ident != TID_ANCHOR_VOL_DESC_PTR) && ((i<6) ||
1076                     (ident != TID_FILE_ENTRY && ident != TID_EXTENDED_FILE_ENTRY))) {
1077                     Vcb->Anchor[i] = 0;
1078                 } else {
1079                     UDFPrint(("UDF: Found AVD at %x (point %d)\n",Vcb->Anchor[i], i));
1080                     if(!LastBlock)
1081                         LastBlock = Vcb->LastLBA;
1082                     if(MRW_candidate) {
1083                         UDFPrint(("UDF: looks like we _*really*_ have MRW....\n"));
1084                         IsMRW = TRUE;
1085                         ASSERT(Vcb->LastReadTrack == 1);
1086                         Vcb->TrackMap[Vcb->LastReadTrack].Flags |= TrackMap_FixMRWAddressing;
1087                         WCachePurgeAll__(&(Vcb->FastCache), Vcb);
1088                         UDFPrint(("UDF: MRW on non-MRW drive => ReadOnly"));
1089                         Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
1090 
1091                         UDFRegisterFsStructure(Vcb, Vcb->Anchor[i], Vcb->BlockSize);
1092 
1093                     }
1094                 }
1095             }
1096         }
1097     }
1098 
1099     UDFPrint(("UDF: -----------------\nUDF: Last block %x\n",LastBlock));
1100     MyFreePool__(Buf);
1101     return LastBlock;
1102 } // end UDFFindAnchor()
1103 
1104 /*
1105     Look for Volume recognition sequence
1106  */
1107 uint32
1108 UDFFindVRS(
1109     PVCB           Vcb
1110     )
1111 {
1112     VolStructDesc  *vsd = NULL;
1113     uint32       offset;
1114     uint32       retStat = 0;
1115     uint32       BeginOffset = Vcb->FirstLBA;
1116     OSSTATUS     RC;
1117     int8*        buffer = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
1118     SIZE_T       ReadBytes;
1119 
1120     if(!buffer) return 0;
1121     // Relative to First LBA in Last Session
1122     offset = Vcb->FirstLBA + 0x10;
1123 
1124     UDFPrint(("UDFFindVRS:\n"));
1125 
1126     // Process the sequence (if applicable)
1127     for (;(offset-BeginOffset <=0x20); offset ++) {
1128         // Read a block
1129         RC = UDFReadSectors(Vcb, FALSE, offset, 1, FALSE, buffer, &ReadBytes);
1130         if(!OS_SUCCESS(RC)) continue;
1131 
1132         // Look for ISO descriptors
1133         vsd = (VolStructDesc *)(buffer);
1134 
1135         if(vsd->stdIdent[0]) {
1136             if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_CD001, STD_ID_LEN))
1137             {
1138                 retStat |= VRS_ISO9660_FOUND;
1139                 switch (vsd->structType)
1140                 {
1141                     case 0:
1142                         UDFPrint(("UDF: ISO9660 Boot Record found\n"));
1143                         break;
1144                     case 1:
1145                         UDFPrint(("UDF: ISO9660 Primary Volume Descriptor found\n"));
1146                         break;
1147                     case 2:
1148                         UDFPrint(("UDF: ISO9660 Supplementary Volume Descriptor found\n"));
1149                         break;
1150                     case 3:
1151                         UDFPrint(("UDF: ISO9660 Volume Partition Descriptor found\n"));
1152                         break;
1153                     case 255:
1154                         UDFPrint(("UDF: ISO9660 Volume Descriptor Set Terminator found\n"));
1155                         break;
1156                     default:
1157                         UDFPrint(("UDF: ISO9660 VRS (%u) found\n", vsd->structType));
1158                         break;
1159                 }
1160             }
1161             else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_BEA01, STD_ID_LEN))
1162             {
1163                 UDFPrint(("UDF: BEA01 Found\n"));
1164             }
1165             else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_TEA01, STD_ID_LEN))
1166             {
1167                 UDFPrint(("UDF: TEA01 Found\n"));
1168                 break;
1169             }
1170             else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_NSR02, STD_ID_LEN))
1171             {
1172                 retStat |= VRS_NSR02_FOUND;
1173                 UDFPrint(("UDF: NSR02 Found\n"));
1174                 break;
1175             }
1176             else if(!strncmp((int8*)(&vsd->stdIdent), STD_ID_NSR03, STD_ID_LEN))
1177             {
1178                 retStat |= VRS_NSR03_FOUND;
1179                 UDFPrint(("UDF: NSR03 Found\n"));
1180                 break;
1181             }
1182         }
1183     }
1184 
1185     MyFreePool__(buffer);
1186 
1187     return retStat;
1188 } // end UDFFindVRS()
1189 
1190 /*
1191     process Primary volume descriptor
1192  */
1193 void
1194 UDFLoadPVolDesc(
1195     PVCB Vcb,
1196     int8* Buf // pointer to buffer containing PVD
1197     )
1198 {
1199     PrimaryVolDesc *pvoldesc;
1200 //    OSSTATUS    RC = STATUS_SUCCESS;
1201 
1202     pvoldesc = (PrimaryVolDesc *)Buf;
1203     UDFPrint(("UDF: PrimaryVolDesc:\n"));
1204     UDFPrint(("volDescSeqNum     = %d\n", pvoldesc->volDescSeqNum));
1205     UDFPrint(("primaryVolDescNum = %d\n", pvoldesc->primaryVolDescNum));
1206     // remember recording time...
1207     Vcb->VolCreationTime = UDFTimeToNT(&(pvoldesc->recordingDateAndTime));
1208     // ...VolIdent...
1209 #define CUR_IDENT_SZ (sizeof(pvoldesc->volIdent))
1210     if (Vcb->VolIdent.Buffer) {
1211         MyFreePool__(Vcb->VolIdent.Buffer);
1212     }
1213     UDFGetDstring(&(Vcb->VolIdent), (dstring*)&(pvoldesc->volIdent), CUR_IDENT_SZ);
1214 #undef CUR_IDENT_SZ
1215     UDFPrint(("volIdent[] = '%ws'\n", Vcb->VolIdent.Buffer));
1216 #ifdef UDF_DBG
1217     UDFPrint(("volSeqNum         = %d\n", pvoldesc->volSeqNum));
1218     UDFPrint(("maxVolSeqNum      = %d\n", pvoldesc->maxVolSeqNum));
1219     UDFPrint(("interchangeLvl    = %d\n", pvoldesc->interchangeLvl));
1220     UDFPrint(("maxInterchangeLvl = %d\n", pvoldesc->maxInterchangeLvl));
1221     UDFPrint(("charSetList       = %d\n", pvoldesc->charSetList));
1222     UDFPrint(("maxCharSetList    = %d\n", pvoldesc->maxCharSetList));
1223     // ...& just print VolSetIdent
1224     UNICODE_STRING      instr;
1225 #define CUR_IDENT_SZ (sizeof(pvoldesc->volSetIdent))
1226     UDFGetDstring(&instr, (dstring*)&(pvoldesc->volSetIdent), CUR_IDENT_SZ);
1227 #undef CUR_IDENT_SZ
1228     UDFPrint(("volSetIdent[] = '%ws'\n", instr.Buffer));
1229 //    UDFPrint(("maxInterchangeLvl = %d\n", pvoldesc->maxInterchangeLvl));
1230     UDFPrint(("flags             = %x\n", pvoldesc->flags));
1231     if(instr.Buffer) MyFreePool__(instr.Buffer);
1232 #endif // UDF_DBG
1233 } // end UDFLoadPVolDesc()
1234 
1235 /*
1236    load Logical volume integrity descriptor
1237  */
1238 OSSTATUS
1239 UDFLoadLogicalVolInt(
1240     PDEVICE_OBJECT  DeviceObject,
1241     PVCB            Vcb,
1242     extent_ad       loc
1243     )
1244 {
1245     OSSTATUS    RC = STATUS_SUCCESS;
1246     uint32      len;
1247     SIZE_T      _ReadBytes;
1248     int8*       Buf = NULL;
1249     uint16      ident;
1250     LogicalVolIntegrityDescImpUse* LVID_iUse;
1251     LogicalVolHeaderDesc* LVID_hd;
1252     extent_ad   last_loc;
1253     BOOLEAN     read_last = FALSE;
1254     uint32      lvid_count = 0;
1255 
1256     ASSERT(!Vcb->LVid);
1257     if(Vcb->LVid) {
1258         MyFreePool__(Vcb->LVid);
1259         Vcb->LVid = NULL;
1260     }
1261     // walk through all sectors inside LogicalVolumeIntegrityDesc
1262     while(loc.extLength) {
1263         UDFPrint(("UDF: Reading LVID @%x (%x)\n", loc.extLocation, loc.extLength));
1264         len = max(loc.extLength, Vcb->BlockSize);
1265         Buf = (int8*)MyAllocatePool__(NonPagedPool,len);
1266         if(!Buf)
1267             return STATUS_INSUFFICIENT_RESOURCES;
1268         RC = UDFReadTagged(Vcb,Buf, loc.extLocation, loc.extLocation, &ident);
1269         if(!OS_SUCCESS(RC)) {
1270 exit_with_err:
1271             UDFPrint(("UDF: Reading LVID @%x (%x) failed.\n", loc.extLocation, loc.extLength));
1272             switch(Vcb->PartitialDamagedVolumeAction) {
1273             case UDF_PART_DAMAGED_RO:
1274                 UDFPrint(("UDF: Switch to r/o mode.\n"));
1275                 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
1276                 Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_MEDIA_DEFECT_RO;
1277                 RC = STATUS_SUCCESS;
1278                 break;
1279             case UDF_PART_DAMAGED_NO:
1280                 UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
1281                 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
1282                 //RC = STATUS_WRONG_VOLUME;
1283                 break;
1284             case UDF_PART_DAMAGED_RW:
1285             default:
1286                 UDFPrint(("UDF: Keep r/w mode for your own risk.\n"));
1287                 RC = STATUS_SUCCESS;
1288                 // asume we have INTEGRITY_TYPE_CLOSE
1289                 Vcb->IntegrityType = INTEGRITY_TYPE_CLOSE;
1290                 break;
1291             }
1292 
1293             MyFreePool__(Buf);
1294             return RC;
1295         }
1296         UDFRegisterFsStructure(Vcb, loc.extLocation, len);
1297         // handle Terminal Entry
1298         if(ident == TID_TERMINAL_ENTRY) {
1299             read_last = TRUE;
1300             MyFreePool__(Buf);
1301             Vcb->LVid = NULL;
1302             loc = last_loc;
1303             continue;
1304         } else
1305         if(ident != TID_LOGICAL_VOL_INTEGRITY_DESC) {
1306             RC = STATUS_DISK_CORRUPT_ERROR;
1307             goto exit_with_err;
1308         }
1309 
1310         Vcb->LVid = (LogicalVolIntegrityDesc *)Buf;
1311         RC = UDFReadData(Vcb, TRUE, ((uint64)(loc.extLocation)) << Vcb->BlockSizeBits, len, FALSE, Buf, &_ReadBytes);
1312         // update info
1313         if( !read_last &&
1314             Vcb->LVid->nextIntegrityExt.extLength) {
1315             // go to next LVID
1316             last_loc = loc;
1317             loc = Vcb->LVid->nextIntegrityExt;
1318             Vcb->LVid = NULL;
1319             lvid_count++;
1320             if(lvid_count > UDF_MAX_LVID_CHAIN_LENGTH) {
1321                 RC = STATUS_DISK_CORRUPT_ERROR;
1322                 goto exit_with_err;
1323             }
1324             MyFreePool__(Buf);
1325             continue;
1326         }
1327         // process last LVID
1328         Vcb->origIntegrityType =
1329             Vcb->IntegrityType = Vcb->LVid->integrityType;
1330         Vcb->LVid_loc = loc;
1331 
1332         LVID_iUse = UDFGetLVIDiUse(Vcb);
1333 
1334         UDFPrint(("UDF: Last LVID:\n"));
1335         UDFPrint(("     minR: %x\n",LVID_iUse->minUDFReadRev ));
1336         UDFPrint(("     minW: %x\n",LVID_iUse->minUDFWriteRev));
1337         UDFPrint(("     maxW: %x\n",LVID_iUse->maxUDFWriteRev));
1338         UDFPrint(("     Type: %s\n",!Vcb->IntegrityType ? "Open" : "Close"));
1339 
1340         Vcb->minUDFReadRev  = LVID_iUse->minUDFReadRev;
1341         Vcb->minUDFWriteRev = LVID_iUse->minUDFWriteRev;
1342         Vcb->maxUDFWriteRev = LVID_iUse->maxUDFWriteRev;
1343 
1344         Vcb->numFiles = LVID_iUse->numFiles;
1345         Vcb->numDirs  = LVID_iUse->numDirs;
1346         UDFPrint(("     nFiles: %x\n",Vcb->numFiles ));
1347         UDFPrint(("     nDirs: %x\n",Vcb->numDirs ));
1348 
1349         // Check if we can understand this format
1350         if(Vcb->minUDFReadRev > UDF_MAX_READ_REVISION)
1351             RC = STATUS_UNRECOGNIZED_VOLUME;
1352         // Check if we know how to write here
1353         if(Vcb->minUDFWriteRev > UDF_MAX_WRITE_REVISION) {
1354             UDFPrint(("     Target FS requires: %x Revision => ReadOnly\n",Vcb->minUDFWriteRev));
1355             Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
1356             Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_NEW_FS_RO;
1357         }
1358 
1359         LVID_hd = (LogicalVolHeaderDesc*)&(Vcb->LVid->logicalVolContentsUse);
1360         Vcb->NextUniqueId = LVID_hd->uniqueID;
1361         UDFPrint(("     Next FID: %x\n",Vcb->NextUniqueId));
1362 
1363         break;
1364     }
1365 
1366     return RC;
1367 } // end UDFLoadLogicalVolInt()
1368 
1369 
1370 /*
1371     load Logical volume descriptor
1372  */
1373 OSSTATUS
1374 UDFLoadLogicalVol(
1375     PDEVICE_OBJECT  DeviceObject,
1376     PVCB            Vcb,
1377     int8*           Buf,
1378     lb_addr         *fileset
1379     )
1380 {
1381     LogicalVolDesc *lvd = (LogicalVolDesc *)Buf;
1382     uint16 i, offset;
1383     uint8 type;
1384     OSSTATUS status = STATUS_SUCCESS;
1385     UDFPrint(("UDF: LogicalVolDesc\n"));
1386     // Validate partition map counter
1387     if(!(Vcb->Partitions)) {
1388         Vcb->PartitionMaps = lvd->numPartitionMaps;
1389         Vcb->Partitions = (PUDFPartMap)MyAllocatePool__(NonPagedPool, sizeof(UDFPartMap) * Vcb->PartitionMaps );
1390         if(!Vcb->Partitions)
1391             return STATUS_INSUFFICIENT_RESOURCES;
1392     } else {
1393         if(Vcb->PartitionMaps != lvd->numPartitionMaps)
1394             return STATUS_DISK_CORRUPT_ERROR;
1395     }
1396     UDFPrint(("UDF: volDescSeqNum = %x\n", lvd->volDescSeqNum));
1397     // Get logical block size (may be different from physical)
1398     Vcb->LBlockSize = lvd->logicalBlockSize;
1399     // Get current UDF revision
1400     // Get Read-Only flags
1401     UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent));
1402 
1403     if(Vcb->LBlockSize < Vcb->BlockSize)
1404         return STATUS_DISK_CORRUPT_ERROR;
1405     switch(Vcb->LBlockSize) {
1406     case 512: Vcb->LBlockSizeBits = 9; break;
1407     case 1024: Vcb->LBlockSizeBits = 10; break;
1408     case 2048: Vcb->LBlockSizeBits = 11; break;
1409     case 4096: Vcb->LBlockSizeBits = 12; break;
1410     case 8192: Vcb->LBlockSizeBits = 13; break;
1411     case 16384: Vcb->LBlockSizeBits = 14; break;
1412     case 32768: Vcb->LBlockSizeBits = 15; break;
1413     case 65536: Vcb->LBlockSizeBits = 16; break;
1414     default:
1415         UDFPrint(("UDF: Bad block size (%ld)\n", Vcb->LBlockSize));
1416         return STATUS_DISK_CORRUPT_ERROR;
1417     }
1418     UDFPrint(("UDF: logical block size (%ld)\n", Vcb->LBlockSize));
1419     Vcb->LB2B_Bits = Vcb->LBlockSizeBits - Vcb->BlockSizeBits;
1420     UDFPrint(("UDF: mapTableLength = %x\n", lvd->mapTableLength));
1421     UDFPrint(("UDF: numPartitionMaps = %x\n", lvd->numPartitionMaps));
1422     // walk through all available part maps
1423     for (i=0,offset=0;
1424          i<Vcb->PartitionMaps && offset<lvd->mapTableLength;
1425          i++,offset+=((GenericPartitionMap *)( ((uint8*)(lvd+1))+offset) )->partitionMapLength)
1426     {
1427         GenericPartitionMap* gpm = (GenericPartitionMap *)(((uint8*)(lvd+1))+offset);
1428         type = gpm->partitionMapType;
1429         UDFPrint(("Partition (%d) type %x, len %x\n", i, type, gpm->partitionMapLength));
1430         if(type == PARTITION_MAP_TYPE_1)
1431         {
1432             GenericPartitionMap1 *gpm1 = (GenericPartitionMap1 *)(((uint8*)(lvd+1))+offset);
1433 
1434             Vcb->Partitions[i].PartitionType = UDF_TYPE1_MAP15;
1435             Vcb->Partitions[i].VolumeSeqNum = gpm1->volSeqNum;
1436             Vcb->Partitions[i].PartitionNum = gpm1->partitionNum;
1437             status = STATUS_SUCCESS;
1438         }
1439         else if(type == PARTITION_MAP_TYPE_2)
1440         {
1441             UdfPartitionMap2* upm2 = (UdfPartitionMap2 *)(((uint8*)(lvd+1))+offset);
1442             if(!strncmp((int8*)&(upm2->partIdent.ident), UDF_ID_VIRTUAL, strlen(UDF_ID_VIRTUAL)))
1443             {
1444                 UDFIdentSuffix* udfis =
1445                     (UDFIdentSuffix*)&(upm2->partIdent.identSuffix);
1446 
1447                 if( (udfis->currentRev == 0x0150)/* ||
1448                     (Vcb->CurrentUDFRev == 0x0150)*/ ) {
1449                     UDFPrint(("Found VAT 1.50\n"));
1450                     Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP15;
1451                 } else
1452                 if( (udfis->currentRev == 0x0200) ||
1453                     (udfis->currentRev == 0x0201) /*||
1454                     (Vcb->CurrentUDFRev == 0x0200) ||
1455                     (Vcb->CurrentUDFRev == 0x0201)*/ ) {
1456                     UDFPrint(("Found VAT 2.00\n"));
1457                     Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP20;
1458                 }
1459                 status = STATUS_SUCCESS;
1460             }
1461             else if(!strncmp((int8*)&(upm2->partIdent.ident), UDF_ID_SPARABLE, strlen(UDF_ID_SPARABLE)))
1462             {
1463                 UDFPrint(("Load sparing table\n"));
1464                 PSPARABLE_PARTITION_MAP spm = (PSPARABLE_PARTITION_MAP)(((uint8*)(lvd+1))+offset);
1465                 Vcb->Partitions[i].PartitionType = UDF_SPARABLE_MAP15;
1466                 status = UDFLoadSparingTable(Vcb, spm);
1467             }
1468             else if(!strncmp((int8*)&(upm2->partIdent.ident), UDF_ID_METADATA, strlen(UDF_ID_METADATA)))
1469             {
1470                 UDFPrint(("Found metadata partition\n"));
1471 //                PMETADATA_PARTITION_MAP mpm = (PMETADATA_PARTITION_MAP)(((uint8*)(lvd+1))+offset);
1472                 Vcb->Partitions[i].PartitionType = UDF_METADATA_MAP25;
1473                 //status = UDFLoadSparingTable(Vcb, spm);
1474             }
1475             else
1476             {
1477                 UDFPrint(("Unknown ident: %s\n", upm2->partIdent.ident));
1478                 continue;
1479             }
1480             Vcb->Partitions[i].VolumeSeqNum = upm2->volSeqNum;
1481             Vcb->Partitions[i].PartitionNum = upm2->partitionNum;
1482         }
1483     }
1484 
1485     if(fileset) {
1486         // remember FileSet location
1487         long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
1488         *fileset = (la->extLocation);
1489         UDFPrint(("FileSet found in LogicalVolDesc at block=%x, partition=%d\n",
1490             fileset->logicalBlockNum,
1491             fileset->partitionReferenceNum));
1492     }
1493     if(OS_SUCCESS(status)) {
1494         // load Integrity Desc if any
1495         if(lvd->integritySeqExt.extLength)
1496             status = UDFLoadLogicalVolInt(DeviceObject,Vcb,lvd->integritySeqExt);
1497     }
1498     return status;
1499 } // end UDFLoadLogicalVol()
1500 
1501 OSSTATUS
1502 UDFLoadBogusLogicalVol(
1503     PDEVICE_OBJECT  DeviceObject,
1504     PVCB            Vcb,
1505     int8*           Buf,
1506     lb_addr         *fileset
1507     )
1508 {
1509 //    LogicalVolDesc *lvd = (LogicalVolDesc *)Buf;
1510     UDFPrint(("UDF: Bogus LogicalVolDesc\n"));
1511     // Validate partition map counter
1512     if(!(Vcb->Partitions)) {
1513         Vcb->PartitionMaps = 1;
1514         Vcb->Partitions = (PUDFPartMap)MyAllocatePool__(NonPagedPool, sizeof(UDFPartMap) * Vcb->PartitionMaps );
1515         if(!Vcb->Partitions)
1516             return STATUS_INSUFFICIENT_RESOURCES;
1517     } else {
1518         if(Vcb->PartitionMaps != 1)
1519             return STATUS_DISK_CORRUPT_ERROR;
1520     }
1521     UDFPrint(("UDF: volDescSeqNum = %x\n", 0));
1522     // Get logical block size (may be different from physical)
1523     Vcb->LBlockSize = 2048;
1524     // Get current UDF revision
1525     // Get Read-Only flags
1526 //    UDFReadEntityID_Domain(Vcb, &(lvd->domainIdent));
1527 
1528     if(Vcb->LBlockSize < Vcb->BlockSize)
1529         return STATUS_DISK_CORRUPT_ERROR;
1530     Vcb->LBlockSizeBits = 11;
1531     UDFPrint(("UDF: logical block size (%ld)\n", Vcb->LBlockSize));
1532     Vcb->LB2B_Bits = Vcb->LBlockSizeBits - Vcb->BlockSizeBits;
1533     UDFPrint(("UDF: mapTableLength = %x\n", 0));
1534     UDFPrint(("UDF: numPartitionMaps = %x\n", 0));
1535 
1536 // if(CDRW) {
1537 
1538     Vcb->Partitions[0].PartitionType = UDF_TYPE1_MAP15;
1539     Vcb->Partitions[0].VolumeSeqNum = 0;
1540     Vcb->Partitions[0].PartitionNum = 0;
1541 
1542 /* } else if(CDR)
1543                 if()
1544                     UDFPrint(("Found VAT 1.50\n"));
1545                     Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP15;
1546                 } else
1547                     UDFPrint(("Found VAT 2.00\n"));
1548                     Vcb->Partitions[i].PartitionType = UDF_VIRTUAL_MAP20;
1549                 }
1550             }
1551     }
1552 */
1553     if(fileset) {
1554         // remember FileSet location
1555 //        long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]);
1556         fileset->logicalBlockNum = 0;
1557         fileset->partitionReferenceNum = 0;
1558         UDFPrint(("FileSet found in LogicalVolDesc at block=%x, partition=%d\n",
1559             fileset->logicalBlockNum,
1560             fileset->partitionReferenceNum));
1561     }
1562     return STATUS_SUCCESS;
1563 } // end UDFLoadBogusLogicalVol()
1564 
1565 /*
1566     This routine adds given Bitmap to existing one
1567  */
1568 OSSTATUS
1569 UDFAddXSpaceBitmap(
1570     IN PVCB Vcb,
1571     IN uint32 PartNum,
1572     IN PSHORT_AD bm,
1573     IN ULONG bm_type
1574     )
1575 {
1576     int8* tmp;
1577     int8* tmp_bm;
1578     uint32 i, lim, j, lba, l, lim2, l2, k;
1579     lb_addr locAddr;
1580     OSSTATUS status;
1581     uint16 Ident;
1582     uint32 flags;
1583     SIZE_T Length;
1584     SIZE_T ReadBytes;
1585     BOOLEAN bit_set;
1586 
1587     UDF_CHECK_BITMAP_RESOURCE(Vcb);
1588     UDFPrint(("UDFAddXSpaceBitmap: at block=%x, partition=%d\n",
1589         bm->extPosition,
1590         PartNum));
1591 
1592     if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1593     i=UDFPartStart(Vcb, PartNum);
1594     flags = bm->extLength >> 30;
1595     if(!flags /*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) {
1596         tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->BlockSize));
1597         if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1598         locAddr.partitionReferenceNum = (uint16)PartNum;
1599         locAddr.logicalBlockNum = bm->extPosition;
1600         // read header of the Bitmap
1601         if(!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, lba = UDFPartLbaToPhys(Vcb, &(locAddr)),
1602                              locAddr.logicalBlockNum, &Ident)) ) {
1603 err_addxsbm_1:
1604             DbgFreePool(tmp);
1605             return status;
1606         }
1607         if(Ident != TID_SPACE_BITMAP_DESC) {
1608             status = STATUS_DISK_CORRUPT_ERROR;
1609             goto err_addxsbm_1;
1610         }
1611         UDFRegisterFsStructure(Vcb, lba, Vcb->BlockSize);
1612         // read the whole Bitmap
1613         if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)lba)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes)))
1614             goto err_addxsbm_1;
1615         UDFRegisterFsStructure(Vcb, lba, Length);
1616         lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount);
1617         tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1618         j = 0;
1619         for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (i<lim);) {
1620             // expand LBlocks to Sectors...
1621             l2 = l << Vcb->LB2B_Bits;
1622             // ...and mark them
1623             if(bm_type == UDF_FSPACE_BM) {
1624                 bit_set = UDFGetFreeBit(tmp_bm, j);
1625                 for(k=0;(k<l2) && (i<lim);k++) {
1626                     if(bit_set) {
1627                         // FREE block
1628                         UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1629                         UDFSetFreeBitOwner(Vcb, i);
1630                         UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1631                     } else {
1632                         // USED block
1633                         UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1634                     }
1635                     i++;
1636                 }
1637             } else {
1638                 bit_set = UDFGetZeroBit(tmp_bm, j);
1639                 for(k=0;(k<l2) && (i<lim);k++) {
1640                     if(bit_set) {
1641                         // ZERO block
1642                         UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1643                     } else {
1644                         // DATA block
1645                         UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1646                     }
1647                     i++;
1648                 }
1649             }
1650             j += l;
1651         }
1652         DbgFreePool(tmp);
1653 /*    } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1654         i=Vcb->Partitions[PartNum].PartitionRoot;
1655         lim = i + Vcb->Partitions[PartNum].PartitionLen;
1656         for(;i<lim;i++) {
1657             UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1658         }*/
1659     }
1660     return STATUS_SUCCESS;
1661 } // end UDFAddXSpaceBitmap()
1662 
1663 /*
1664     This routine adds given Bitmap to existing one
1665  */
1666 OSSTATUS
1667 UDFVerifyXSpaceBitmap(
1668     IN PVCB Vcb,
1669     IN uint32 PartNum,
1670     IN PSHORT_AD bm,
1671     IN ULONG bm_type
1672     )
1673 {
1674     int8* tmp;
1675 //    int8* tmp_bm;
1676 //    uint32 i, l2, k, lim, j, lim2;
1677     uint32 lba;
1678     lb_addr locAddr;
1679     OSSTATUS status;
1680     uint16 Ident;
1681     uint32 flags;
1682     uint32 Length;
1683     SIZE_T ReadBytes;
1684 //    BOOLEAN bit_set;
1685 
1686     UDF_CHECK_BITMAP_RESOURCE(Vcb);
1687 
1688     UDFPrint((" UDFVerifyXSpaceBitmap: part %x\n", PartNum));
1689 
1690     if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1691 //    i=UDFPartStart(Vcb, PartNum);
1692     flags = bm->extLength >> 30;
1693     if(!flags /*|| flags == EXTENT_NOT_RECORDED_ALLOCATED*/) {
1694         tmp = (int8*)DbgAllocatePool(NonPagedPool, max(Length, Vcb->BlockSize));
1695         if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1696         locAddr.partitionReferenceNum = (uint16)PartNum;
1697         locAddr.logicalBlockNum = bm->extPosition;
1698         // read header of the Bitmap
1699         if(!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, lba = UDFPartLbaToPhys(Vcb, &(locAddr)),
1700                              locAddr.logicalBlockNum, &Ident)) ) {
1701 err_vfyxsbm_1:
1702             DbgFreePool(tmp);
1703             return status;
1704         }
1705         UDFPrint((" BM Lba %x\n", lba));
1706         if(Ident != TID_SPACE_BITMAP_DESC) {
1707             status = STATUS_DISK_CORRUPT_ERROR;
1708             goto err_vfyxsbm_1;
1709         }
1710         // read the whole Bitmap
1711         if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)lba)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes)))
1712             goto err_vfyxsbm_1;
1713         UDFRegisterFsStructure(Vcb, lba, Length);
1714 //        lim = min(i + ((lim2 = ((PSPACE_BITMAP_DESC)tmp)->numOfBits) << Vcb->LB2B_Bits), Vcb->FSBM_BitCount);
1715 //        tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1716 //        j = 0;
1717 /*        for(;(l = UDFGetBitmapLen((uint32*)tmp_bm, j, lim2)) && (i<lim);) {
1718             // expand LBlocks to Sectors...
1719             l2 = l << Vcb->LB2B_Bits;
1720             // ...and mark them
1721             if(bm_type == UDF_FSPACE_BM) {
1722                 bit_set = UDFGetFreeBit(tmp_bm, j);
1723                 for(k=0;(k<l2) && (i<lim);k++) {
1724                     if(bit_set) {
1725                         // FREE block
1726                         UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1727                         UDFSetFreeBitOwner(Vcb, i);
1728                         UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1729                     } else {
1730                         // USED block
1731                         UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1732                     }
1733                     i++;
1734                 }
1735             } else {
1736                 bit_set = UDFGetZeroBit(tmp_bm, j);
1737                 for(k=0;(k<l2) && (i<lim);k++) {
1738                     if(bit_set) {
1739                         // ZERO block
1740                         UDFSetZeroBit(Vcb->ZSBM_Bitmap, i);
1741                     } else {
1742                         // DATA block
1743                         UDFClrZeroBit(Vcb->ZSBM_Bitmap, i);
1744                     }
1745                     i++;
1746                 }
1747             }
1748             j += l;
1749         }*/
1750         DbgFreePool(tmp);
1751 /*    } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1752         i=Vcb->Partitions[PartNum].PartitionRoot;
1753         lim = i + Vcb->Partitions[PartNum].PartitionLen;
1754         for(;i<lim;i++) {
1755             UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1756         }*/
1757     }
1758     return STATUS_SUCCESS;
1759 } // end UDFVerifyXSpaceBitmap()
1760 
1761 /*
1762     This routine subtracts given Bitmap to existing one
1763  */
1764 /*OSSTATUS
1765 UDFDelXSpaceBitmap(
1766     IN PVCB Vcb,
1767     IN uint32 PartNum,
1768     IN PSHORT_AD bm
1769     )
1770 {
1771     int8* tmp, tmp_bm;
1772     uint32 i, lim, j;
1773     lb_addr locAddr;
1774     OSSTATUS status;
1775     uint16 Ident;
1776     uint32 flags;
1777     uint32 Length;
1778     SIZE_T ReadBytes;
1779 
1780     if(!(Length = (bm->extLength & UDF_EXTENT_LENGTH_MASK))) return STATUS_SUCCESS;
1781     i=0;
1782     flags = bm->extLength >> 30;
1783     if(!flags || flags == EXTENT_NOT_RECORDED_ALLOCATED) {
1784         tmp = (int8*)MyAllocatePool__(NonPagedPool, Length);
1785         if(!tmp) return STATUS_INSUFFICIENT_RESOURCES;
1786         locAddr.partitionReferenceNum = (uint16)PartNum;
1787         locAddr.logicalBlockNum = bm->extPosition;
1788         if((!OS_SUCCESS(status = UDFReadTagged(Vcb, tmp, (j = UDFPartLbaToPhys(Vcb, &(locAddr))),
1789                              locAddr.logicalBlockNum, &Ident))) ||
1790            (Ident != TID_SPACE_BITMAP_DESC) ) {
1791             MyFreePool__(tmp);
1792             return status;
1793         }
1794         if(!OS_SUCCESS(status = UDFReadData(Vcb, FALSE, ((uint64)j)<<Vcb->BlockSizeBits, Length, FALSE, tmp, &ReadBytes))) {
1795             MyFreePool__(tmp);
1796             return status;
1797         }
1798         lim = i + ((PSPACE_BITMAP_DESC)tmp)->numOfBits;
1799         tmp_bm = tmp + sizeof(SPACE_BITMAP_DESC);
1800         j = 0;
1801         for(;i<lim;i++) {
1802             if(UDFGetUsedBit(tmp_bm, j)) UDFSetFreeBit(Vcb->FSBM_Bitmap, i);
1803             j++;
1804         }
1805         MyFreePool__(tmp);
1806 //    } else if((bm->extLength >> 30) == EXTENT_NOT_RECORDED_ALLOCATED) {
1807 //        i=Vcb->Partitions[PartNum].PartitionRoot;
1808 //        lim = i + Vcb->Partitions[PartNum].PartitionLen;
1809 //        for(;i<lim;i++) {
1810 //            UDFSetUsedBit(Vcb->FSBM_Bitmap, i);
1811 //        }
1812     }
1813     return STATUS_SUCCESS;
1814 } // end UDFDelXSpaceBitmap()  */
1815 
1816 /*
1817     This routine verifues FreeSpaceBitmap (internal) according to media
1818     parameters & input data
1819  */
1820 OSSTATUS
1821 UDFVerifyFreeSpaceBitmap(
1822     IN PVCB Vcb,
1823     IN uint32 PartNdx,
1824     IN PPARTITION_HEADER_DESC phd, // partition header pointing to Bitmaps
1825     IN uint32 Lba                   // UnallocSpaceDesc
1826     )
1827 {
1828     OSSTATUS status;
1829     uint32 i, l;
1830     uint16 Ident;
1831     int8* AllocDesc;
1832     PEXTENT_MAP Extent;
1833     lb_addr locAddr;
1834     uint32 PartNum;
1835 
1836     PartNum = UDFGetPartNumByPartNdx(Vcb, PartNdx);
1837 
1838     UDFPrint(("UDFVerifyFreeSpaceBitmap:\n"));
1839     // read info for partition header (if any)
1840     if(phd) {
1841         // read unallocated Bitmap
1842         if(!OS_SUCCESS(status = UDFVerifyXSpaceBitmap(Vcb, PartNum, &(phd->unallocatedSpaceBitmap), UDF_FSPACE_BM)))
1843             return status;
1844         // read freed Bitmap
1845         if(!OS_SUCCESS(status = UDFVerifyXSpaceBitmap(Vcb, PartNum, &(phd->freedSpaceBitmap), UDF_ZSPACE_BM)))
1846             return status;
1847     }
1848     // read UnallocatedSpaceDesc & convert to Bitmap
1849     if(Lba) {
1850         UDFPrint((" Lba @%x\n", Lba));
1851         if(!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize + sizeof(EXTENT_AD) )))
1852             return STATUS_INSUFFICIENT_RESOURCES;
1853         RtlZeroMemory(((int8*)AllocDesc) + Vcb->LBlockSize, sizeof(EXTENT_AD));
1854         if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1855            !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, l = (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1856             MyFreePool__(AllocDesc);
1857             return status;
1858         }
1859         UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1860         RtlCopyMemory((int8*)Extent, AllocDesc+sizeof(UNALLOC_SPACE_DESC), (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) );
1861         locAddr.partitionReferenceNum = (uint16)PartNum;
1862         // read extent is recorded with relative addresses
1863         // so, we should convert it to suitable form
1864         for(i=0; Extent[i].extLength; i++) {
1865             locAddr.logicalBlockNum = Extent[i].extLocation;
1866             Extent[i].extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
1867             if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
1868                 BrutePoint();
1869                 MyFreePool__(AllocDesc);
1870                 return STATUS_DISK_CORRUPT_ERROR;
1871             }
1872             if((Extent[i].extLocation >> 30) == EXTENT_NEXT_EXTENT_ALLOCDESC) {
1873                 // load continuation
1874                 Lba = Extent[i].extLocation & UDF_EXTENT_LENGTH_MASK;
1875                 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1876                    !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1877                     MyFreePool__(AllocDesc);
1878                     return status;
1879                 }
1880                 if(Ident == TID_UNALLOC_SPACE_DESC) {
1881                     UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1882                     if(!(l = MyReallocPool__((int8*)Extent, l, (int8**)&Extent, i*sizeof(EXTENT_MAP)))) {
1883                         MyFreePool__(Extent);
1884                         MyFreePool__(AllocDesc);
1885                         return STATUS_INSUFFICIENT_RESOURCES;
1886                     }
1887                     Extent[i].extLength =
1888                     Extent[i].extLocation = 0;
1889                     Extent = UDFMergeMappings(Extent, (PEXTENT_MAP)(AllocDesc+sizeof(UNALLOC_SPACE_DESC)) );
1890 #ifdef UDF_DBG
1891                 } else {
1892                     UDFPrint(("Broken unallocated space descriptor sequence\n"));
1893 #endif // UDF_DBG
1894                 }
1895             }
1896         }
1897 //        UDFMarkSpaceAsXXX(Vcb, (-1), Extent, AS_USED); // mark as used
1898         MyFreePool__(Extent);
1899         MyFreePool__(AllocDesc);
1900         status = STATUS_SUCCESS;
1901     }
1902     return status;
1903 } // end UDFBuildFreeSpaceBitmap()
1904 
1905 /*
1906     This routine builds FreeSpaceBitmap (internal) according to media
1907     parameters & input data
1908  */
1909 OSSTATUS
1910 UDFBuildFreeSpaceBitmap(
1911     IN PVCB Vcb,
1912     IN uint32 PartNdx,
1913     IN PPARTITION_HEADER_DESC phd, // partition header pointing to Bitmaps
1914     IN uint32 Lba                   // UnallocSpaceDesc
1915     )
1916 {
1917     OSSTATUS status;
1918     uint32 i, l;
1919     uint16 Ident;
1920     int8* AllocDesc;
1921     PEXTENT_MAP Extent;
1922     lb_addr locAddr;
1923     uint32 PartNum;
1924 
1925     PartNum = UDFGetPartNumByPartNdx(Vcb, PartNdx);
1926     if(!(Vcb->FSBM_Bitmap)) {
1927         // init Bitmap buffer if necessary
1928         Vcb->FSBM_Bitmap = (int8*)DbgAllocatePool(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3) );
1929         if(!(Vcb->FSBM_Bitmap)) return STATUS_INSUFFICIENT_RESOURCES;
1930 
1931         Vcb->ZSBM_Bitmap = (int8*)DbgAllocatePool(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3) );
1932         if(!(Vcb->ZSBM_Bitmap)) {
1933 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1934 free_fsbm:
1935 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1936             MyFreePool__(Vcb->FSBM_Bitmap);
1937             Vcb->FSBM_Bitmap = NULL;
1938             return STATUS_INSUFFICIENT_RESOURCES;
1939         }
1940 
1941         RtlZeroMemory(Vcb->FSBM_Bitmap, i);
1942         RtlZeroMemory(Vcb->ZSBM_Bitmap, i);
1943 #ifdef UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1944         Vcb->FSBM_Bitmap_owners = (uint32*)DbgAllocatePool(NonPagedPool, (Vcb->LastPossibleLBA+1)*sizeof(uint32));
1945         if(!(Vcb->FSBM_Bitmap_owners)) {
1946             MyFreePool__(Vcb->ZSBM_Bitmap);
1947             Vcb->ZSBM_Bitmap = NULL;
1948             goto free_fsbm;
1949         }
1950         RtlFillMemory(Vcb->FSBM_Bitmap_owners, (Vcb->LastPossibleLBA+1)*sizeof(uint32), 0xff);
1951 #endif //UDF_TRACK_ONDISK_ALLOCATION_OWNERS
1952         Vcb->FSBM_ByteCount = i;
1953         Vcb->FSBM_BitCount = Vcb->LastPossibleLBA+1;
1954     }
1955     // read info for partition header (if any)
1956     if(phd) {
1957         // read unallocated Bitmap
1958         if(!OS_SUCCESS(status = UDFAddXSpaceBitmap(Vcb, PartNum, &(phd->unallocatedSpaceBitmap), UDF_FSPACE_BM)))
1959             return status;
1960         // read freed Bitmap
1961         if(!OS_SUCCESS(status = UDFAddXSpaceBitmap(Vcb, PartNum, &(phd->freedSpaceBitmap), UDF_ZSPACE_BM)))
1962             return status;
1963     }
1964     // read UnallocatedSpaceDesc & convert to Bitmap
1965     if(Lba) {
1966         if(!(AllocDesc = (int8*)MyAllocatePool__(NonPagedPool, Vcb->LBlockSize + sizeof(EXTENT_AD) )))
1967             return STATUS_INSUFFICIENT_RESOURCES;
1968         RtlZeroMemory(((int8*)AllocDesc) + Vcb->LBlockSize, sizeof(EXTENT_AD));
1969         if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1970            !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, l = (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1971             MyFreePool__(AllocDesc);
1972             return status;
1973         }
1974         UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1975         RtlCopyMemory((int8*)Extent, AllocDesc+sizeof(UNALLOC_SPACE_DESC), (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) );
1976         locAddr.partitionReferenceNum = (uint16)PartNum;
1977         // read extent is recorded with relative addresses
1978         // so, we should convert it to suitable form
1979         for(i=0; Extent[i].extLength; i++) {
1980             locAddr.logicalBlockNum = Extent[i].extLocation;
1981             Extent[i].extLocation = UDFPartLbaToPhys(Vcb, &locAddr);
1982             if(Extent[i].extLocation == LBA_OUT_OF_EXTENT) {
1983                 BrutePoint();
1984                 MyFreePool__(AllocDesc);
1985                 return STATUS_DISK_CORRUPT_ERROR;
1986             }
1987             if((Extent[i].extLocation >> 30) == EXTENT_NEXT_EXTENT_ALLOCDESC) {
1988                 // load continuation
1989                 Lba = Extent[i].extLocation & UDF_EXTENT_LENGTH_MASK;
1990                 if(!OS_SUCCESS(status = UDFReadTagged(Vcb, AllocDesc, Lba, Lba, &Ident)) ||
1991                    !(Extent = (PEXTENT_MAP)MyAllocatePool__(NonPagedPool, (((PUNALLOC_SPACE_DESC)AllocDesc)->numAllocDescs+1) * sizeof(EXTENT_AD) ))) {
1992                     MyFreePool__(AllocDesc);
1993                     return status;
1994                 }
1995                 if(Ident == TID_UNALLOC_SPACE_DESC) {
1996                     UDFRegisterFsStructure(Vcb, Lba, Vcb->BlockSize);
1997                     if(!(l = MyReallocPool__((int8*)Extent, l, (int8**)&Extent, i*sizeof(EXTENT_MAP)))) {
1998                         MyFreePool__(Extent);
1999                         MyFreePool__(AllocDesc);
2000                         return STATUS_INSUFFICIENT_RESOURCES;
2001                     }
2002                     Extent[i].extLength =
2003                     Extent[i].extLocation = 0;
2004                     Extent = UDFMergeMappings(Extent, (PEXTENT_MAP)(AllocDesc+sizeof(UNALLOC_SPACE_DESC)) );
2005 #ifdef UDF_DBG
2006                 } else {
2007                     UDFPrint(("Broken unallocated space descriptor sequence\n"));
2008 #endif // UDF_DBG
2009                 }
2010             }
2011         }
2012         UDFMarkSpaceAsXXX(Vcb, (-1), Extent, AS_USED); // mark as used
2013         MyFreePool__(Extent);
2014         MyFreePool__(AllocDesc);
2015     }
2016     return status;
2017 } // end UDFVerifyFreeSpaceBitmap()
2018 
2019 /*
2020     process Partition descriptor
2021  */
2022 OSSTATUS
2023 UDFLoadPartDesc(
2024     PVCB      Vcb,
2025     int8*     Buf
2026     )
2027 {
2028     PartitionDesc *p = (PartitionDesc *)Buf;
2029     uint32 i;
2030     OSSTATUS RC;
2031     BOOLEAN Found = FALSE;
2032     UDFPrint(("UDF: Pard Descr:\n"));
2033     UDFPrint((" volDescSeqNum   = %x\n", p->volDescSeqNum));
2034     UDFPrint((" partitionFlags  = %x\n", p->partitionFlags));
2035     UDFPrint((" partitionNumber = %x\n", p->partitionNumber));
2036     UDFPrint((" accessType      = %x\n", p->accessType));
2037     UDFPrint((" partitionStartingLocation = %x\n", p->partitionStartingLocation));
2038     UDFPrint((" partitionLength = %x\n", p->partitionLength));
2039     // There is nothing interesting to comment here
2040     // Just look at Names & Messages....
2041     for (i=0; i<Vcb->PartitionMaps; i++) {
2042         UDFPrint(("Searching map: (%d == %d)\n",
2043             Vcb->Partitions[i].PartitionNum, (p->partitionNumber) ));
2044         if(Vcb->Partitions[i].PartitionNum == (p->partitionNumber)) {
2045             Found = TRUE;
2046             Vcb->Partitions[i].PartitionRoot = p->partitionStartingLocation + Vcb->FirstLBA;
2047             Vcb->Partitions[i].PartitionLen = p->partitionLength;
2048             Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2049             Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2050             Vcb->Partitions[i].AccessType = p->accessType;
2051             UDFPrint(("Access mode %x\n", p->accessType));
2052             if(p->accessType == PARTITION_ACCESS_WO) {
2053                 Vcb->CDR_Mode = TRUE;
2054 //                Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2055             } else if(p->accessType < PARTITION_ACCESS_WO) {
2056                 // Soft-read-only volume
2057                 UDFPrint(("Soft Read-only volume\n"));
2058                 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2059                 Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_PART_RO;
2060             } else if(p->accessType > PARTITION_ACCESS_MAX_KNOWN) {
2061                 return STATUS_UNRECOGNIZED_MEDIA;
2062             }
2063 
2064             if(!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
2065                 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03))
2066             {
2067                 PPARTITION_HEADER_DESC phd;
2068 
2069                 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
2070 #ifdef UDF_DBG
2071                 if(phd->unallocatedSpaceTable.extLength)
2072                     UDFPrint(("unallocatedSpaceTable (part %d)\n", i));
2073 #endif // UDF_DBG
2074                 if(phd->unallocatedSpaceBitmap.extLength) {
2075                     Vcb->Partitions[i].UspaceBitmap =
2076                         phd->unallocatedSpaceBitmap.extPosition;
2077                     UDFPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2078                         i, Vcb->Partitions[i].UspaceBitmap ));
2079                 }
2080 #ifdef UDF_DBG
2081                 if(phd->partitionIntegrityTable.extLength)
2082                     UDFPrint(("partitionIntegrityTable (part %d)\n", i));
2083                 if(phd->freedSpaceTable.extLength)
2084                     UDFPrint(("freedSpaceTable (part %d)\n", i));
2085 #endif // UDF_DBG
2086                 if(phd->freedSpaceBitmap.extLength) {
2087                     Vcb->Partitions[i].FspaceBitmap =
2088                         phd->freedSpaceBitmap.extPosition;
2089                     UDFPrint(("freedSpaceBitmap (part %d)\n", i));
2090                 }
2091                 RC = UDFBuildFreeSpaceBitmap(Vcb, i, phd, 0);
2092                 //Vcb->Modified = FALSE;
2093                 UDFPreClrModified(Vcb);
2094                 UDFClrModified(Vcb);
2095                 if(!OS_SUCCESS(RC))
2096                     return RC;
2097 
2098                 if ((Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP15) ||
2099                     (Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP20)) {
2100                     RC = UDFLoadVAT(Vcb, i);
2101                     if(!OS_SUCCESS(RC))
2102                         return RC;
2103                     WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2104                     WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2105                     Vcb->LastModifiedTrack = 0;
2106                 }
2107             }
2108         }
2109     }
2110 #ifdef UDF_DBG
2111     if(!Found) {
2112         UDFPrint(("Partition (%d) not found in partition map\n", (p->partitionNumber) ));
2113     } else {
2114         UDFPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2115             p->partitionNumber, i-1, Vcb->Partitions[i-1].PartitionType,
2116             Vcb->Partitions[i-1].PartitionRoot, Vcb->Partitions[i-1].PartitionLen));
2117     }
2118 #endif // UDF_DBG
2119     return STATUS_SUCCESS;
2120 } // end UDFLoadPartDesc()
2121 
2122 /*
2123     process Partition descriptor
2124  */
2125 OSSTATUS
2126 UDFVerifyPartDesc(
2127     PVCB      Vcb,
2128     int8*     Buf
2129     )
2130 {
2131     PartitionDesc *p = (PartitionDesc *)Buf;
2132     uint32 i;
2133     OSSTATUS RC;
2134     BOOLEAN Found = FALSE;
2135     UDFPrint(("UDF: Verify Part Descr:\n"));
2136     UDFPrint((" volDescSeqNum   = %x\n", p->volDescSeqNum));
2137     UDFPrint((" partitionFlags  = %x\n", p->partitionFlags));
2138     UDFPrint((" partitionNumber = %x\n", p->partitionNumber));
2139     UDFPrint((" accessType      = %x\n", p->accessType));
2140     UDFPrint((" partitionStartingLocation = %x\n", p->partitionStartingLocation));
2141     UDFPrint((" partitionLength = %x\n", p->partitionLength));
2142     // There is nothing interesting to comment here
2143     // Just look at Names & Messages....
2144     for (i=0; i<Vcb->PartitionMaps; i++) {
2145         UDFPrint(("Searching map: (%d == %d)\n",
2146             Vcb->Partitions[i].PartitionNum, (p->partitionNumber) ));
2147         if(Vcb->Partitions[i].PartitionNum == (p->partitionNumber)) {
2148             Found = TRUE;
2149             if(Vcb->Partitions[i].PartitionRoot != p->partitionStartingLocation + Vcb->FirstLBA)
2150                 return STATUS_DISK_CORRUPT_ERROR;
2151             if(Vcb->Partitions[i].PartitionLen !=
2152                 min(p->partitionLength,
2153                     Vcb->LastPossibleLBA - Vcb->Partitions[i].PartitionRoot)) /* sectors */
2154                 return STATUS_DISK_CORRUPT_ERROR;
2155 //            Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2156 //            Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2157             if(Vcb->Partitions[i].AccessType != p->accessType)
2158                 return STATUS_DISK_CORRUPT_ERROR;
2159             UDFPrint(("Access mode %x\n", p->accessType));
2160             if(p->accessType == PARTITION_ACCESS_WO) {
2161                 if(Vcb->CDR_Mode != TRUE)
2162                     return STATUS_DISK_CORRUPT_ERROR;
2163 //                Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2164             } else if(p->accessType < PARTITION_ACCESS_WO) {
2165                 // Soft-read-only volume
2166                 UDFPrint(("Soft Read-only volume\n"));
2167                 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY))
2168                     return STATUS_DISK_CORRUPT_ERROR;
2169             } else if(p->accessType > PARTITION_ACCESS_MAX_KNOWN) {
2170                 return STATUS_UNRECOGNIZED_MEDIA;
2171             }
2172 
2173             if(!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
2174                 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03))
2175             {
2176                 PPARTITION_HEADER_DESC phd;
2177 
2178                 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
2179 #ifdef UDF_DBG
2180                 if(phd->unallocatedSpaceTable.extLength)
2181                     UDFPrint(("unallocatedSpaceTable (part %d)\n", i));
2182 #endif // UDF_DBG
2183                 if(phd->unallocatedSpaceBitmap.extLength) {
2184                     if(Vcb->Partitions[i].UspaceBitmap ==
2185                         phd->unallocatedSpaceBitmap.extPosition) {
2186                         UDFPrint(("Warning: both USpaceBitmaps have same location\n"));
2187                     }
2188                     UDFPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2189                         i, Vcb->Partitions[i].UspaceBitmap ));
2190                 }
2191 #ifdef UDF_DBG
2192                 if(phd->partitionIntegrityTable.extLength)
2193                     UDFPrint(("partitionIntegrityTable (part %d)\n", i));
2194                 if(phd->freedSpaceTable.extLength)
2195                     UDFPrint(("freedSpaceTable (part %d)\n", i));
2196 #endif // UDF_DBG
2197                 if(phd->freedSpaceBitmap.extLength) {
2198                     if(Vcb->Partitions[i].FspaceBitmap ==
2199                         phd->freedSpaceBitmap.extPosition) {
2200                         UDFPrint(("Warning: both FSpaceBitmaps have same location\n"));
2201                     }
2202                     UDFPrint(("freedSpaceBitmap (part %d)\n", i));
2203                 }
2204                 RC = UDFVerifyFreeSpaceBitmap(Vcb, i, phd, 0);
2205                 //Vcb->Modified = FALSE;
2206                 //UDFPreClrModified(Vcb);
2207                 //UDFClrModified(Vcb);
2208                 if(!OS_SUCCESS(RC))
2209                     return RC;
2210 
2211                 if ((Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP15) ||
2212                     (Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP20)) {
2213 /*                    RC = UDFLoadVAT(Vcb, i);
2214                     if(!OS_SUCCESS(RC))
2215                         return RC;
2216                     WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2217                     WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2218                     Vcb->LastModifiedTrack = 0;*/
2219                 }
2220             }
2221         }
2222     }
2223 #ifdef UDF_DBG
2224     if(!Found) {
2225         UDFPrint(("Partition (%d) not found in partition map\n", (p->partitionNumber) ));
2226     } else {
2227         UDFPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2228             p->partitionNumber, i-1, Vcb->Partitions[i-1].PartitionType,
2229             Vcb->Partitions[i-1].PartitionRoot, Vcb->Partitions[i-1].PartitionLen));
2230     }
2231 #endif // UDF_DBG
2232     return STATUS_SUCCESS;
2233 } // end UDFVerifyPartDesc()
2234 
2235 /*
2236     This routine scans VDS & fills special array with Desc locations
2237  */
2238 OSSTATUS
2239 UDFReadVDS(
2240     IN PVCB Vcb,
2241     IN uint32 block,
2242     IN uint32 lastblock,
2243     IN PUDF_VDS_RECORD vds,
2244     IN int8* Buf
2245     )
2246 {
2247     OSSTATUS status;
2248     GenericDesc* gd;
2249     BOOLEAN done=FALSE;
2250     uint32 vdsn;
2251     uint16 ident;
2252 
2253     UDFPrint(("UDF: Read VDS (%x - %x)\n", block, lastblock ));
2254     // Read the main descriptor sequence
2255     for (;(!done && block <= lastblock); block++)
2256     {
2257         status = UDFReadTagged(Vcb, Buf, block, block, &ident);
2258         if(!OS_SUCCESS(status))
2259             return status;
2260         UDFRegisterFsStructure(Vcb, block, Vcb->BlockSize);
2261 
2262         // Process each descriptor (ISO 13346 3/8.3-8.4)
2263         gd = (struct GenericDesc *)Buf;
2264         vdsn = gd->volDescSeqNum;
2265         UDFPrint(("LBA %x, Ident = %x, vdsn = %x\n", block, ident, vdsn ));
2266         switch (ident)
2267         {
2268             case TID_PRIMARY_VOL_DESC: // ISO 13346 3/10.1
2269                 if(vdsn >= vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum)
2270                 {
2271                     vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum = vdsn;
2272                     vds[VDS_POS_PRIMARY_VOL_DESC].block = block;
2273                 }
2274                 break;
2275             case TID_VOL_DESC_PTR: // ISO 13346 3/10.3
2276                 struct VolDescPtr* pVDP;
2277                 if(vdsn >= vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum)
2278                 {
2279                     vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn;
2280                     vds[VDS_POS_VOL_DESC_PTR].block = block;
2281                     vds[VDS_POS_RECURSION_COUNTER].volDescSeqNum++;
2282                     if(vds[VDS_POS_RECURSION_COUNTER].volDescSeqNum > MAX_VDS_PARTS) {
2283                        UDFPrint(("too long multipart VDS -> abort\n"));
2284                         return STATUS_DISK_CORRUPT_ERROR;
2285                     }
2286                     pVDP = (struct VolDescPtr*)Buf;
2287                     UDFPrint(("multipart VDS...\n"));
2288                     return UDFReadVDS(Vcb, pVDP->nextVolDescSeqExt.extLocation,
2289                                          pVDP->nextVolDescSeqExt.extLocation + (pVDP->nextVolDescSeqExt.extLocation >> Vcb->BlockSizeBits),
2290                                          vds, Buf);
2291                 }
2292                 break;
2293             case TID_IMP_USE_VOL_DESC: // ISO 13346 3/10.4
2294                 if(vdsn >= vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum)
2295                 {
2296                     vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum = vdsn;
2297                     vds[VDS_POS_IMP_USE_VOL_DESC].block = block;
2298                 }
2299                 break;
2300             case TID_PARTITION_DESC: // ISO 13346 3/10.5
2301                 if(!vds[VDS_POS_PARTITION_DESC].block)
2302                     vds[VDS_POS_PARTITION_DESC].block = block;
2303                 break;
2304             case TID_LOGICAL_VOL_DESC: // ISO 13346 3/10.6
2305             case TID_ADAPTEC_LOGICAL_VOL_DESC: // Adaptec Compressed UDF extesion
2306                 if(vdsn >= vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum)
2307                 {
2308                     vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum = vdsn;
2309                     vds[VDS_POS_LOGICAL_VOL_DESC].block = block;
2310                 }
2311                 break;
2312             case TID_UNALLOC_SPACE_DESC: // ISO 13346 3/10.8
2313                 if(vdsn >= vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum)
2314                 {
2315                     vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum = vdsn;
2316                     vds[VDS_POS_UNALLOC_SPACE_DESC].block = block;
2317                 }
2318                 break;
2319             case TID_TERMINATING_DESC: // ISO 13346 3/10.9
2320                 vds[VDS_POS_TERMINATING_DESC].block = block;
2321                 done = TRUE;
2322                 break;
2323         }
2324     }
2325     return STATUS_SUCCESS;
2326 } // UDFReadVDS()
2327 
2328 OSSTATUS
2329 UDFLoadImpUseVolDesc(
2330     IN PVCB   Vcb,
2331     int8*     Buf
2332     )
2333 {
2334 #ifdef UDF_DBG
2335     ImpUseVolDesc* iuvd = (ImpUseVolDesc*)Buf;
2336     ImpUseVolDescImpUse* iuvdiu = (ImpUseVolDescImpUse*)&(iuvd->impUse);
2337     UDFPrint(("UDF: Imp Use Vol Desc:\n"));
2338     UDFPrint((" volDescSeqNum = %x\n", iuvd->volDescSeqNum));
2339     UDFPrint(("UDF: Imp Use Vol Desc Imp Use:\n"));
2340     KdDump(iuvdiu, sizeof(ImpUseVolDescImpUse));
2341 #endif
2342     return STATUS_SUCCESS;
2343 } // UDFLoadImpUseVolDesc()
2344 
2345 OSSTATUS
2346 UDFLoadUnallocatedSpaceDesc(
2347     IN PVCB   Vcb,
2348     int8*     Buf
2349     )
2350 {
2351     UDFPrint(("UDF: Unallocated Space Desc:\n"));
2352 //    UnallocatedSpaceDesc* usd = (UnallocatedSpaceDesc*)Buf;
2353     return STATUS_SUCCESS;
2354 } // UDFLoadImpUseVolDesc()
2355 
2356 /*
2357     Process a main/reserve volume descriptor sequence.
2358 */
2359 OSSTATUS
2360 UDFProcessSequence(
2361      IN PDEVICE_OBJECT    DeviceObject,
2362      IN PVCB              Vcb,
2363      IN uint32            block,
2364      IN uint32            lastblock,
2365     OUT lb_addr           *fileset
2366     )
2367 {
2368     OSSTATUS    RC = STATUS_SUCCESS;
2369     int8*       Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2370     UDF_VDS_RECORD vds[VDS_POS_LENGTH];
2371 //    GenericDesc   *gd;
2372     uint32   i,j;
2373     uint16  ident;
2374     int8*  Buf2 = NULL;
2375 
2376     _SEH2_TRY {
2377         if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2378         RtlZeroMemory(vds, sizeof(UDF_VDS_RECORD) * VDS_POS_LENGTH);
2379         if(!OS_SUCCESS(RC = UDFReadVDS(Vcb, block, lastblock, (PUDF_VDS_RECORD)&vds, Buf)))
2380             try_return(RC);
2381         // walk through Vol Desc Sequence according to locations gained by
2382         // UDFReadVDS() & do some procesing for each one
2383         // It is very simple dispath routine...
2384         for (i=0; i<VDS_POS_LENGTH; i++)
2385         {
2386             if(vds[i].block)
2387             {
2388                 if(!OS_SUCCESS(RC = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident)))
2389                     try_return(RC);
2390                 UDFRegisterFsStructure(Vcb, vds[i].block, Vcb->BlockSize);
2391 
2392                 if(i == VDS_POS_PRIMARY_VOL_DESC) {
2393                     UDFLoadPVolDesc(Vcb,Buf);
2394                     if(!Vcb->PVolDescAddr.block) {
2395                         Vcb->PVolDescAddr = vds[i];
2396                     } else {
2397                         Vcb->PVolDescAddr2 = vds[i];
2398                     }
2399                 } else
2400                 if(i == VDS_POS_LOGICAL_VOL_DESC) {
2401                     RC = UDFLoadLogicalVol(DeviceObject,Vcb, Buf, fileset);
2402                     if(!OS_SUCCESS(RC)) try_return(RC);
2403                 } else
2404 
2405                 if(i == VDS_POS_IMP_USE_VOL_DESC) {
2406                     UDFLoadImpUseVolDesc(Vcb, Buf);
2407                 } else
2408                 if(i == VDS_POS_UNALLOC_SPACE_DESC) {
2409                     UDFLoadUnallocatedSpaceDesc(Vcb, Buf);
2410                 } else
2411 
2412                 if(i == VDS_POS_PARTITION_DESC)
2413                 {
2414                     Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2415                     if(!Buf2) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2416                     RC = UDFLoadPartDesc(Vcb,Buf);
2417                     if(!OS_SUCCESS(RC)) try_return(RC);
2418                     for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++)
2419                     {
2420                         RC = UDFReadTagged(Vcb,Buf2, j, j, &ident);
2421                         if(!OS_SUCCESS(RC)) try_return(RC);
2422                         UDFRegisterFsStructure(Vcb, j, Vcb->BlockSize);
2423 //                        gd = (struct GenericDesc *)Buf2;
2424                         if(ident == TID_PARTITION_DESC) {
2425                             RC = UDFLoadPartDesc(Vcb,Buf2);
2426                             if(!OS_SUCCESS(RC)) try_return(RC);
2427                         } else if(ident == TID_UNALLOC_SPACE_DESC) {
2428                             RC = UDFBuildFreeSpaceBitmap(Vcb,0,NULL,j);
2429                             //Vcb->Modified = FALSE;
2430                             UDFPreClrModified(Vcb);
2431                             UDFClrModified(Vcb);
2432                             if(!OS_SUCCESS(RC))
2433                                 try_return(RC);
2434                         }
2435                     }
2436                     MyFreePool__(Buf2);
2437                     Buf2 = NULL;
2438                 }
2439             } else {
2440                 if(i == VDS_POS_LOGICAL_VOL_DESC) {
2441                     RC = UDFLoadBogusLogicalVol(DeviceObject,Vcb, Buf, fileset);
2442                     if(!OS_SUCCESS(RC)) try_return(RC);
2443                 }
2444             }
2445         }
2446 
2447 try_exit: NOTHING;
2448 
2449     } _SEH2_FINALLY {
2450         if(Buf) MyFreePool__(Buf);
2451         if(Buf2) MyFreePool__(Buf2);
2452     } _SEH2_END;
2453 
2454     return RC;
2455 } // end UDFProcessSequence()
2456 
2457 /*
2458     Verifies a main/reserve volume descriptor sequence.
2459 */
2460 OSSTATUS
2461 UDFVerifySequence(
2462      IN PDEVICE_OBJECT    DeviceObject,
2463      IN PVCB              Vcb,
2464      IN uint32             block,
2465      IN uint32             lastblock,
2466      OUT lb_addr          *fileset
2467      )
2468 {
2469     OSSTATUS    RC = STATUS_SUCCESS;
2470     int8*       Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2471     UDF_VDS_RECORD vds[VDS_POS_LENGTH];
2472 //    GenericDesc   *gd;
2473     uint32   i,j;
2474     uint16  ident;
2475     int8*  Buf2 = NULL;
2476 
2477     _SEH2_TRY {
2478         if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2479         if(!block) try_return (RC = STATUS_SUCCESS);
2480         RtlZeroMemory(vds, sizeof(UDF_VDS_RECORD) * VDS_POS_LENGTH);
2481         if(!OS_SUCCESS(RC = UDFReadVDS(Vcb, block, lastblock, (PUDF_VDS_RECORD)&vds, Buf)))
2482             try_return(RC);
2483 
2484         for (i=0; i<VDS_POS_LENGTH; i++)
2485         {
2486             if(vds[i].block)
2487             {
2488                 if(!OS_SUCCESS(RC = UDFReadTagged(Vcb, Buf, vds[i].block, vds[i].block, &ident)))
2489                     try_return(RC);
2490                 UDFRegisterFsStructure(Vcb, vds[i].block, Vcb->BlockSize);
2491 
2492     /*            if(i == VDS_POS_PRIMARY_VOL_DESC)
2493                     UDFLoadPVolDesc(Vcb,Buf);
2494                 else if(i == VDS_POS_LOGICAL_VOL_DESC) {
2495                     RC = UDFLoadLogicalVol(DeviceObject,Vcb, Buf, fileset);
2496                     if(!OS_SUCCESS(RC)) try_return(RC);
2497                 }
2498                 else*/ if(i == VDS_POS_PARTITION_DESC)
2499                 {
2500                     Buf2 = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2501                     if(!Buf2) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
2502                     RC = UDFVerifyPartDesc(Vcb,Buf);
2503                     if(!OS_SUCCESS(RC)) try_return(RC);
2504                     for (j=vds[i].block+1; j<vds[VDS_POS_TERMINATING_DESC].block; j++)
2505                     {
2506                         RC = UDFReadTagged(Vcb,Buf2, j, j, &ident);
2507                         if(!OS_SUCCESS(RC)) try_return(RC);
2508                         UDFRegisterFsStructure(Vcb, j, Vcb->BlockSize);
2509 //                        gd = (struct GenericDesc *)Buf2;
2510                         if(ident == TID_PARTITION_DESC) {
2511                             RC = UDFVerifyPartDesc(Vcb,Buf2);
2512                             if(!OS_SUCCESS(RC)) try_return(RC);
2513                         } else if(ident == TID_UNALLOC_SPACE_DESC) {
2514                             RC = UDFVerifyFreeSpaceBitmap(Vcb,0,NULL,j);
2515                             Vcb->Modified = FALSE;
2516                             if(!OS_SUCCESS(RC))
2517                                 try_return(RC);
2518                         }
2519                     }
2520                     MyFreePool__(Buf2);
2521                     Buf2 = NULL;
2522                 }
2523             }
2524         }
2525 try_exit: NOTHING;
2526 
2527     } _SEH2_FINALLY {
2528         if(Buf) MyFreePool__(Buf);
2529         if(Buf2) MyFreePool__(Buf2);
2530     } _SEH2_END;
2531 
2532     return RC;
2533 } // end UDFVerifySequence()
2534 
2535 /*
2536     remember some useful info about FileSet & RootDir location
2537  */
2538 void
2539 UDFLoadFileset(
2540      IN PVCB            Vcb,
2541      IN PFILE_SET_DESC  fset,
2542     OUT lb_addr         *root,
2543     OUT lb_addr         *sysstream
2544     )
2545 {
2546     *root = fset->rootDirectoryICB.extLocation;
2547     Vcb->SerialNumber = fset->descTag.tagSerialNum;
2548     UDFPrint(("Rootdir at block=%x, partition=%d\n",
2549         root->logicalBlockNum, root->partitionReferenceNum));
2550     if(sysstream) {
2551         *sysstream = fset->streamDirectoryICB.extLocation;
2552         UDFPrint(("SysStream at block=%x, partition=%d\n",
2553             sysstream->logicalBlockNum, sysstream->partitionReferenceNum));
2554     }
2555 #define CUR_IDENT_SZ (sizeof(fset->logicalVolIdent))
2556     if (Vcb->VolIdent.Buffer) {
2557         MyFreePool__(Vcb->VolIdent.Buffer);
2558     }
2559     UDFGetDstring(&(Vcb->VolIdent), (dstring*)&(fset->logicalVolIdent), CUR_IDENT_SZ);
2560 #undef CUR_IDENT_SZ
2561     UDFPrint(("volIdent[] = '%ws'\n", Vcb->VolIdent.Buffer));
2562     // Get current UDF revision
2563     // Get Read-Only flags
2564     UDFReadEntityID_Domain(Vcb, &(fset->domainIdent));
2565 
2566 } // end UDFLoadFileset()
2567 
2568 OSSTATUS
2569 UDFIsCachedBadSequence(
2570     IN PVCB Vcb,
2571     IN uint32 Lba
2572     )
2573 {
2574     ULONG j;
2575     OSSTATUS RC = STATUS_SUCCESS;
2576     // Check if it is known bad sequence
2577     for(j=0; j<Vcb->BadSeqLocIndex; j++) {
2578         if(Vcb->BadSeqLoc[j] == Lba) {
2579             RC = Vcb->BadSeqStatus[j];
2580             break;
2581         }
2582     }
2583     return RC;
2584 } // end UDFIsCachedBadSequence()
2585 
2586 VOID
2587 UDFRememberBadSequence(
2588     IN PVCB Vcb,
2589     IN uint32 Lba,
2590     IN OSSTATUS RC
2591     )
2592 {
2593     int j;
2594     if(!OS_SUCCESS(UDFIsCachedBadSequence(Vcb, Lba)))
2595         return;
2596     // Remenber bad sequence
2597     j = Vcb->BadSeqLocIndex;
2598     Vcb->BadSeqLocIndex++;
2599     Vcb->BadSeqLoc[j]    = Lba;
2600     Vcb->BadSeqStatus[j] = RC;
2601 } // end UDFRememberBadSequence()
2602 
2603 /*
2604     load partition info
2605  */
2606 OSSTATUS
2607 UDFLoadPartition(
2608      IN PDEVICE_OBJECT  DeviceObject,
2609      IN PVCB            Vcb,
2610     OUT lb_addr         *fileset
2611     )
2612 {
2613     OSSTATUS            RC = STATUS_UNRECOGNIZED_VOLUME;
2614     OSSTATUS            RC2 = STATUS_UNRECOGNIZED_VOLUME;
2615     AnchorVolDescPtr    *anchor;
2616     uint16              ident;
2617     int8*               Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2618     uint32              main_s, main_e;
2619     uint32              reserve_s, reserve_e;
2620     int                 i;
2621 
2622     if(!Buf) return STATUS_INSUFFICIENT_RESOURCES;
2623     // walk through all available Anchors & load data
2624     for (i=0; i<MAX_ANCHOR_LOCATIONS; i++)
2625     {
2626         if(Vcb->Anchor[i] && (OS_SUCCESS(UDFReadTagged(Vcb, Buf,
2627             Vcb->Anchor[i], Vcb->Anchor[i] - Vcb->FirstLBA, &ident))))
2628         {
2629             anchor = (AnchorVolDescPtr *)Buf;
2630 
2631             // Locate the main sequence
2632             main_s = ( anchor->mainVolDescSeqExt.extLocation );
2633             main_e = ( anchor->mainVolDescSeqExt.extLength );
2634             main_e = main_e >> Vcb->BlockSizeBits;
2635             main_e += main_s;
2636 
2637             // Locate the reserve sequence
2638             reserve_s = (anchor->reserveVolDescSeqExt.extLocation);
2639             reserve_e = (anchor->reserveVolDescSeqExt.extLength);
2640             reserve_e = reserve_e >> Vcb->BlockSizeBits;
2641             reserve_e += reserve_s;
2642 
2643             // Check if it is known bad sequence
2644             RC = UDFIsCachedBadSequence(Vcb, main_s);
2645             if(OS_SUCCESS(RC)) {
2646                 // Process the main & reserve sequences
2647                 // responsible for finding the PartitionDesc(s)
2648                 UDFPrint(("-----------------------------------\n"));
2649                 UDFPrint(("UDF: Main sequence:\n"));
2650                 RC = UDFProcessSequence(DeviceObject, Vcb, main_s, main_e, fileset);
2651             }
2652 
2653             if(!OS_SUCCESS(RC)) {
2654                 // Remenber bad sequence
2655                 UDFRememberBadSequence(Vcb, main_s, RC);
2656 
2657                 UDFPrint(("-----------------------------------\n"));
2658                 UDFPrint(("UDF: Main sequence failed.\n"));
2659                 UDFPrint(("UDF: Reserve sequence\n"));
2660                 if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2661                 Vcb->LVid = NULL;
2662 
2663                 RC2 = UDFIsCachedBadSequence(Vcb, reserve_s);
2664                 if(OS_SUCCESS(RC2)) {
2665                     RC2 = UDFProcessSequence(DeviceObject, Vcb, reserve_s, reserve_e, fileset);
2666                 }
2667 
2668                 if(OS_SUCCESS(RC2)) {
2669                     UDFPrint(("-----------------------------------\n"));
2670                     Vcb->VDS2_Len = reserve_e - reserve_s;
2671                     Vcb->VDS2 = reserve_s;
2672                     RC = STATUS_SUCCESS;
2673                     // Vcb is already Zero-filled
2674 //                    Vcb->VDS1_Len = 0;
2675 //                    Vcb->VDS1 = 0;
2676                     break;
2677                 } else {
2678                     // This is also bad sequence. Remenber it too
2679                     UDFRememberBadSequence(Vcb, reserve_s, RC);
2680                 }
2681             } else {
2682                 // remember these values for umount__
2683                 Vcb->VDS1_Len = main_e - main_s;
2684                 Vcb->VDS1 = main_s;
2685 /*                if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2686                 Vcb->LVid = NULL;*/
2687                 if(OS_SUCCESS(UDFVerifySequence(DeviceObject, Vcb, reserve_s, reserve_e, fileset)))
2688                 {
2689                     UDFPrint(("-----------------------------------\n"));
2690                     Vcb->VDS2_Len = reserve_e - reserve_s;
2691                     Vcb->VDS2 = reserve_s;
2692                     break;
2693                 } else {
2694                     UDFPrint(("UDF: Reserve sequence verification failed.\n"));
2695                     switch(Vcb->PartitialDamagedVolumeAction) {
2696                     case UDF_PART_DAMAGED_RO:
2697                         UDFPrint(("UDF: Switch to r/o mode.\n"));
2698                         Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2699                         break;
2700                     case UDF_PART_DAMAGED_NO:
2701                         UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
2702                         Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2703                         RC = STATUS_WRONG_VOLUME;
2704                         break;
2705                     case UDF_PART_DAMAGED_RW:
2706                     default:
2707                         UDFPrint(("UDF: Keep r/w mode for your own risk.\n"));
2708                         break;
2709                     }
2710                 }
2711                 break;
2712             }
2713         }
2714     }
2715 
2716     if(Vcb->SparingCount &&
2717        (Vcb->NoFreeRelocationSpaceVolumeAction != UDF_PART_DAMAGED_RW)) {
2718         UDFPrint(("UDF: No free Sparing Entries -> Switch to r/o mode.\n"));
2719         Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2720     }
2721 
2722     if(i == sizeof(Vcb->Anchor)/sizeof(int)) {
2723         UDFPrint(("No Anchor block found\n"));
2724         RC = STATUS_UNRECOGNIZED_VOLUME;
2725 #ifdef UDF_DBG
2726     } else {
2727         UDFPrint(("Using anchor in block %x\n", Vcb->Anchor[i]));
2728 #endif // UDF_DBG
2729     }
2730     MyFreePool__(Buf);
2731     return RC;
2732 } // end UDFLoadPartition()
2733 
2734 /*
2735     This routine scans FileSet sequence & returns pointer to last valid
2736     FileSet
2737  */
2738 OSSTATUS
2739 UDFFindLastFileSet(
2740     IN PVCB Vcb,
2741     IN lb_addr *Addr,  // Addr for the 1st FileSet
2742     IN OUT PFILE_SET_DESC FileSetDesc
2743     )
2744 {
2745     OSSTATUS status;
2746     uint32 relLocExt = Addr->logicalBlockNum;
2747     uint32 locExt = UDFPartLbaToPhys(Vcb, Addr);
2748     uint16 Ident;
2749     uint32 relPrevExt, prevExt;
2750 
2751     relPrevExt, prevExt = NULL;
2752     FileSetDesc->nextExt.extLength = 1;  // ;)
2753     // walk through FileSet chain
2754     // we've just pre-init'd extent length to read 1st FileSet
2755     while(FileSetDesc->nextExt.extLength) {
2756         status = UDFReadTagged(Vcb, (int8*)FileSetDesc, locExt, relLocExt, &Ident);
2757         if(!OS_SUCCESS(status)) {
2758             FileSetDesc->nextExt.extLength = 0;
2759             return status;
2760         }
2761         UDFRegisterFsStructure(Vcb, locExt, Vcb->BlockSize);
2762         if((locExt == LBA_OUT_OF_EXTENT) || (Ident != TID_FILE_SET_DESC)) {
2763             // try to read previous FileSet
2764             if(!prevExt) return STATUS_UNRECOGNIZED_VOLUME;
2765             status = UDFReadTagged(Vcb, (int8*)FileSetDesc, prevExt, relLocExt, &Ident);
2766             if(OS_SUCCESS(status)) {
2767                 UDFRegisterFsStructure(Vcb, prevExt, Vcb->BlockSize);
2768             }
2769             return status;
2770         }
2771         prevExt = locExt;
2772         relPrevExt = relLocExt;
2773         locExt = UDFPartLbaToPhys(Vcb, &(FileSetDesc->nextExt.extLocation));
2774     }
2775     return STATUS_SUCCESS;
2776 } // end UDFFindLastFileSet()
2777 
2778 /*
2779     This routine reads all sparing tables & stores them in contiguos memory
2780     space
2781  */
2782 OSSTATUS
2783 UDFLoadSparingTable(
2784     IN PVCB Vcb,
2785     IN PSPARABLE_PARTITION_MAP PartMap
2786     )
2787 {
2788     PSPARING_MAP RelocMap;
2789     PSPARING_MAP NewRelocMap;
2790     OSSTATUS status;
2791     uint32 i=0, BC, BC2;
2792     PSPARING_TABLE SparTable;
2793     uint32 TabSize, NewSize;
2794     SIZE_T ReadBytes;
2795     uint32 SparTableLoc;
2796 #ifdef UDF_TRACK_FS_STRUCTURES
2797     uint32 j;
2798 #endif //UDF_TRACK_FS_STRUCTURES
2799     uint32 n,m;
2800     BOOLEAN merged;
2801 
2802     Vcb->SparingCountFree = -1;
2803 
2804     UDFPrint(("UDF: Sparable Part Map:\n"));
2805     Vcb->SparingTableLength = PartMap->sizeSparingTable;
2806     BC = (PartMap->sizeSparingTable >> Vcb->BlockSizeBits) + 1;
2807     UDFPrint((" partitionMapType   = %x\n", PartMap->partitionMapType));
2808     UDFPrint((" partitionMapLength = %x\n", PartMap->partitionMapLength));
2809     UDFPrint((" volSeqNum          = %x\n", PartMap->volSeqNum));
2810     UDFPrint((" partitionNum       = %x\n", PartMap->partitionNum));
2811     UDFPrint((" packetLength       = %x\n", PartMap->packetLength));
2812     UDFPrint((" numSparingTables   = %x\n", PartMap->numSparingTables));
2813     UDFPrint((" sizeSparingTable   = %x\n", PartMap->sizeSparingTable));
2814     SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize);
2815     if(!SparTable) return STATUS_INSUFFICIENT_RESOURCES;
2816     if(Vcb->SparingTable) {
2817         // if a part of Sparing Table is already loaded,
2818         // update it with data from another one
2819         RelocMap = Vcb->SparingTable;
2820         TabSize = Vcb->SparingCount * sizeof(SPARING_ENTRY);
2821     } else {
2822         // do some init to load first part of Sparing Table
2823         RelocMap = (PSPARING_MAP)MyAllocatePool__(NonPagedPool, RELOC_MAP_GRAN);
2824         if(!RelocMap) {
2825             MyFreePool__(SparTable);
2826             return STATUS_INSUFFICIENT_RESOURCES;
2827         }
2828         TabSize = RELOC_MAP_GRAN;
2829         Vcb->SparingBlockSize = PartMap->packetLength;
2830     }
2831     // walk through all available Sparing Tables
2832     for(i=0;i<PartMap->numSparingTables;i++) {
2833         // read (next) table
2834         SparTableLoc = ((uint32*)(PartMap+1))[i];
2835         for(n=0; n<Vcb->SparingTableCount; n++) {
2836             if(Vcb->SparingTableLoc[i] == SparTableLoc) {
2837                 UDFPrint((" already processed @%x\n",
2838                     SparTableLoc
2839                     ));
2840                 continue;
2841             }
2842         }
2843         status = UDFReadSectors(Vcb, FALSE, SparTableLoc, 1, FALSE, (int8*)SparTable, &ReadBytes);
2844         // tag should be set to TID_UNUSED_DESC
2845         if(OS_SUCCESS(status) && (SparTable->descTag.tagIdent == TID_UNUSED_DESC)) {
2846 
2847             UDFRegisterFsStructure(Vcb,  SparTableLoc, Vcb->BlockSize);
2848             BC2 = ((sizeof(SPARING_TABLE) +
2849                     SparTable->reallocationTableLen*sizeof(SparingEntry) +
2850                     Vcb->BlockSize-1)
2851                                       >> Vcb->BlockSizeBits);
2852             if(BC2 > BC) {
2853                 UDFPrint((" sizeSparingTable @%x too long: %x > %x\n",
2854                     SparTableLoc, BC2, BC
2855                     ));
2856                 continue;
2857             }
2858             status = UDFReadSectors(Vcb, FALSE, SparTableLoc,
2859                 BC2, FALSE, (int8*)SparTable, &ReadBytes);
2860             UDFRegisterFsStructure(Vcb,  SparTableLoc, BC2<<Vcb->BlockSizeBits);
2861 
2862             if(!OS_SUCCESS(status)) {
2863                 UDFPrint((" Error reading sizeSparingTable @%x (%x)\n",
2864                     SparTableLoc, BC2
2865                     ));
2866                 continue;
2867             }
2868             // process sparing table
2869             NewSize = sizeof(SparingEntry)*SparTable->reallocationTableLen;
2870             TabSize = MyReallocPool__((int8*)RelocMap, TabSize, (int8**)&RelocMap, TabSize+NewSize);
2871             if(!TabSize) {
2872                 MyFreePool__(SparTable);
2873                 return STATUS_INSUFFICIENT_RESOURCES;
2874             }
2875 
2876 #ifdef UDF_TRACK_FS_STRUCTURES
2877             for(j=0; j<SparTable->reallocationTableLen; j++) {
2878                 UDFRegisterFsStructure(Vcb,  ((SparingEntry*)(SparTable+1))[j].mappedLocation, Vcb->WriteBlockSize);
2879             }
2880 #endif //UDF_TRACK_FS_STRUCTURES
2881 
2882             Vcb->SparingTableLoc[Vcb->SparingTableCount] = SparTableLoc;
2883             Vcb->SparingTableCount++;
2884 
2885             NewRelocMap = (PSPARING_MAP)(SparTable+1);
2886             for(n=0; n<SparTable->reallocationTableLen; n++) {
2887                 merged = TRUE;
2888                 for(m=0; m<Vcb->SparingCount; m++) {
2889                     if(RelocMap[m].mappedLocation == NewRelocMap[n].mappedLocation) {
2890                         UDFPrint(("  dup @%x (%x) vs @%x (%x)\n",
2891                             RelocMap[m].origLocation, RelocMap[m].mappedLocation,
2892                             NewRelocMap[m].origLocation, NewRelocMap[m].mappedLocation));
2893                         merged = FALSE;
2894                     }
2895                     if((RelocMap[m].origLocation   == NewRelocMap[n].origLocation) &&
2896                        (RelocMap[m].mappedLocation != NewRelocMap[n].mappedLocation) &&
2897                        (RelocMap[m].origLocation != SPARING_LOC_AVAILABLE) &&
2898                        (RelocMap[m].origLocation != SPARING_LOC_CORRUPTED)) {
2899                         UDFPrint(("  conflict @%x (%x) vs @%x (%x)\n",
2900                             RelocMap[m].origLocation, RelocMap[m].mappedLocation,
2901                             NewRelocMap[n].origLocation, NewRelocMap[n].mappedLocation));
2902                         merged = FALSE;
2903                     }
2904                 }
2905                 if(merged) {
2906                     RelocMap[Vcb->SparingCount] = NewRelocMap[n];
2907                     UDFPrint(("  reloc %x -> %x\n",
2908                         RelocMap[Vcb->SparingCount].origLocation, RelocMap[Vcb->SparingCount].mappedLocation));
2909                     Vcb->SparingCount++;
2910                     if(RelocMap[Vcb->SparingCount].origLocation == SPARING_LOC_AVAILABLE) {
2911                         Vcb->NoFreeRelocationSpaceVolumeAction = UDF_PART_DAMAGED_RW;
2912                     }
2913                 }
2914             }
2915 
2916 /*
2917             RtlCopyMemory((int8*)(RelocMap+Vcb->SparingCount),
2918                           (int8*)(SparTable+1), NewSize);
2919             Vcb->SparingCount += NewSize/sizeof(SPARING_ENTRY);
2920 */
2921             if(Vcb->SparingTableCount >= MAX_SPARING_TABLE_LOCATIONS) {
2922                 UDFPrint(("    too many Sparing Tables\n"));
2923                 break;
2924             }
2925         }
2926     }
2927     Vcb->SparingTable = RelocMap;
2928     MyFreePool__(SparTable);
2929     return STATUS_SUCCESS;
2930 } // end UDFLoadSparingTable()
2931 
2932 /*
2933     This routine checks if buffer is ZERO-filled
2934  */
2935 BOOLEAN
2936 UDFCheckZeroBuf(
2937     IN int8* Buf,
2938     IN uint32 Length
2939     )
2940 {
2941 
2942 #if defined(_X86_) && defined(_MSC_VER) && !defined(__clang__)
2943 
2944     BOOLEAN RC = FALSE;
2945 
2946     uint32 len = Length;
2947     __asm push  ecx
2948     __asm push  edi
2949 
2950     __asm mov   ecx,len
2951     __asm mov   edi,Buf
2952     __asm xor   eax,eax
2953     __asm shr   ecx,2
2954     __asm repe scasd
2955     __asm jne   short not_all_zeros
2956     __asm mov   RC,1
2957 
2958 not_all_zeros:
2959 
2960     __asm pop   edi
2961     __asm pop   ecx
2962 
2963     return RC;
2964 
2965 #else // _X86_
2966 
2967     uint32* tmp = (uint32*)Buf;
2968     uint32 i;
2969 
2970     for(i=0; i<Length/4; i++) {
2971         if(tmp[i]) return FALSE;
2972     }
2973     return TRUE;
2974 
2975 #endif // _X86_
2976 
2977 } // end UDFCheckZeroBuf()
2978 
2979 /*
2980     check if this is an UDF-formatted disk
2981 */
2982 OSSTATUS
2983 UDFGetDiskInfoAndVerify(
2984     IN PDEVICE_OBJECT DeviceObject,      // the target device object
2985     IN PVCB           Vcb                // Volume control block from this DevObj
2986     )
2987 {
2988     OSSTATUS        RC = STATUS_UNRECOGNIZED_VOLUME;
2989     uint32          NSRDesc;
2990     lb_addr         fileset;
2991     PFILE_SET_DESC  FileSetDesc = NULL;
2992 
2993     int8*           Buf = NULL;
2994     SIZE_T          ReadBytes;
2995 
2996     UDFPrint(("UDFGetDiskInfoAndVerify\n"));
2997     _SEH2_TRY {
2998 
2999         if(!UDFFindAnchor(Vcb)) {
3000             if(Vcb->FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
3001                 // check if this disc is mountable for CDFS
3002                 UDFPrint(("   FILE_DEVICE_CD_ROM_FILE_SYSTEM\n"));
3003 check_NSR:
3004                 NSRDesc = UDFFindVRS(Vcb);
3005                 if(!(NSRDesc & VRS_ISO9660_FOUND)) {
3006                     // no CDFS VRS found
3007                     UDFPrint(("UDFGetDiskInfoAndVerify: no CDFS VRS found\n"));
3008                     if(!Vcb->TrackMap[Vcb->LastTrackNum].LastLba &&
3009                        !Vcb->TrackMap[Vcb->FirstTrackNum].LastLba) {
3010                         // such a stupid method of Audio-CD detection...
3011                         UDFPrint(("UDFGetDiskInfoAndVerify: set UDF_VCB_FLAGS_RAW_DISK\n"));
3012                         Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
3013                     }
3014                 }
3015                 Vcb->NSRDesc = NSRDesc;
3016 
3017                 Buf = (int8*)MyAllocatePool__(NonPagedPool, 0x10000);
3018                 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3019                 RC = UDFReadData(Vcb, FALSE, 0, 0x10000, FALSE, Buf, &ReadBytes);
3020                 if(!OS_SUCCESS(RC))
3021                     try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3022                 RC = STATUS_UNRECOGNIZED_VOLUME;
3023                 if(!UDFCheckZeroBuf(Buf,0x10000)) {
3024                     UDFPrint(("UDFGetDiskInfoAndVerify: possible FS detected, remove UDF_VCB_FLAGS_RAW_DISK\n"));
3025                     Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
3026                 }
3027                 MyFreePool__(Buf);
3028                 Buf = NULL;
3029             }
3030             try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3031         }
3032 
3033         RC = UDFLoadPartition(DeviceObject,Vcb,&fileset);
3034         if(!OS_SUCCESS(RC)) {
3035             if(RC == STATUS_UNRECOGNIZED_VOLUME) {
3036                 UDFPrint(("UDFGetDiskInfoAndVerify: check NSR presence\n"));
3037                 goto check_NSR;
3038             }
3039             try_return(RC);
3040         }
3041 
3042         FileSetDesc = (PFILE_SET_DESC)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
3043         if(!FileSetDesc) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3044 
3045         RC = UDFFindLastFileSet(Vcb,&fileset,FileSetDesc);
3046         if(!OS_SUCCESS(RC)) try_return(RC);
3047 
3048         UDFLoadFileset(Vcb,FileSetDesc, &(Vcb->RootLbAddr), &(Vcb->SysStreamLbAddr));
3049 
3050         Vcb->FSBM_OldBitmap = (int8*)DbgAllocatePool(NonPagedPool, Vcb->FSBM_ByteCount);
3051         if(!(Vcb->FSBM_OldBitmap)) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3052         RtlCopyMemory(Vcb->FSBM_OldBitmap, Vcb->FSBM_Bitmap, Vcb->FSBM_ByteCount);
3053 
3054 try_exit:   NOTHING;
3055     } _SEH2_FINALLY {
3056         if(FileSetDesc)   MyFreePool__(FileSetDesc);
3057         if(Buf)           MyFreePool__(Buf);
3058     } _SEH2_END;
3059 
3060     return(RC);
3061 
3062 } // end UDFGetDiskInfoAndVerify()
3063 
3064