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
UDFPrepareXSpaceBitmap(IN PVCB Vcb,IN OUT PSHORT_AD XSpaceBitmap,IN OUT PEXTENT_INFO XSBMExtInfo,IN OUT int8 ** XSBM,IN OUT uint32 * XSl)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
UDFUpdateXSpaceBitmaps(IN PVCB Vcb,IN uint32 PartNum,IN PPARTITION_HEADER_DESC phd)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
UDFUpdatePartDesc(PVCB Vcb,int8 * Buf)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
UDFUpdateLogicalVolInt(PVCB Vcb,BOOLEAN Close)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
UDFUpdateSparingTable(IN PVCB Vcb)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
UDFUpdateLogicalVol(IN PVCB Vcb,IN UDF_VDS_RECORD Lba,IN PUNICODE_STRING VolIdent)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
UDFUpdateVDS(IN PVCB Vcb,IN uint32 block,IN uint32 lastblock,IN uint32 flags)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
UDFSetDstring(IN PUNICODE_STRING UName,IN dstring * Dest,IN uint32 Length)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
UDFGetDstring(IN OUT PUNICODE_STRING UName,IN dstring * Dest,IN uint32 Length)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
UDFUpdateVolIdent(IN PVCB Vcb,IN UDF_VDS_RECORD Lba,IN PUNICODE_STRING VolIdent)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
UDFUpdateNonAllocated(IN PVCB Vcb)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
UDFUmount__(IN PVCB Vcb)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
UDFFindAnchor(PVCB Vcb)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
UDFFindVRS(PVCB Vcb)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
UDFLoadPVolDesc(PVCB Vcb,int8 * Buf)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
UDFLoadLogicalVolInt(PDEVICE_OBJECT DeviceObject,PVCB Vcb,extent_ad loc)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
UDFLoadLogicalVol(PDEVICE_OBJECT DeviceObject,PVCB Vcb,int8 * Buf,lb_addr * fileset)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
UDFLoadBogusLogicalVol(PDEVICE_OBJECT DeviceObject,PVCB Vcb,int8 * Buf,lb_addr * fileset)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
UDFAddXSpaceBitmap(IN PVCB Vcb,IN uint32 PartNum,IN PSHORT_AD bm,IN ULONG bm_type)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
UDFVerifyXSpaceBitmap(IN PVCB Vcb,IN uint32 PartNum,IN PSHORT_AD bm,IN ULONG bm_type)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
UDFVerifyFreeSpaceBitmap(IN PVCB Vcb,IN uint32 PartNdx,IN PPARTITION_HEADER_DESC phd,IN uint32 Lba)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
UDFBuildFreeSpaceBitmap(IN PVCB Vcb,IN uint32 PartNdx,IN PPARTITION_HEADER_DESC phd,IN uint32 Lba)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
UDFLoadPartDesc(PVCB Vcb,int8 * Buf)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
UDFVerifyPartDesc(PVCB Vcb,int8 * Buf)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
UDFReadVDS(IN PVCB Vcb,IN uint32 block,IN uint32 lastblock,IN PUDF_VDS_RECORD vds,IN int8 * Buf)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
UDFLoadImpUseVolDesc(IN PVCB Vcb,int8 * Buf)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
UDFLoadUnallocatedSpaceDesc(IN PVCB Vcb,int8 * Buf)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
UDFProcessSequence(IN PDEVICE_OBJECT DeviceObject,IN PVCB Vcb,IN uint32 block,IN uint32 lastblock,OUT lb_addr * fileset)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
UDFVerifySequence(IN PDEVICE_OBJECT DeviceObject,IN PVCB Vcb,IN uint32 block,IN uint32 lastblock,OUT lb_addr * fileset)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
UDFLoadFileset(IN PVCB Vcb,IN PFILE_SET_DESC fset,OUT lb_addr * root,OUT lb_addr * sysstream)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
UDFIsCachedBadSequence(IN PVCB Vcb,IN uint32 Lba)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
UDFRememberBadSequence(IN PVCB Vcb,IN uint32 Lba,IN OSSTATUS RC)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
UDFLoadPartition(IN PDEVICE_OBJECT DeviceObject,IN PVCB Vcb,OUT lb_addr * fileset)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
UDFFindLastFileSet(IN PVCB Vcb,IN lb_addr * Addr,IN OUT PFILE_SET_DESC FileSetDesc)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
UDFLoadSparingTable(IN PVCB Vcb,IN PSPARABLE_PARTITION_MAP PartMap)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
UDFCheckZeroBuf(IN int8 * Buf,IN uint32 Length)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
UDFGetDiskInfoAndVerify(IN PDEVICE_OBJECT DeviceObject,IN PVCB Vcb)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