[UDFS]
[reactos.git] / reactos / drivers / filesystems / udfs / udf_info / mount.cpp
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 uint32 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 uint32 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 uint32 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 uint32 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 uint32 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->minUDFReadRev == Vcb->minUDFReadRev) &&
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 uint32 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 uint32 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 uint32 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 uint32 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 uint32 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 uint32 _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 uint32 Length;
1584 uint32 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 uint32 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 uint32 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 =
2048 min(p->partitionLength,
2049 Vcb->LastPossibleLBA - Vcb->Partitions[i].PartitionRoot); /* sectors */
2050 Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2051 Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2052 Vcb->Partitions[i].AccessType = p->accessType;
2053 UDFPrint(("Access mode %x\n", p->accessType));
2054 if(p->accessType == PARTITION_ACCESS_WO) {
2055 Vcb->CDR_Mode = TRUE;
2056 // Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2057 } else if(p->accessType < PARTITION_ACCESS_WO) {
2058 // Soft-read-only volume
2059 UDFPrint(("Soft Read-only volume\n"));
2060 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2061 Vcb->UserFSFlags |= UDF_USER_FS_FLAGS_PART_RO;
2062 } else if(p->accessType > PARTITION_ACCESS_MAX_KNOWN) {
2063 return STATUS_UNRECOGNIZED_MEDIA;
2064 }
2065
2066 if(!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
2067 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03))
2068 {
2069 PPARTITION_HEADER_DESC phd;
2070
2071 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
2072 #ifdef UDF_DBG
2073 if(phd->unallocatedSpaceTable.extLength)
2074 UDFPrint(("unallocatedSpaceTable (part %d)\n", i));
2075 #endif // UDF_DBG
2076 if(phd->unallocatedSpaceBitmap.extLength) {
2077 Vcb->Partitions[i].UspaceBitmap =
2078 phd->unallocatedSpaceBitmap.extPosition;
2079 UDFPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2080 i, Vcb->Partitions[i].UspaceBitmap ));
2081 }
2082 #ifdef UDF_DBG
2083 if(phd->partitionIntegrityTable.extLength)
2084 UDFPrint(("partitionIntegrityTable (part %d)\n", i));
2085 if(phd->freedSpaceTable.extLength)
2086 UDFPrint(("freedSpaceTable (part %d)\n", i));
2087 #endif // UDF_DBG
2088 if(phd->freedSpaceBitmap.extLength) {
2089 Vcb->Partitions[i].FspaceBitmap =
2090 phd->freedSpaceBitmap.extPosition;
2091 UDFPrint(("freedSpaceBitmap (part %d)\n", i));
2092 }
2093 RC = UDFBuildFreeSpaceBitmap(Vcb, i, phd, 0);
2094 //Vcb->Modified = FALSE;
2095 UDFPreClrModified(Vcb);
2096 UDFClrModified(Vcb);
2097 if(!OS_SUCCESS(RC))
2098 return RC;
2099
2100 if ((Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP15) ||
2101 (Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP20)) {
2102 RC = UDFLoadVAT(Vcb, i);
2103 if(!OS_SUCCESS(RC))
2104 return RC;
2105 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2106 WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2107 Vcb->LastModifiedTrack = 0;
2108 }
2109 }
2110 }
2111 }
2112 #ifdef UDF_DBG
2113 if(!Found) {
2114 UDFPrint(("Partition (%d) not found in partition map\n", (p->partitionNumber) ));
2115 } else {
2116 UDFPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2117 p->partitionNumber, i-1, Vcb->Partitions[i-1].PartitionType,
2118 Vcb->Partitions[i-1].PartitionRoot, Vcb->Partitions[i-1].PartitionLen));
2119 }
2120 #endif // UDF_DBG
2121 return STATUS_SUCCESS;
2122 } // end UDFLoadPartDesc()
2123
2124 /*
2125 process Partition descriptor
2126 */
2127 OSSTATUS
2128 UDFVerifyPartDesc(
2129 PVCB Vcb,
2130 int8* Buf
2131 )
2132 {
2133 PartitionDesc *p = (PartitionDesc *)Buf;
2134 uint32 i;
2135 OSSTATUS RC;
2136 BOOLEAN Found = FALSE;
2137 UDFPrint(("UDF: Verify Part Descr:\n"));
2138 UDFPrint((" volDescSeqNum = %x\n", p->volDescSeqNum));
2139 UDFPrint((" partitionFlags = %x\n", p->partitionFlags));
2140 UDFPrint((" partitionNumber = %x\n", p->partitionNumber));
2141 UDFPrint((" accessType = %x\n", p->accessType));
2142 UDFPrint((" partitionStartingLocation = %x\n", p->partitionStartingLocation));
2143 UDFPrint((" partitionLength = %x\n", p->partitionLength));
2144 // There is nothing interesting to comment here
2145 // Just look at Names & Messages....
2146 for (i=0; i<Vcb->PartitionMaps; i++) {
2147 UDFPrint(("Searching map: (%d == %d)\n",
2148 Vcb->Partitions[i].PartitionNum, (p->partitionNumber) ));
2149 if(Vcb->Partitions[i].PartitionNum == (p->partitionNumber)) {
2150 Found = TRUE;
2151 if(Vcb->Partitions[i].PartitionRoot != p->partitionStartingLocation + Vcb->FirstLBA)
2152 return STATUS_DISK_CORRUPT_ERROR;
2153 if(Vcb->Partitions[i].PartitionLen !=
2154 min(p->partitionLength,
2155 Vcb->LastPossibleLBA - Vcb->Partitions[i].PartitionRoot)) /* sectors */
2156 return STATUS_DISK_CORRUPT_ERROR;
2157 // Vcb->Partitions[i].UspaceBitmap = 0xFFFFFFFF;
2158 // Vcb->Partitions[i].FspaceBitmap = 0xFFFFFFFF;
2159 if(Vcb->Partitions[i].AccessType != p->accessType)
2160 return STATUS_DISK_CORRUPT_ERROR;
2161 UDFPrint(("Access mode %x\n", p->accessType));
2162 if(p->accessType == PARTITION_ACCESS_WO) {
2163 if(Vcb->CDR_Mode != TRUE)
2164 return STATUS_DISK_CORRUPT_ERROR;
2165 // Vcb->Partitions[i].PartitionLen = Vcb->LastPossibleLBA - p->partitionStartingLocation;
2166 } else if(p->accessType < PARTITION_ACCESS_WO) {
2167 // Soft-read-only volume
2168 UDFPrint(("Soft Read-only volume\n"));
2169 if(!(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY))
2170 return STATUS_DISK_CORRUPT_ERROR;
2171 } else if(p->accessType > PARTITION_ACCESS_MAX_KNOWN) {
2172 return STATUS_UNRECOGNIZED_MEDIA;
2173 }
2174
2175 if(!strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR02) ||
2176 !strcmp((int8*)&(p->partitionContents.ident), PARTITION_CONTENTS_NSR03))
2177 {
2178 PPARTITION_HEADER_DESC phd;
2179
2180 phd = (PPARTITION_HEADER_DESC)(p->partitionContentsUse);
2181 #ifdef UDF_DBG
2182 if(phd->unallocatedSpaceTable.extLength)
2183 UDFPrint(("unallocatedSpaceTable (part %d)\n", i));
2184 #endif // UDF_DBG
2185 if(phd->unallocatedSpaceBitmap.extLength) {
2186 if(Vcb->Partitions[i].UspaceBitmap ==
2187 phd->unallocatedSpaceBitmap.extPosition) {
2188 UDFPrint(("Warning: both USpaceBitmaps have same location\n"));
2189 }
2190 UDFPrint(("unallocatedSpaceBitmap (part %d) @ %x\n",
2191 i, Vcb->Partitions[i].UspaceBitmap ));
2192 }
2193 #ifdef UDF_DBG
2194 if(phd->partitionIntegrityTable.extLength)
2195 UDFPrint(("partitionIntegrityTable (part %d)\n", i));
2196 if(phd->freedSpaceTable.extLength)
2197 UDFPrint(("freedSpaceTable (part %d)\n", i));
2198 #endif // UDF_DBG
2199 if(phd->freedSpaceBitmap.extLength) {
2200 if(Vcb->Partitions[i].FspaceBitmap ==
2201 phd->freedSpaceBitmap.extPosition) {
2202 UDFPrint(("Warning: both FSpaceBitmaps have same location\n"));
2203 }
2204 UDFPrint(("freedSpaceBitmap (part %d)\n", i));
2205 }
2206 RC = UDFVerifyFreeSpaceBitmap(Vcb, i, phd, 0);
2207 //Vcb->Modified = FALSE;
2208 //UDFPreClrModified(Vcb);
2209 //UDFClrModified(Vcb);
2210 if(!OS_SUCCESS(RC))
2211 return RC;
2212
2213 if ((Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP15) ||
2214 (Vcb->Partitions[i].PartitionType == UDF_VIRTUAL_MAP20)) {
2215 /* RC = UDFLoadVAT(Vcb, i);
2216 if(!OS_SUCCESS(RC))
2217 return RC;
2218 WCacheFlushAll__(&(Vcb->FastCache), Vcb);
2219 WCacheSetMode__(&(Vcb->FastCache), WCACHE_MODE_R);
2220 Vcb->LastModifiedTrack = 0;*/
2221 }
2222 }
2223 }
2224 }
2225 #ifdef UDF_DBG
2226 if(!Found) {
2227 UDFPrint(("Partition (%d) not found in partition map\n", (p->partitionNumber) ));
2228 } else {
2229 UDFPrint(("Partition (%d:%d type %x) starts at physical %x, length %x\n",
2230 p->partitionNumber, i-1, Vcb->Partitions[i-1].PartitionType,
2231 Vcb->Partitions[i-1].PartitionRoot, Vcb->Partitions[i-1].PartitionLen));
2232 }
2233 #endif // UDF_DBG
2234 return STATUS_SUCCESS;
2235 } // end UDFVerifyPartDesc()
2236
2237 /*
2238 This routine scans VDS & fills special array with Desc locations
2239 */
2240 OSSTATUS
2241 UDFReadVDS(
2242 IN PVCB Vcb,
2243 IN uint32 block,
2244 IN uint32 lastblock,
2245 IN PUDF_VDS_RECORD vds,
2246 IN int8* Buf
2247 )
2248 {
2249 OSSTATUS status;
2250 GenericDesc* gd;
2251 BOOLEAN done=FALSE;
2252 uint32 vdsn;
2253 uint16 ident;
2254
2255 UDFPrint(("UDF: Read VDS (%x - %x)\n", block, lastblock ));
2256 // Read the main descriptor sequence
2257 for (;(!done && block <= lastblock); block++)
2258 {
2259 status = UDFReadTagged(Vcb, Buf, block, block, &ident);
2260 if(!OS_SUCCESS(status))
2261 return status;
2262 UDFRegisterFsStructure(Vcb, block, Vcb->BlockSize);
2263
2264 // Process each descriptor (ISO 13346 3/8.3-8.4)
2265 gd = (struct GenericDesc *)Buf;
2266 vdsn = gd->volDescSeqNum;
2267 UDFPrint(("LBA %x, Ident = %x, vdsn = %x\n", block, ident, vdsn ));
2268 switch (ident)
2269 {
2270 case TID_PRIMARY_VOL_DESC: // ISO 13346 3/10.1
2271 if(vdsn >= vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum)
2272 {
2273 vds[VDS_POS_PRIMARY_VOL_DESC].volDescSeqNum = vdsn;
2274 vds[VDS_POS_PRIMARY_VOL_DESC].block = block;
2275 }
2276 break;
2277 case TID_VOL_DESC_PTR: // ISO 13346 3/10.3
2278 struct VolDescPtr* pVDP;
2279 if(vdsn >= vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum)
2280 {
2281 vds[VDS_POS_VOL_DESC_PTR].volDescSeqNum = vdsn;
2282 vds[VDS_POS_VOL_DESC_PTR].block = block;
2283 vds[VDS_POS_RECURSION_COUNTER].volDescSeqNum++;
2284 if(vds[VDS_POS_RECURSION_COUNTER].volDescSeqNum > MAX_VDS_PARTS) {
2285 UDFPrint(("too long multipart VDS -> abort\n"));
2286 return STATUS_DISK_CORRUPT_ERROR;
2287 }
2288 pVDP = (struct VolDescPtr*)Buf;
2289 UDFPrint(("multipart VDS...\n"));
2290 return UDFReadVDS(Vcb, pVDP->nextVolDescSeqExt.extLocation,
2291 pVDP->nextVolDescSeqExt.extLocation + (pVDP->nextVolDescSeqExt.extLocation >> Vcb->BlockSizeBits),
2292 vds, Buf);
2293 }
2294 break;
2295 case TID_IMP_USE_VOL_DESC: // ISO 13346 3/10.4
2296 if(vdsn >= vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum)
2297 {
2298 vds[VDS_POS_IMP_USE_VOL_DESC].volDescSeqNum = vdsn;
2299 vds[VDS_POS_IMP_USE_VOL_DESC].block = block;
2300 }
2301 break;
2302 case TID_PARTITION_DESC: // ISO 13346 3/10.5
2303 if(!vds[VDS_POS_PARTITION_DESC].block)
2304 vds[VDS_POS_PARTITION_DESC].block = block;
2305 break;
2306 case TID_LOGICAL_VOL_DESC: // ISO 13346 3/10.6
2307 case TID_ADAPTEC_LOGICAL_VOL_DESC: // Adaptec Compressed UDF extesion
2308 if(vdsn >= vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum)
2309 {
2310 vds[VDS_POS_LOGICAL_VOL_DESC].volDescSeqNum = vdsn;
2311 vds[VDS_POS_LOGICAL_VOL_DESC].block = block;
2312 }
2313 break;
2314 case TID_UNALLOC_SPACE_DESC: // ISO 13346 3/10.8
2315 if(vdsn >= vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum)
2316 {
2317 vds[VDS_POS_UNALLOC_SPACE_DESC].volDescSeqNum = vdsn;
2318 vds[VDS_POS_UNALLOC_SPACE_DESC].block = block;
2319 }
2320 break;
2321 case TID_TERMINATING_DESC: // ISO 13346 3/10.9
2322 vds[VDS_POS_TERMINATING_DESC].block = block;
2323 done = TRUE;
2324 break;
2325 }
2326 }
2327 return STATUS_SUCCESS;
2328 } // UDFReadVDS()
2329
2330 OSSTATUS
2331 UDFLoadImpUseVolDesc(
2332 IN PVCB Vcb,
2333 int8* Buf
2334 )
2335 {
2336 ImpUseVolDesc* iuvd = (ImpUseVolDesc*)Buf;
2337 ImpUseVolDescImpUse* iuvdiu = (ImpUseVolDescImpUse*)&(iuvd->impUse);
2338 UDFPrint(("UDF: Imp Use Vol Desc:\n"));
2339 UDFPrint((" volDescSeqNum = %x\n", iuvd->volDescSeqNum));
2340 UDFPrint(("UDF: Imp Use Vol Desc Imp Use:\n"));
2341 KdDump(iuvdiu, sizeof(ImpUseVolDescImpUse));
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 // Get current UDF revision
2556 // Get Read-Only flags
2557 UDFReadEntityID_Domain(Vcb, &(fset->domainIdent));
2558
2559 } // end UDFLoadFileset()
2560
2561 OSSTATUS
2562 UDFIsCachedBadSequence(
2563 IN PVCB Vcb,
2564 IN uint32 Lba
2565 )
2566 {
2567 ULONG j;
2568 OSSTATUS RC = STATUS_SUCCESS;
2569 // Check if it is known bad sequence
2570 for(j=0; j<Vcb->BadSeqLocIndex; j++) {
2571 if(Vcb->BadSeqLoc[j] == Lba) {
2572 RC = Vcb->BadSeqStatus[j];
2573 break;
2574 }
2575 }
2576 return RC;
2577 } // end UDFIsCachedBadSequence()
2578
2579 VOID
2580 UDFRememberBadSequence(
2581 IN PVCB Vcb,
2582 IN uint32 Lba,
2583 IN OSSTATUS RC
2584 )
2585 {
2586 int j;
2587 if(!OS_SUCCESS(UDFIsCachedBadSequence(Vcb, Lba)))
2588 return;
2589 // Remenber bad sequence
2590 j = Vcb->BadSeqLocIndex;
2591 Vcb->BadSeqLocIndex++;
2592 Vcb->BadSeqLoc[j] = Lba;
2593 Vcb->BadSeqStatus[j] = RC;
2594 } // end UDFRememberBadSequence()
2595
2596 /*
2597 load partition info
2598 */
2599 OSSTATUS
2600 UDFLoadPartition(
2601 IN PDEVICE_OBJECT DeviceObject,
2602 IN PVCB Vcb,
2603 OUT lb_addr *fileset
2604 )
2605 {
2606 OSSTATUS RC = STATUS_UNRECOGNIZED_VOLUME;
2607 OSSTATUS RC2 = STATUS_UNRECOGNIZED_VOLUME;
2608 AnchorVolDescPtr *anchor;
2609 uint16 ident;
2610 int8* Buf = (int8*)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
2611 uint32 main_s, main_e;
2612 uint32 reserve_s, reserve_e;
2613 int i;
2614
2615 if(!Buf) return STATUS_INSUFFICIENT_RESOURCES;
2616 // walk through all available Anchors & load data
2617 for (i=0; i<MAX_ANCHOR_LOCATIONS; i++)
2618 {
2619 if(Vcb->Anchor[i] && (OS_SUCCESS(UDFReadTagged(Vcb, Buf,
2620 Vcb->Anchor[i], Vcb->Anchor[i] - Vcb->FirstLBA, &ident))))
2621 {
2622 anchor = (AnchorVolDescPtr *)Buf;
2623
2624 // Locate the main sequence
2625 main_s = ( anchor->mainVolDescSeqExt.extLocation );
2626 main_e = ( anchor->mainVolDescSeqExt.extLength );
2627 main_e = main_e >> Vcb->BlockSizeBits;
2628 main_e += main_s;
2629
2630 // Locate the reserve sequence
2631 reserve_s = (anchor->reserveVolDescSeqExt.extLocation);
2632 reserve_e = (anchor->reserveVolDescSeqExt.extLength);
2633 reserve_e = reserve_e >> Vcb->BlockSizeBits;
2634 reserve_e += reserve_s;
2635
2636 // Check if it is known bad sequence
2637 RC = UDFIsCachedBadSequence(Vcb, main_s);
2638 if(OS_SUCCESS(RC)) {
2639 // Process the main & reserve sequences
2640 // responsible for finding the PartitionDesc(s)
2641 UDFPrint(("-----------------------------------\n"));
2642 UDFPrint(("UDF: Main sequence:\n"));
2643 RC = UDFProcessSequence(DeviceObject, Vcb, main_s, main_e, fileset);
2644 }
2645
2646 if(!OS_SUCCESS(RC)) {
2647 // Remenber bad sequence
2648 UDFRememberBadSequence(Vcb, main_s, RC);
2649
2650 UDFPrint(("-----------------------------------\n"));
2651 UDFPrint(("UDF: Main sequence failed.\n"));
2652 UDFPrint(("UDF: Reserve sequence\n"));
2653 if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2654 Vcb->LVid = NULL;
2655
2656 RC2 = UDFIsCachedBadSequence(Vcb, reserve_s);
2657 if(OS_SUCCESS(RC2)) {
2658 RC2 = UDFProcessSequence(DeviceObject, Vcb, reserve_s, reserve_e, fileset);
2659 }
2660
2661 if(OS_SUCCESS(RC2)) {
2662 UDFPrint(("-----------------------------------\n"));
2663 Vcb->VDS2_Len = reserve_e - reserve_s;
2664 Vcb->VDS2 = reserve_s;
2665 RC = STATUS_SUCCESS;
2666 // Vcb is already Zero-filled
2667 // Vcb->VDS1_Len = 0;
2668 // Vcb->VDS1 = 0;
2669 break;
2670 } else {
2671 // This is also bad sequence. Remenber it too
2672 UDFRememberBadSequence(Vcb, reserve_s, RC);
2673 }
2674 } else {
2675 // remember these values for umount__
2676 Vcb->VDS1_Len = main_e - main_s;
2677 Vcb->VDS1 = main_s;
2678 /* if(Vcb->LVid) MyFreePool__(Vcb->LVid);
2679 Vcb->LVid = NULL;*/
2680 if(OS_SUCCESS(UDFVerifySequence(DeviceObject, Vcb, reserve_s, reserve_e, fileset)))
2681 {
2682 UDFPrint(("-----------------------------------\n"));
2683 Vcb->VDS2_Len = reserve_e - reserve_s;
2684 Vcb->VDS2 = reserve_s;
2685 break;
2686 } else {
2687 UDFPrint(("UDF: Reserve sequence verification failed.\n"));
2688 switch(Vcb->PartitialDamagedVolumeAction) {
2689 case UDF_PART_DAMAGED_RO:
2690 UDFPrint(("UDF: Switch to r/o mode.\n"));
2691 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2692 break;
2693 case UDF_PART_DAMAGED_NO:
2694 UDFPrint(("UDF: Switch to raw mount mode, return UNRECOGNIZED_VOLUME.\n"));
2695 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2696 RC = STATUS_WRONG_VOLUME;
2697 break;
2698 case UDF_PART_DAMAGED_RW:
2699 default:
2700 UDFPrint(("UDF: Keep r/w mode for your own risk.\n"));
2701 break;
2702 }
2703 }
2704 break;
2705 }
2706 }
2707 }
2708
2709 if(Vcb->SparingCount &&
2710 (Vcb->NoFreeRelocationSpaceVolumeAction != UDF_PART_DAMAGED_RW)) {
2711 UDFPrint(("UDF: No free Sparing Entries -> Switch to r/o mode.\n"));
2712 Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
2713 }
2714
2715 if(i == sizeof(Vcb->Anchor)/sizeof(int)) {
2716 UDFPrint(("No Anchor block found\n"));
2717 RC = STATUS_UNRECOGNIZED_VOLUME;
2718 #ifdef UDF_DBG
2719 } else {
2720 UDFPrint(("Using anchor in block %x\n", Vcb->Anchor[i]));
2721 #endif // UDF_DBG
2722 }
2723 MyFreePool__(Buf);
2724 return RC;
2725 } // end UDFLoadPartition()
2726
2727 /*
2728 This routine scans FileSet sequence & returns pointer to last valid
2729 FileSet
2730 */
2731 OSSTATUS
2732 UDFFindLastFileSet(
2733 IN PVCB Vcb,
2734 IN lb_addr *Addr, // Addr for the 1st FileSet
2735 IN OUT PFILE_SET_DESC FileSetDesc
2736 )
2737 {
2738 OSSTATUS status;
2739 uint32 relLocExt = Addr->logicalBlockNum;
2740 uint32 locExt = UDFPartLbaToPhys(Vcb, Addr);
2741 uint16 Ident;
2742 uint32 relPrevExt, prevExt;
2743
2744 relPrevExt, prevExt = NULL;
2745 FileSetDesc->nextExt.extLength = 1; // ;)
2746 // walk through FileSet chain
2747 // we've just pre-init'd extent length to read 1st FileSet
2748 while(FileSetDesc->nextExt.extLength) {
2749 status = UDFReadTagged(Vcb, (int8*)FileSetDesc, locExt, relLocExt, &Ident);
2750 if(!OS_SUCCESS(status)) {
2751 FileSetDesc->nextExt.extLength = 0;
2752 return status;
2753 }
2754 UDFRegisterFsStructure(Vcb, locExt, Vcb->BlockSize);
2755 if((locExt == LBA_OUT_OF_EXTENT) || (Ident != TID_FILE_SET_DESC)) {
2756 // try to read previous FileSet
2757 if(!prevExt) return STATUS_UNRECOGNIZED_VOLUME;
2758 status = UDFReadTagged(Vcb, (int8*)FileSetDesc, prevExt, relLocExt, &Ident);
2759 if(OS_SUCCESS(status)) {
2760 UDFRegisterFsStructure(Vcb, prevExt, Vcb->BlockSize);
2761 }
2762 return status;
2763 }
2764 prevExt = locExt;
2765 relPrevExt = relLocExt;
2766 locExt = UDFPartLbaToPhys(Vcb, &(FileSetDesc->nextExt.extLocation));
2767 }
2768 return STATUS_SUCCESS;
2769 } // end UDFFindLastFileSet()
2770
2771 /*
2772 This routine reads all sparing tables & stores them in contiguos memory
2773 space
2774 */
2775 OSSTATUS
2776 UDFLoadSparingTable(
2777 IN PVCB Vcb,
2778 IN PSPARABLE_PARTITION_MAP PartMap
2779 )
2780 {
2781 PSPARING_MAP RelocMap;
2782 PSPARING_MAP NewRelocMap;
2783 OSSTATUS status;
2784 uint32 i=0, BC, BC2;
2785 PSPARING_TABLE SparTable;
2786 uint32 TabSize, NewSize;
2787 uint32 ReadBytes;
2788 uint32 SparTableLoc;
2789 #ifdef UDF_TRACK_FS_STRUCTURES
2790 uint32 j;
2791 #endif //UDF_TRACK_FS_STRUCTURES
2792 uint32 n,m;
2793 BOOLEAN merged;
2794
2795 Vcb->SparingCountFree = -1;
2796
2797 UDFPrint(("UDF: Sparable Part Map:\n"));
2798 Vcb->SparingTableLength = PartMap->sizeSparingTable;
2799 BC = (PartMap->sizeSparingTable >> Vcb->BlockSizeBits) + 1;
2800 UDFPrint((" partitionMapType = %x\n", PartMap->partitionMapType));
2801 UDFPrint((" partitionMapLength = %x\n", PartMap->partitionMapLength));
2802 UDFPrint((" volSeqNum = %x\n", PartMap->volSeqNum));
2803 UDFPrint((" partitionNum = %x\n", PartMap->partitionNum));
2804 UDFPrint((" packetLength = %x\n", PartMap->packetLength));
2805 UDFPrint((" numSparingTables = %x\n", PartMap->numSparingTables));
2806 UDFPrint((" sizeSparingTable = %x\n", PartMap->sizeSparingTable));
2807 SparTable = (PSPARING_TABLE)MyAllocatePool__(NonPagedPool, BC*Vcb->BlockSize);
2808 if(!SparTable) return STATUS_INSUFFICIENT_RESOURCES;
2809 if(Vcb->SparingTable) {
2810 // if a part of Sparing Table is already loaded,
2811 // update it with data from another one
2812 RelocMap = Vcb->SparingTable;
2813 TabSize = Vcb->SparingCount * sizeof(SPARING_ENTRY);
2814 } else {
2815 // do some init to load first part of Sparing Table
2816 RelocMap = (PSPARING_MAP)MyAllocatePool__(NonPagedPool, RELOC_MAP_GRAN);
2817 if(!RelocMap) {
2818 MyFreePool__(SparTable);
2819 return STATUS_INSUFFICIENT_RESOURCES;
2820 }
2821 TabSize = RELOC_MAP_GRAN;
2822 Vcb->SparingBlockSize = PartMap->packetLength;
2823 }
2824 // walk through all available Sparing Tables
2825 for(i=0;i<PartMap->numSparingTables;i++) {
2826 // read (next) table
2827 SparTableLoc = ((uint32*)(PartMap+1))[i];
2828 for(n=0; n<Vcb->SparingTableCount; n++) {
2829 if(Vcb->SparingTableLoc[i] == SparTableLoc) {
2830 UDFPrint((" already processed @%x\n",
2831 SparTableLoc
2832 ));
2833 continue;
2834 }
2835 }
2836 status = UDFReadSectors(Vcb, FALSE, SparTableLoc, 1, FALSE, (int8*)SparTable, &ReadBytes);
2837 // tag should be set to TID_UNUSED_DESC
2838 if(OS_SUCCESS(status) && (SparTable->descTag.tagIdent == TID_UNUSED_DESC)) {
2839
2840 UDFRegisterFsStructure(Vcb, SparTableLoc, Vcb->BlockSize);
2841 BC2 = ((sizeof(SPARING_TABLE) +
2842 SparTable->reallocationTableLen*sizeof(SparingEntry) +
2843 Vcb->BlockSize-1)
2844 >> Vcb->BlockSizeBits);
2845 if(BC2 > BC) {
2846 UDFPrint((" sizeSparingTable @%x too long: %x > %x\n",
2847 SparTableLoc, BC2, BC
2848 ));
2849 continue;
2850 }
2851 status = UDFReadSectors(Vcb, FALSE, SparTableLoc,
2852 BC2, FALSE, (int8*)SparTable, &ReadBytes);
2853 UDFRegisterFsStructure(Vcb, SparTableLoc, BC2<<Vcb->BlockSizeBits);
2854
2855 if(!OS_SUCCESS(status)) {
2856 UDFPrint((" Error reading sizeSparingTable @%x (%x)\n",
2857 SparTableLoc, BC2
2858 ));
2859 continue;
2860 }
2861 // process sparing table
2862 NewSize = sizeof(SparingEntry)*SparTable->reallocationTableLen;
2863 TabSize = MyReallocPool__((int8*)RelocMap, TabSize, (int8**)&RelocMap, TabSize+NewSize);
2864 if(!TabSize) {
2865 MyFreePool__(SparTable);
2866 return STATUS_INSUFFICIENT_RESOURCES;
2867 }
2868
2869 #ifdef UDF_TRACK_FS_STRUCTURES
2870 for(j=0; j<SparTable->reallocationTableLen; j++) {
2871 UDFRegisterFsStructure(Vcb, ((SparingEntry*)(SparTable+1))[j].mappedLocation, Vcb->WriteBlockSize);
2872 }
2873 #endif //UDF_TRACK_FS_STRUCTURES
2874
2875 Vcb->SparingTableLoc[Vcb->SparingTableCount] = SparTableLoc;
2876 Vcb->SparingTableCount++;
2877
2878 NewRelocMap = (PSPARING_MAP)(SparTable+1);
2879 for(n=0; n<SparTable->reallocationTableLen; n++) {
2880 merged = TRUE;
2881 for(m=0; m<Vcb->SparingCount; m++) {
2882 if(RelocMap[m].mappedLocation == NewRelocMap[n].mappedLocation) {
2883 UDFPrint((" dup @%x (%x) vs @%x (%x)\n",
2884 RelocMap[m].origLocation, RelocMap[m].mappedLocation,
2885 NewRelocMap[m].origLocation, NewRelocMap[m].mappedLocation));
2886 merged = FALSE;
2887 }
2888 if((RelocMap[m].origLocation == NewRelocMap[n].origLocation) &&
2889 (RelocMap[m].mappedLocation != NewRelocMap[n].mappedLocation) &&
2890 (RelocMap[m].origLocation != SPARING_LOC_AVAILABLE) &&
2891 (RelocMap[m].origLocation != SPARING_LOC_CORRUPTED)) {
2892 UDFPrint((" conflict @%x (%x) vs @%x (%x)\n",
2893 RelocMap[m].origLocation, RelocMap[m].mappedLocation,
2894 NewRelocMap[n].origLocation, NewRelocMap[n].mappedLocation));
2895 merged = FALSE;
2896 }
2897 }
2898 if(merged) {
2899 RelocMap[Vcb->SparingCount] = NewRelocMap[n];
2900 UDFPrint((" reloc %x -> %x\n",
2901 RelocMap[Vcb->SparingCount].origLocation, RelocMap[Vcb->SparingCount].mappedLocation));
2902 Vcb->SparingCount++;
2903 if(RelocMap[Vcb->SparingCount].origLocation == SPARING_LOC_AVAILABLE) {
2904 Vcb->NoFreeRelocationSpaceVolumeAction = UDF_PART_DAMAGED_RW;
2905 }
2906 }
2907 }
2908
2909 /*
2910 RtlCopyMemory((int8*)(RelocMap+Vcb->SparingCount),
2911 (int8*)(SparTable+1), NewSize);
2912 Vcb->SparingCount += NewSize/sizeof(SPARING_ENTRY);
2913 */
2914 if(Vcb->SparingTableCount >= MAX_SPARING_TABLE_LOCATIONS) {
2915 UDFPrint((" too many Sparing Tables\n"));
2916 break;
2917 }
2918 }
2919 }
2920 Vcb->SparingTable = RelocMap;
2921 MyFreePool__(SparTable);
2922 return STATUS_SUCCESS;
2923 } // end UDFLoadSparingTable()
2924
2925 /*
2926 This routine checks if buffer is ZERO-filled
2927 */
2928 BOOLEAN
2929 UDFCheckZeroBuf(
2930 IN int8* Buf,
2931 IN uint32 Length
2932 )
2933 {
2934
2935 #if defined (_X86_) && defined (_MSC_VER)
2936
2937 BOOLEAN RC = FALSE;
2938
2939 uint32 len = Length;
2940 __asm push ecx
2941 __asm push edi
2942
2943 __asm mov ecx,len
2944 __asm mov edi,Buf
2945 __asm xor eax,eax
2946 __asm shr ecx,2
2947 __asm repe scasd
2948 __asm jne short not_all_zeros
2949 __asm mov RC,1
2950
2951 not_all_zeros:
2952
2953 __asm pop edi
2954 __asm pop ecx
2955
2956 return RC;
2957
2958 #else // _X86_
2959
2960 uint32* tmp = (uint32*)Buf;
2961 uint32 i;
2962
2963 for(i=0; i<Length/4; i++) {
2964 if(tmp[i]) return FALSE;
2965 }
2966 return TRUE;
2967
2968 #endif // _X86_
2969
2970 } // end UDFCheckZeroBuf()
2971
2972 /*
2973 check if this is an UDF-formatted disk
2974 */
2975 OSSTATUS
2976 UDFGetDiskInfoAndVerify(
2977 IN PDEVICE_OBJECT DeviceObject, // the target device object
2978 IN PVCB Vcb // Volume control block from this DevObj
2979 )
2980 {
2981 OSSTATUS RC = STATUS_UNRECOGNIZED_VOLUME;
2982 uint32 NSRDesc;
2983 lb_addr fileset;
2984 PFILE_SET_DESC FileSetDesc = NULL;
2985
2986 int8* Buf = NULL;
2987 uint32 ReadBytes;
2988
2989 UDFPrint(("UDFGetDiskInfoAndVerify\n"));
2990 _SEH2_TRY {
2991
2992 if(!UDFFindAnchor(Vcb)) {
2993 if(Vcb->FsDeviceType == FILE_DEVICE_CD_ROM_FILE_SYSTEM) {
2994 // check if this disc is mountable for CDFS
2995 UDFPrint((" FILE_DEVICE_CD_ROM_FILE_SYSTEM\n"));
2996 check_NSR:
2997 NSRDesc = UDFFindVRS(Vcb);
2998 if(!(NSRDesc & VRS_ISO9660_FOUND)) {
2999 // no CDFS VRS found
3000 UDFPrint(("UDFGetDiskInfoAndVerify: no CDFS VRS found\n"));
3001 if(!Vcb->TrackMap[Vcb->LastTrackNum].LastLba &&
3002 !Vcb->TrackMap[Vcb->FirstTrackNum].LastLba) {
3003 // such a stupid method of Audio-CD detection...
3004 UDFPrint(("UDFGetDiskInfoAndVerify: set UDF_VCB_FLAGS_RAW_DISK\n"));
3005 Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
3006 }
3007 }
3008 Vcb->NSRDesc = NSRDesc;
3009
3010 Buf = (int8*)MyAllocatePool__(NonPagedPool, 0x10000);
3011 if(!Buf) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3012 RC = UDFReadData(Vcb, FALSE, 0, 0x10000, FALSE, Buf, &ReadBytes);
3013 if(!OS_SUCCESS(RC))
3014 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3015 RC = STATUS_UNRECOGNIZED_VOLUME;
3016 if(!UDFCheckZeroBuf(Buf,0x10000)) {
3017 UDFPrint(("UDFGetDiskInfoAndVerify: possible FS detected, remove UDF_VCB_FLAGS_RAW_DISK\n"));
3018 Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
3019 }
3020 MyFreePool__(Buf);
3021 Buf = NULL;
3022 }
3023 try_return(RC = STATUS_UNRECOGNIZED_VOLUME);
3024 }
3025
3026 RC = UDFLoadPartition(DeviceObject,Vcb,&fileset);
3027 if(!OS_SUCCESS(RC)) {
3028 if(RC == STATUS_UNRECOGNIZED_VOLUME) {
3029 UDFPrint(("UDFGetDiskInfoAndVerify: check NSR presence\n"));
3030 goto check_NSR;
3031 }
3032 try_return(RC);
3033 }
3034
3035 FileSetDesc = (PFILE_SET_DESC)MyAllocatePool__(NonPagedPool,Vcb->BlockSize);
3036 if(!FileSetDesc) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3037
3038 RC = UDFFindLastFileSet(Vcb,&fileset,FileSetDesc);
3039 if(!OS_SUCCESS(RC)) try_return(RC);
3040
3041 UDFLoadFileset(Vcb,FileSetDesc, &(Vcb->RootLbAddr), &(Vcb->SysStreamLbAddr));
3042
3043 Vcb->FSBM_OldBitmap = (int8*)DbgAllocatePool(NonPagedPool, Vcb->FSBM_ByteCount);
3044 if(!(Vcb->FSBM_OldBitmap)) try_return(RC = STATUS_INSUFFICIENT_RESOURCES);
3045 RtlCopyMemory(Vcb->FSBM_OldBitmap, Vcb->FSBM_Bitmap, Vcb->FSBM_ByteCount);
3046
3047 try_exit: NOTHING;
3048 } _SEH2_FINALLY {
3049 if(FileSetDesc) MyFreePool__(FileSetDesc);
3050 if(Buf) MyFreePool__(Buf);
3051 } _SEH2_END;
3052
3053 return(RC);
3054
3055 } // end UDFGetDiskInfoAndVerify()
3056