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