ReactOS  0.4.14-dev-50-g13bb5e2
phys_lib.cpp
Go to the documentation of this file.
1 // 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.
6 /*
7  Module Name: Phys_lib.cpp
8 
9  Execution: Kernel mode only
10 
11  Description:
12 
13  Contains code that implement read/write operations for physical device
14 */
15 
16 #include "phys_lib.h"
17 
18 static const char Signature [16] = {CDRW_SIGNATURE_v1};
19 
20 // Local functions:
21 
24  IN PVCB Vcb
25  );
26 
29  IN PVCB Vcb
30  );
31 
34  IN PVCB Vcb,
35  IN BOOLEAN WriteOp,
37  IN uint32 Lba,
38  IN uint32 BCount,
39  IN OUT uint32* retry);
40 
41 #ifdef _BROWSE_UDF_
42 
43 uint32
44 UDFFixFPAddress(
45  IN PVCB Vcb, // Volume control block from this DevObj
46  IN uint32 Lba
47  );
48 
49 #endif //_BROWSE_UDF_
50 
53  IN PVCB Vcb
54  )
55 {
56  UDFPrint(("UDFSyncCache:\n"));
57  OSSTATUS RC;
58  RC = UDFPhSendIOCTL( IOCTL_CDRW_SYNC_CACHE, Vcb->TargetDeviceObject,
59  NULL,0, NULL,0, FALSE, NULL);
60  if(OS_SUCCESS(RC)) {
61  // clear LAST_WRITE flag
62  Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
63  }
64  return RC;
65 } // end UDFSyncCache()
66 
67 
70  IN PVCB Vcb,
71  IN uint32 TrackNum
72  )
73 {
74 #ifdef _BROWSE_UDF_
75  if(Vcb->TrackMap) {
76  MyFreePool__(Vcb->TrackMap);
77  Vcb->TrackMap = NULL;
78  }
79  Vcb->TrackMap = (PUDFTrackMap)
80  MyAllocatePool__(NonPagedPool, TrackNum*sizeof(UDFTrackMap));
81  if(!Vcb->TrackMap) {
83  }
84 #endif //_BROWSE_UDF_
85  RtlZeroMemory(Vcb->TrackMap,TrackNum*sizeof(UDFTrackMap));
86  return STATUS_SUCCESS;
87 } // end UDFReallocTrackMap()
88 
89 #ifdef _BROWSE_UDF_
90 
91 
95  IN void* _Vcb,
96  IN void* Buffer, // Target buffer
98  IN uint32 LBA,
99  OUT PSIZE_T IOBytes,
100  IN uint32 Flags
101  )
102 {
104  uint32 i, j;
105  SIZE_T mask;
106  uint32 lba0, len, lba1;
107  PUCHAR tmp_buff;
108  PUCHAR p;
109  PCHAR cached_block;
110  SIZE_T tmp_wb;
111  BOOLEAN need_remap;
112  OSSTATUS final_RC = STATUS_SUCCESS;
113  BOOLEAN zero;
114  BOOLEAN non_zero;
115  BOOLEAN packet_ok;
116  BOOLEAN free_tmp = FALSE;
117  BOOLEAN single_packet = FALSE;
118 
119 #define Vcb ((PVCB)_Vcb)
120  // ATTENTION! Do not touch bad block bitmap here, since it describes PHYSICAL addresses WITHOUT remapping,
121  // while here we work with LOGICAL addresses
122 
123  if(Vcb->VerifyCtx.ItemCount > UDF_MAX_VERIFY_CACHE) {
124  UDFVVerify(Vcb, 0/*UFD_VERIFY_FLAG_WAIT*/);
125  }
126 
127  UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
128  Flags |= PH_IO_LOCKED;
129 
130  tmp_wb = (SIZE_T)_Vcb;
131  if(Flags & PH_EX_WRITE) {
132  UDFPrint(("IO-Write-Verify\n"));
133  RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN);
134  } else {
135  UDFPrint(("IO-Read-Verify\n"));
136  RC = UDFTRead(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_VCB_IN_RETLEN);
137  }
138  (*IOBytes) = tmp_wb;
139 
140  switch(RC) {
141  default:
142  UDFReleaseResource(&(Vcb->IoResource));
143  return RC;
147  break;
148  /* FALL THROUGH */
149  } // end switch(RC)
150 
151  if(!Vcb->SparingCount ||
152  !Vcb->SparingCountFree ||
153  Vcb->CDR_Mode) {
154  UDFPrint(("Can't remap\n"));
155  UDFReleaseResource(&(Vcb->IoResource));
156  return RC;
157  }
158 
159  if(Flags & PH_EX_WRITE) {
160  UDFPrint(("Write failed, try relocation\n"));
161  } else {
162  if(Vcb->Modified) {
163  UDFPrint(("Read failed, try relocation\n"));
164  } else {
165  UDFPrint(("no remap on not modified volume\n"));
166  UDFReleaseResource(&(Vcb->IoResource));
167  return RC;
168  }
169  }
170  if(Flags & PH_LOCK_CACHE) {
171  UDFReleaseResource(&(Vcb->IoResource));
172  WCacheStartDirect__(&(Vcb->FastCache), Vcb, TRUE);
173  UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
174  }
175 
177 
178  // NOTE: SparingBlockSize may be not equal to PacketSize
179  // perform recovery
180  mask = Vcb->SparingBlockSize-1;
181  lba0 = LBA & ~mask;
182  len = ((LBA+(Length>>Vcb->BlockSizeBits)+mask) & ~mask) - lba0;
183  j=0;
184  if((lba0 == LBA) && (len == mask+1) && (len == (Length>>Vcb->BlockSizeBits))) {
185  single_packet = TRUE;
186  tmp_buff = NULL;
187  } else {
188  tmp_buff = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->SparingBlockSize << Vcb->BlockSizeBits, 'bNWD');
189  if(!tmp_buff) {
190  UDFPrint((" can't alloc tmp\n"));
191  UDFReleaseResource(&(Vcb->IoResource));
193  }
194  free_tmp = TRUE;
195  }
196 
197  for(i=0; i<len; i++) {
198  if(!Vcb->SparingCountFree) {
199  UDFPrint((" no more free spare blocks, abort verification\n"));
200  break;
201  }
202  UDFPrint((" read LBA %x (%x)\n", lba0+i, j));
203  if(!j) {
204  need_remap = FALSE;
205  lba1 = lba0+i;
206  non_zero = FALSE;
207  if(single_packet) {
208  // single packet requested
209  tmp_buff = (PUCHAR)Buffer;
210  if(Flags & PH_EX_WRITE) {
211  UDFPrint((" remap single write\n"));
212  UDFPrint((" try del from verify cache @ %x, %x\n", lba0, len));
213  UDFVForget(Vcb, len, UDFRelocateSector(Vcb, lba0), 0);
214  goto do_remap;
215  } else {
216  UDFPrint((" recover and remap single read\n"));
217  }
218  }
219  }
220  p = tmp_buff+(j<<Vcb->BlockSizeBits);
221  // not cached, try to read
222  // prepare for error, if block cannot be read, assume it is zero-filled
223  RtlZeroMemory(p, Vcb->BlockSize);
224 
225  // check if block valid
226  if(Vcb->BSBM_Bitmap) {
227  if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), UDFRelocateSector(Vcb, lba0+i))) {
228  UDFPrint((" remap: known BB @ %x, mapped to %x\n", lba0+i, UDFRelocateSector(Vcb, lba0+i)));
229  need_remap = TRUE;
230  }
231  }
232  zero = FALSE;
233  if(Vcb->FSBM_Bitmap) {
234  if(UDFGetFreeBit((uint32*)(Vcb->FSBM_Bitmap), lba0+i)) {
235  UDFPrint((" unused @ %x\n", lba0+i));
236  zero = TRUE;
237  }
238  }
239  if(!zero && Vcb->ZSBM_Bitmap) {
240  if(UDFGetZeroBit((uint32*)(Vcb->ZSBM_Bitmap), lba0+i)) {
241  UDFPrint((" unused @ %x (Z)\n", lba0+i));
242  zero = TRUE;
243  }
244  }
245  non_zero |= !zero;
246 
247  if(!j) {
248  packet_ok = FALSE;
249  if(!single_packet) {
250  // try to read entire packet, this returs error more often then sequential reading of all blocks one by one
251  tmp_wb = (SIZE_T)_Vcb;
252  RC = UDFTRead(_Vcb, p, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba0+i, &tmp_wb,
254  } else {
255  // Note: we get here ONLY if original request failed
256  // do not retry if it was single-packet request
257  RC = STATUS_UNSUCCESSFUL;
258  }
259  if(RC == STATUS_SUCCESS) {
260  UDFPrint((" packet ok @ %x\n", lba0+i));
261  packet_ok = TRUE;
262  i += Vcb->SparingBlockSize-1;
263  continue;
264  } else {
265  need_remap = TRUE;
266  }
267  }
268 
269  if(!zero) {
270  if(WCacheIsCached__(&(Vcb->FastCache), lba0+i, 1)) {
271  // even if block is cached, we have to verify if it is readable
272  if(!packet_ok && !UDFVIsStored(Vcb, lba0+i)) {
273 
274  tmp_wb = (SIZE_T)_Vcb;
275  RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
277  if(!OS_SUCCESS(RC)) {
278  UDFPrint((" Found BB @ %x\n", lba0+i));
279  }
280 
281  }
282  RC = WCacheDirect__(&(Vcb->FastCache), _Vcb, lba0+i, FALSE, &cached_block, TRUE/* cached only */);
283  } else {
284  cached_block = NULL;
285  if(!packet_ok) {
286  RC = STATUS_UNSUCCESSFUL;
287  } else {
288  RC = STATUS_SUCCESS;
289  }
290  }
291  if(OS_SUCCESS(RC)) {
292  // cached or successfully read
293  if(cached_block) {
294  // we can get from cache the most fresh data
295  RtlCopyMemory(p, cached_block, Vcb->BlockSize);
296  }
297 
298  } else {
299  if(!UDFVIsStored(Vcb, lba0+i)) {
300  tmp_wb = (SIZE_T)_Vcb;
301  RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
303  } else {
304  // get it from verify-cache
305  RC = STATUS_UNSUCCESSFUL;
306  }
307  if(!OS_SUCCESS(RC)) {
308 /*
309  UDFPrint((" retry @ %x\n", lba0+i));
310  tmp_wb = (uint32)_Vcb;
311  RC = UDFTRead(_Vcb, p, Vcb->BlockSize, lba0+i, &tmp_wb,
312  Flags | PH_FORGET_VERIFIED | PH_READ_VERIFY_CACHE | PH_TMP_BUFFER | PH_VCB_IN_RETLEN);
313 */
314  UDFPrint((" try get from verify cache @ %x\n", lba0+i));
315  RC = UDFVRead(Vcb, p, 1, UDFRelocateSector(Vcb, lba0+i),
317  need_remap = TRUE;
318  }
319  }
320  } else {
321  RtlZeroMemory(p, Vcb->BlockSize);
322  }
323  if(!packet_ok) {
324  UDFPrint((" try del from verify cache @ %x\n", lba0+i));
325  RC = UDFVForget(Vcb, 1, UDFRelocateSector(Vcb, lba0+i), 0);
326  }
327 
328  if(!packet_ok || need_remap) {
329  UDFPrint((" block in bad packet @ %x\n", lba0+i));
330  if(Vcb->BSBM_Bitmap) {
331  UDFSetBit(Vcb->BSBM_Bitmap, lba0+i);
332  }
333  if(Vcb->FSBM_Bitmap) {
334  UDFSetUsedBit(Vcb->FSBM_Bitmap, lba0+i);
335  }
336  }
337 
338  j++;
339  if(j >= Vcb->SparingBlockSize) {
340  // remap this packet
341  if(need_remap) {
342  ASSERT(!packet_ok);
343  if(!non_zero) {
344  UDFPrint((" forget Z packet @ %x\n", lba1));
345  UDFUnmapRange(Vcb, lba1, Vcb->SparingBlockSize);
346  RC = STATUS_SUCCESS;
347  } else {
348 do_remap:
349  for(j=0; j<3; j++) {
350  UDFPrint((" remap packet @ %x\n", lba1));
351  RC = UDFRemapPacket(Vcb, lba1, FALSE);
352  if(!OS_SUCCESS(RC)) {
353  if(RC == STATUS_SHARING_VIOLATION) {
354  UDFPrint((" remap2\n"));
355  // remapped location have died
356  RC = UDFRemapPacket(Vcb, lba1, TRUE);
357  }
358  if(!OS_SUCCESS(RC)) {
359  // packet cannot be remapped :(
361  }
362  }
363  UDFPrint((" remap status %x\n", RC));
364  if(OS_SUCCESS(RC)) {
365  // write to remapped area
366  tmp_wb = (SIZE_T)_Vcb;
367  RC = UDFTWrite(_Vcb, tmp_buff, Vcb->SparingBlockSize << Vcb->BlockSizeBits, lba1, &tmp_wb,
369  UDFPrint((" write status %x\n", RC));
370  if(RC != STATUS_SUCCESS) {
371  // will be remapped
372  UDFPrint((" retry remap\n"));
373 
374  // Note: when remap of already remapped block is requested, verify of
375  // entire sparing are will be performed.
376 
377  } else {
378  UDFPrint((" remap OK\n"));
379  break;
380  }
381  } else {
382  UDFPrint((" failed remap\n"));
383  break;
384  }
385  } // for
386  }
387  if(!OS_SUCCESS(RC) && !OS_SUCCESS(final_RC)) {
388  final_RC = RC;
389  }
390  } else {
391  UDFPrint((" NO remap for @ %x\n", (lba0+i) & ~mask));
392  }
393  j=0;
394  }
395  }
396  if(free_tmp) {
397  DbgFreePool(tmp_buff);
398  }
399 
400  tmp_wb = (SIZE_T)_Vcb;
401  if(Flags & PH_EX_WRITE) {
402  UDFPrint(("IO-Write-Verify (2)\n"));
403  //RC = UDFTWrite(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN);
404  } else {
405  UDFPrint(("IO-Read-Verify (2)\n"));
406  RC = UDFTRead(_Vcb, Buffer, Length, LBA, &tmp_wb, Flags | PH_FORGET_VERIFIED | PH_VCB_IN_RETLEN);
407  }
408  (*IOBytes) = tmp_wb;
409  UDFPrint(("Final %x\n", RC));
410 
411  UDFReleaseResource(&(Vcb->IoResource));
412  if(Flags & PH_LOCK_CACHE) {
413  WCacheEODirect__(&(Vcb->FastCache), Vcb);
414  }
415 
416  return RC;
417 } // end UDFTIOVerify()
418 
419 OSSTATUS
421  IN void* _Vcb,
422  IN void* Buffer, // Target buffer
423  IN SIZE_T Length,
424  IN uint32 LBA,
425  OUT PSIZE_T WrittenBytes,
426  IN uint32 Flags
427  )
428 {
429  return UDFTIOVerify(_Vcb, Buffer, Length, LBA, WrittenBytes, Flags | PH_VCB_IN_RETLEN | PH_EX_WRITE | PH_KEEP_VERIFY_CACHE);
430 } // end UDFTWriteVerify()
431 
432 OSSTATUS
434  IN void* _Vcb,
435  IN void* Buffer, // Target buffer
436  IN SIZE_T Length,
437  IN uint32 LBA,
439  IN uint32 Flags
440  )
441 {
443 } // end UDFTReadVerify()
444 #endif //_BROWSE_UDF_
445 
446 /*
447  This routine performs low-level write
448 
449  ATTENTION! When we are in Variable-Packet mode (CDR_Mode = TRUE)
450  LBA is ignored and assumed to be equal to NWA by CD-R(W) driver
451  */
452 OSSTATUS
454  IN void* _Vcb,
455  IN void* Buffer, // Target buffer
456  IN SIZE_T Length,
457  IN uint32 LBA,
458  OUT PSIZE_T WrittenBytes,
459  IN uint32 Flags
460  )
461 {
462 #ifndef UDF_READ_ONLY_BUILD
463 #define Vcb ((PVCB)_Vcb)
464 
465 #ifdef _BROWSE_UDF_
466  PEXTENT_MAP RelocExtent;
467  PEXTENT_MAP RelocExtent_saved = NULL;
468 #endif //_BROWSE_UDF_
469  uint32 retry;
470  BOOLEAN res_acq = FALSE;
471 
473  uint32 rLba;
474  uint32 BCount;
475  uint32 i;
476 
477 #ifdef DBG
478  //ASSERT(!(LBA & (32-1)));
479 #endif //DBG
480 
481  (*WrittenBytes) = 0;
482  BCount = Length>>Vcb->BlockSizeBits;
483 
484  UDFPrint(("TWrite %x (%x)\n", LBA, BCount));
485 #ifdef _BROWSE_UDF_
486  if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD) {
487  UDFPrint(("DEAD\n"));
488  return STATUS_NO_SUCH_DEVICE;
489  }
490 
492  if(!Vcb->CDR_Mode) {
493  RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount);
494  if(!RelocExtent) {
495  UDFPrint(("can't relocate\n"));
497  }
498  rLba = LBA;
499  } else {
500  RelocExtent = UDF_NO_EXTENT_MAP;
501  rLba = Vcb->NWA;
502  }
503 #else //_BROWSE_UDF_
504  rLba = LBA;
505 #endif //_BROWSE_UDF_
506 
507 #ifdef DBG
508  //ASSERT(!(rLba & (32-1)));
509 #endif //DBG
510 
511  _SEH2_TRY {
512 #ifdef _BROWSE_UDF_
513 
514  if(!(Flags & PH_IO_LOCKED)) {
515  UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
516  res_acq = TRUE;
517  }
518 
519  if(RelocExtent == UDF_NO_EXTENT_MAP) {
520 #endif //_BROWSE_UDF_
521  retry = UDF_WRITE_MAX_RETRY;
522 retry_1:
523  RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount);
524  if(!OS_SUCCESS(RC)) {
525  UDFPrint(("prepare failed\n"));
526  try_return(RC);
527  }
528  if(Flags & PH_VCB_IN_RETLEN) {
529  (*WrittenBytes) = (ULONG_PTR)Vcb;
530  }
531  RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Buffer, Length,
532  ((uint64)rLba) << Vcb->BlockSizeBits, WrittenBytes, Flags);
533 #ifdef _BROWSE_UDF_
534  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
535 #endif //_BROWSE_UDF_
536  if(!OS_SUCCESS(RC) &&
537  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) )
538  goto retry_1;
539  UDFUpdateNWA((PVCB)_Vcb, rLba, BCount, RC);
540  try_return(RC);
541 #ifdef _BROWSE_UDF_
542  }
543  // write according to relocation table
544  RelocExtent_saved = RelocExtent;
545  for(i=0; RelocExtent->extLength; i++, RelocExtent++) {
546  SIZE_T _WrittenBytes;
547  rLba = RelocExtent->extLocation;
548  BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;
549  retry = UDF_WRITE_MAX_RETRY;
550 retry_2:
551  RC = UDFPrepareForWriteOperation(Vcb, rLba, BCount);
552  if(!OS_SUCCESS(RC)) {
553  UDFPrint(("prepare failed (2)\n"));
554  break;
555  }
556  if(Flags & PH_VCB_IN_RETLEN) {
557  _WrittenBytes = (ULONG_PTR)Vcb;
558  }
559  RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength,
560  ((uint64)rLba) << Vcb->BlockSizeBits, &_WrittenBytes, Flags);
561  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
562  if(!OS_SUCCESS(RC) &&
563  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, rLba, BCount, &retry)) )
564  goto retry_2;
565  UDFUpdateNWA((PVCB)_Vcb, rLba, BCount, RC);
566  LBA += BCount;
567  (*WrittenBytes) += _WrittenBytes;
568  if(!OS_SUCCESS(RC)) break;
569  *((uint32*)&Buffer) += RelocExtent->extLength;
570  }
571 #endif //_BROWSE_UDF_
572 try_exit: NOTHING;
573  } _SEH2_FINALLY {
574  if(res_acq) {
575  UDFReleaseResource(&(Vcb->IoResource));
576  }
577 #ifdef _BROWSE_UDF_
578  if(RelocExtent_saved) {
579  MyFreePool__(RelocExtent_saved);
580  }
581 #endif //_BROWSE_UDF_
582  } _SEH2_END;
583  UDFPrint(("TWrite: %x\n", RC));
584  return RC;
585 
586 #undef Vcb
587 #else //UDF_READ_ONLY_BUILD
588  return STATUS_ACCESS_DENIED;
589 #endif //UDF_READ_ONLY_BUILD
590 } // end UDFTWrite()
591 
592 /*
593  This routine performs low-level read
594  */
595 OSSTATUS
597  IN void* _Vcb,
598  IN void* Buffer, // Target buffer
599  IN SIZE_T Length,
600  IN uint32 LBA,
602  IN uint32 Flags
603  )
604 {
605  uint32 rLba;
607  uint32 retry;
608  PVCB Vcb = (PVCB)_Vcb;
609  uint32 BCount = Length >> Vcb->BlockSizeBits;
610  uint32 i;
611 #ifdef _BROWSE_UDF_
612  PEXTENT_MAP RelocExtent;
613  PEXTENT_MAP RelocExtent_saved = NULL;
614  BOOLEAN res_acq = FALSE;
615 // LARGE_INTEGER delay;
616  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
617 
618  ASSERT(Buffer);
619 
620  (*ReadBytes) = 0;
621 
622  if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD)
623  return STATUS_NO_SUCH_DEVICE;
624 
625  RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount);
626  if(!RelocExtent) return STATUS_INSUFFICIENT_RESOURCES;
627 
628  _SEH2_TRY {
629 
630  if(!(Flags & PH_IO_LOCKED)) {
631  UDFAcquireResourceExclusive(&(Vcb->IoResource), TRUE);
632  res_acq = TRUE;
633  }
634 
635  if(RelocExtent == UDF_NO_EXTENT_MAP) {
636  rLba = LBA;
637  if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
640  }
641  retry = UDF_WRITE_MAX_RETRY;
642 retry_1:
643  RC = UDFPrepareForReadOperation(Vcb, rLba, Length >> Vcb->BlockSizeBits);
644  if(!OS_SUCCESS(RC)) try_return(RC);
645  rLba = UDFFixFPAddress(Vcb, rLba);
646 #else
647  rLba = LBA;
648  retry = UDF_WRITE_MAX_RETRY;
649 retry_1:
650  RC = UDFPrepareForReadOperation(Vcb, rLba, Length >> Vcb->BlockSizeBits);
651  if(!OS_SUCCESS(RC)) return RC; // this is for !_BROWSE_UDF only
652 #endif //_BROWSE_UDF_
653  if(Flags & PH_VCB_IN_RETLEN) {
654  (*ReadBytes) = (SIZE_T)Vcb;
655  }
656  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Length,
657  ((uint64)rLba) << Vcb->BlockSizeBits, ReadBytes, Flags);
658  Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
659 #ifdef _BROWSE_UDF_
660  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
661 #endif //_BROWSE_UDF_
662  if(!OS_SUCCESS(RC) &&
663  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) {
664  if(RC != STATUS_BUFFER_ALL_ZEROS) {
665  goto retry_1;
666  }
668  (*ReadBytes) = Length;
669  RC = STATUS_SUCCESS;
670  }
671 #ifdef _BROWSE_UDF_
672  try_return(RC);
673  }
674  // read according to relocation table
675  RelocExtent_saved = RelocExtent;
676  for(i=0; RelocExtent->extLength; i++, RelocExtent++) {
677  SIZE_T _ReadBytes;
678  rLba = RelocExtent->extLocation;
679  if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
680  RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength);
681  RC = STATUS_SUCCESS;
682  goto TR_continue;
683  }
684  BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;
685  retry = UDF_WRITE_MAX_RETRY;
686 retry_2:
687  RC = UDFPrepareForReadOperation(Vcb, rLba, RelocExtent->extLength >> Vcb->BlockSizeBits);
688  if(!OS_SUCCESS(RC)) break;
689  rLba = UDFFixFPAddress(Vcb, rLba);
690  if(Flags & PH_VCB_IN_RETLEN) {
691  _ReadBytes = (SIZE_T)Vcb;
692  }
693  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength,
694  ((uint64)rLba) << Vcb->BlockSizeBits, &_ReadBytes, Flags);
695  Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
696  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
697  if(!OS_SUCCESS(RC) &&
698  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) ) {
699  if(RC != STATUS_BUFFER_ALL_ZEROS) {
700  goto retry_2;
701  }
702  RtlZeroMemory(Buffer, RelocExtent->extLength);
703  _ReadBytes = RelocExtent->extLength;
704  RC = STATUS_SUCCESS;
705  }
706 TR_continue:
707  (*ReadBytes) += _ReadBytes;
708  if(!OS_SUCCESS(RC)) break;
709  *((uint32*)&Buffer) += RelocExtent->extLength;
710  }
711 try_exit: NOTHING;
712  } _SEH2_FINALLY {
713  if(res_acq) {
714  UDFReleaseResource(&(Vcb->IoResource));
715  }
716  if(RelocExtent_saved) {
717  MyFreePool__(RelocExtent_saved);
718  }
719  } _SEH2_END;
720 #endif //_BROWSE_UDF_
721  return RC;
722 } // end UDFTRead()
723 
724 #ifdef UDF_ASYNC_IO
725 /*
726  This routine performs asynchronous low-level read
727  Is not used now.
728  */
729 OSSTATUS
730 UDFTReadAsync(
731  IN void* _Vcb,
732  IN void* _WContext,
733  IN void* Buffer, // Target buffer
734  IN SIZE_T Length,
735  IN uint32 LBA,
737  )
738 {
739  PEXTENT_MAP RelocExtent;
740  PEXTENT_MAP RelocExtent_saved;
742 // LARGE_INTEGER delay;
743  uint32 retry = UDF_READ_MAX_RETRY;
744  PVCB Vcb = (PVCB)_Vcb;
745  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
746  uint32 rLba;
747  uint32 BCount;
748 
749  ASSERT(Buffer);
750 
751  (*ReadBytes) = 0;
752 
753  RelocExtent = UDFRelocateSectors(Vcb, LBA, BCount = Length >> Vcb->BlockSizeBits);
754  if(!RelocExtent) return STATUS_INSUFFICIENT_RESOURCES;
755  if(RelocExtent == UDF_NO_EXTENT_MAP) {
756  rLba = LBA;
757  if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
759  return STATUS_SUCCESS;
760  }
761 retry_1:
762  RC = UDFPrepareForReadOperation(Vcb, rLba, BCount);
763  if(!OS_SUCCESS(RC)) return RC;
764  rLba = UDFFixFPAddress(Vcb, rLba);
765  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Length,
766  ((uint64)rLba) << Vcb->BlockSizeBits, ReadBytes, 0);
767  Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
768  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
769  if(!OS_SUCCESS(RC) &&
770  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) )
771  goto retry_1;
772  return RC;
773  }
774  // read according to relocation table
775  RelocExtent_saved = RelocExtent;
776  for(uint32 i=0; RelocExtent->extLength; i++, RelocExtent++) {
777  SIZE_T _ReadBytes;
778  rLba = RelocExtent->extLocation;
779  if(rLba >= (Vcb->CDR_Mode ? Vcb->NWA : Vcb->LastLBA + 1)) {
780  RtlZeroMemory(Buffer, _ReadBytes = RelocExtent->extLength);
781  RC = STATUS_SUCCESS;
782  goto TR_continue;
783  }
784  BCount = RelocExtent->extLength>>Vcb->BlockSizeBits;
785 retry_2:
786  RC = UDFPrepareForReadOperation(Vcb, rLba, RelocExtent->extLength >> Vcb->BlockSizeBits);
787  if(!OS_SUCCESS(RC)) break;
788  rLba = UDFFixFPAddress(Vcb, rLba);
789  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, RelocExtent->extLength,
790  ((uint64)rLba) << Vcb->BlockSizeBits, &_ReadBytes, 0);
791  Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
792  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
793  if(!OS_SUCCESS(RC) &&
794  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, FALSE, RC, rLba, BCount, &retry)) )
795  goto retry_2;
796 TR_continue:
797  (*ReadBytes) += _ReadBytes;
798  if(!OS_SUCCESS(RC)) break;
799  *((uint32*)&Buffer) += RelocExtent->extLength;
800  }
801  MyFreePool__(RelocExtent_saved);
802  return RC;
803 } // end UDFTReadAsync()
804 
805 #endif //UDF_ASYNC_IO
806 
807 /*
808 
809  */
810 NTSTATUS
812  IN PVCB Vcb
813  )
814 {
815  GET_MRW_MODE_USER_OUT MRWPage;
816  OSSTATUS RC;
817 
818  if(Vcb->MediaClassEx != CdMediaClass_CDRW)
819  return STATUS_SUCCESS;
820 //#ifdef _BROWSE_UDF_
821  if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM)
822  return STATUS_SUCCESS;
823 //#endif //_BROWSE_UDF_
824 
825  if(!Vcb->MRWStatus) {
826  UDFPrint(("Non-MRW disk. Skip setting MRW_MODE\n"));
827  return STATUS_SUCCESS;
828  }
829  UDFPrint(("try set MRW_MODE\n"));
830  RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_MRW_MODE, Vcb->TargetDeviceObject,
831  NULL,0,
832  (PVOID)&MRWPage,sizeof(MRWPage),
833  FALSE, NULL);
834  if(!NT_SUCCESS(RC)) {
835  return RC;
836  }
837  UDFPrint(("GET_MRW_MODE ok (current %x)\n", MRWPage.AddressMode));
838  MRWPage.AddressMode = Vcb->MRWStatus ? 0 : MrwPage_use_GAA;
839  UDFPrint(("SET_MRW_MODE %x\n", MRWPage.AddressMode));
840  RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_MRW_MODE, Vcb->TargetDeviceObject,
841  (PVOID)&MRWPage,sizeof(MRWPage),
842  NULL,0,
843  FALSE, NULL);
844  UDFPrint(("SET_MRW_MODE status %x\n", RC));
845 
846  return STATUS_SUCCESS;
847 } // end UDFSetMRWMode()
848 
849 OSSTATUS
851  IN PVCB Vcb
852  )
853 {
854  OSSTATUS RC;
855  if(Vcb->OPCNum && !Vcb->OPCDone) {
856  UDFPrint(("UDFDoOPC\n"));
857  if(!Vcb->OPCh) {
858  Vcb->OPCh =
861  }
862  if(!Vcb->OPCh)
864  Vcb->OPCh->DoOpc = TRUE;
865  Vcb->OPCh->OpcBlocksNumber = 0;
866  RC = UDFPhSendIOCTL(IOCTL_CDRW_SEND_OPC_INFO, Vcb->TargetDeviceObject,
867  (void*)(Vcb->OPCh),sizeof(SEND_OPC_INFO_HEADER_USER_IN),
868  NULL,0,
869  FALSE, NULL);
870  if(!OS_SUCCESS(RC)) {
871  UDFPrint(("UDFDoOPC failed\n"));
872  Vcb->OPCNum = 0;
873 // Vcb->VCBFlags |= UDF_VCB_FLAGS_OPC_FAILED;
874  }
875  Vcb->OPCDone = TRUE;
876  }
877  return RC;
878 } // end UDFDoOPC()
879 
880 /*
881  This routine performs media-type dependent preparations
882  for write operation.
883 
884  For CDR/RW it sets WriteParameters according to track parameters,
885  in some cases issues SYNC_CACHE command.
886  It can also send OPC info if requered.
887  If write-requested block is located beyond last formatted LBA
888  on incompletely formatted DVD media, this routine performs
889  all neccessary formatting operations in order to satisfy
890  subsequent write request.
891  */
892 OSSTATUS
894  IN PVCB Vcb,
895  IN uint32 Lba,
896  IN uint32 BCount
897  )
898 {
899 #ifndef UDF_READ_ONLY_BUILD
900 #ifdef UDF_FORMAT_MEDIA
901  PUDFFmtState fms = Vcb->fms;
902 #else
903  #define fms FALSE
904 #endif //UDF_FORMAT_MEDIA
905 
906 #ifdef _UDF_STRUCTURES_H_
907  if(Vcb->BSBM_Bitmap) {
908  ULONG i;
909  for(i=0; i<BCount; i++) {
910  if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), Lba+i)) {
911  UDFPrint(("W: Known BB @ %#x\n", Lba));
912  //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and
913  // we shall get IO request to BAD block
915  }
916  }
917  }
918 #endif //_UDF_STRUCTURES_H_
919 
920  Vcb->VCBFlags |= UDF_VCB_LAST_WRITE;
921 
922  if(
923 #ifdef _BROWSE_UDF_
924  (((Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM) ||
925  !(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_MOUNTED) ||
926  (Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK))
927  && !fms
928  ) ||
929 #endif //_BROWSE_UDF_
930 #ifdef UDF_FORMAT_MEDIA
931  (fms && fms->SkipPrepareW) ||
932 #endif //UDF_FORMAT_MEDIA
933  !(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER)
934  ) {
935  UDFPrint(("Skip prepare for Write @%x\n", Lba));
936  return STATUS_SUCCESS;
937  }
938 
939  // check if the device requires OPC before each write operation
940  UDFDoOPC(Vcb);
941 
942  if(Vcb->SyncCacheState == SYNC_CACHE_RECOVERY_ATTEMPT) {
943  Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_RETRY;
944  } else {
945  Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_NONE;
946  }
947  if(Vcb->LastModifiedTrack &&
948  (Vcb->TrackMap[Vcb->LastModifiedTrack].FirstLba <= Lba) &&
949  (Vcb->TrackMap[Vcb->LastModifiedTrack].LastLba >= Lba) &&
950  !( (Vcb->MediaClassEx == CdMediaClass_DVDRW ||
951  Vcb->MediaClassEx == CdMediaClass_DVDpRW ||
952  Vcb->MediaClassEx == CdMediaClass_DVDRAM ||
953  Vcb->MRWStatus == DiscInfo_BGF_Interrupted ||
954  Vcb->MRWStatus == DiscInfo_BGF_InProgress) && (Lba > Vcb->LastLBA))
955  ) {
956  // Ok, we needn't change Write Parameters
957 // if(Vcb->TrackMap[Vcb->LastModifiedTrack].Flags & TrackMap_Try_variation)
958 // Vcb->TrackMap[Vcb->LastModifiedTrack].Flags |= TrackMap_Use_variation;
959  UDFPrint(("Skip prepare for Write (2) @%x\n", Lba));
960  return STATUS_SUCCESS;
961  }
962 
964 
965  if(!UDFIsWriteParamsReq(Vcb)) {
966 #ifdef UDF_FORMAT_MEDIA
967  if(fms) {
968  return STATUS_SUCCESS;
969  }
970 #endif //UDF_FORMAT_MEDIA
971  }
972 
973  for(uint32 i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) {
974  if((Vcb->TrackMap[i].FirstLba > Lba) ||
975  (Vcb->TrackMap[i].LastLba < Lba)) {
976  //UDFPrint(("not in track %d\n"));
977  continue;
978  }
979  OSSTATUS RC;
980  PGET_WRITE_MODE_USER_OUT WParams;
981 
982  if(!UDFIsWriteParamsReq(Vcb)) {
983  RC = STATUS_SUCCESS;
984  goto check_dvd_bg_format;
985  }
986 
987  if(!Vcb->WParams) {
988  Vcb->WParams =
990  }
991  if(!(WParams = Vcb->WParams)) {
992  UDFPrint(("!WParams\n"));
994  }
995 
996  RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE, Vcb->TargetDeviceObject,
997  NULL,0,
998  (void*)(Vcb->WParams),sizeof(GET_WRITE_MODE_USER_OUT),
999  FALSE, NULL);
1000  if(!OS_SUCCESS(RC)) {
1001 #ifdef UDF_FORMAT_MEDIA
1002  if(fms) {
1003  fms->SkipPrepareW = 1;
1004  MyFreePool__(WParams);
1005  return STATUS_SUCCESS;
1006  }
1007 #endif //UDF_FORMAT_MEDIA
1008  UDFPrint(("!get WParams\n"));
1009  return RC;
1010  }
1011  // clear unnecassary flags
1012  WParams->Byte2.Flags &= ~WParam_TestWrite;
1013  WParams->Byte2.Flags &= ~WParam_WType_Mask;
1014  // select packet writing
1015  WParams->Byte2.Flags |= WParam_WType_Packet;
1016 
1017  WParams->Byte3.Flags &= ~(WParam_TrkMode_Mask |
1019  WParam_Copy);
1020  WParams->Byte3.Flags |= Vcb->TrackMap[i].TrackParam &
1023  WParam_Copy);
1024 
1025  // set packet type (VP/FP)
1026 // if(opt_partition == PT_VAT15 ||
1027 // opt_blank_vat15)
1028  if(WParams->Byte2.Flags & WParam_LS_V) {
1029  WParams->LinkSize = 7;
1030  }
1031 
1032  if(Vcb->TrackMap[i].DataParam & TrkInfo_Packet) {
1033  if((Vcb->TrackMap[i].DataParam & TrkInfo_FP) &&
1034  !Vcb->CDR_Mode) {
1035  WParams->Byte3.Flags |= WParam_FP;
1036  } else {
1037  WParams->Byte3.Flags &= ~WParam_FP;
1038  }
1039  } else {
1040  if(!Vcb->CDR_Mode) {
1041  WParams->Byte3.Flags |= WParam_FP;
1042  } else {
1043  WParams->Byte3.Flags &= ~WParam_FP;
1044  }
1045  }
1046 
1047  // select multisession mode
1048  WParams->Byte3.Flags &= ~WParam_MultiSes_Mask;
1049  if((Vcb->DiscStat & DiscInfo_Disk_Mask) == DiscInfo_Disk_Appendable) {
1050  WParams->Byte3.Flags |= WParam_Multises_Multi;
1051  } else
1052  if(Vcb->LastSession > 1) {
1053  WParams->Byte3.Flags |= WParam_Multises_Final;
1054  } else {
1055  WParams->Byte3.Flags |= WParam_Multises_None;
1056  }
1057  // set sector mode (Mode1/XA)
1058  WParams->Byte4.Flags &= ~WParam_BlkType_Mask;
1059  if((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask) == TrkInfo_Dat_XA) {
1060  // XA Mode2
1062  WParams->SesFmt = WParam_SesFmt_CdRomXa;
1063  } else if((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask) == TrkInfo_Dat_Mode1) {
1064  // Mode1
1065  WParams->Byte4.Flags |= WParam_BlkType_M1_2048;
1066  WParams->SesFmt = WParam_SesFmt_CdRom;
1067  } else {
1068 #ifdef UDF_FORMAT_MEDIA
1069  if(fms) {
1070  fms->SkipPrepareW = 1;
1071  MyFreePool__(WParams);
1072  return STATUS_SUCCESS;
1073  }
1074 #endif //UDF_FORMAT_MEDIA
1075  UDFPrint((" inv sector mode\n"));
1076  return STATUS_INVALID_PARAMETER;
1077  }
1078  // set packet size
1079  *((uint32*)&(WParams->PacketSize)) = BCount;
1080  *((uint32*)&(WParams->SubHeader)) = 0;
1081  // set additional flags for VP
1082 
1083  if(Vcb->CDR_Mode) {
1084 // if(opt_partition == PT_VAT15)
1085  WParams->SubHeader.Params.Params1.SubMode = WParam_SubHdr_SubMode1;
1086  }
1087  WParams->PageLength = sizeof(GET_WRITE_MODE_USER_OUT)-2;
1088  WParams->PageCode = MODE_PAGE_WRITE_PARAMS;
1089  // apply write parameters
1090  RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_WRITE_MODE, Vcb->TargetDeviceObject,
1091  (void*)WParams,sizeof(SET_WRITE_MODE_USER_IN),
1092  NULL,0,FALSE,NULL);
1093 
1094 #ifdef UDF_FORMAT_MEDIA
1095  if(fms) {
1096  if(!NT_SUCCESS(RC)) {
1097  fms->SkipPrepareW = 1;
1098  MyFreePool__(WParams);
1099  return STATUS_SUCCESS;
1100  }
1101 
1102  RC = UDFPhSendIOCTL(IOCTL_CDRW_GET_WRITE_MODE, Vcb->TargetDeviceObject,
1103  NULL,0,
1104  (PVOID)WParams,sizeof(GET_WRITE_MODE_USER_OUT),
1105  FALSE, NULL);
1106  if(!NT_SUCCESS(RC)) {
1107  MyFreePool__(WParams);
1108  return RC;
1109  }
1110 
1111  if(fms->opt_partition == PT_VAT15 ||
1112  fms->opt_blank_vat15) {
1113  if(WParams->Byte3.Flags & WParam_FP) {
1114  MyFreePool__(WParams);
1116  }
1117  } else {
1118  if(!(WParams->Byte3.Flags & WParam_FP)) {
1119  MyFreePool__(WParams);
1121  }
1122  }
1123  }
1124 #endif //UDF_FORMAT_MEDIA
1125 
1126  // switch to random access mode
1127  ((PSET_RANDOM_ACCESS_USER_IN)WParams)->RandomAccessMode = Vcb->CDR_Mode ? FALSE : TRUE;
1128 // ((PSET_RANDOM_ACCESS_USER_IN)WParams)->RandomAccessMode = (opt_partition != PT_VAT15) ? TRUE : FALSE;
1129  RC = UDFPhSendIOCTL(IOCTL_CDRW_SET_RANDOM_ACCESS, Vcb->TargetDeviceObject,
1130  (void*)WParams,sizeof(SET_RANDOM_ACCESS_USER_IN),
1131  NULL,0,FALSE, NULL);
1132 
1133 check_dvd_bg_format:
1134 
1135  UDFPrint((" check BGF\n"));
1136  if(!Vcb->CDR_Mode) {
1137  if(OS_SUCCESS(RC)) {
1138  Vcb->LastModifiedTrack = i;
1139  if(!(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)) {
1140  if(Vcb->TrackMap[i].Flags & TrackMap_Try_variation) {
1141  Vcb->TrackMap[i].Flags |= TrackMap_Use_variation;
1142  } else {
1143  Vcb->TrackMap[i].Flags |= TrackMap_Try_variation;
1144  }
1145  }
1146  }
1147  } else {
1148  Vcb->LastModifiedTrack = 0;
1149  }
1150 // fms->SkipPrepareW = 1;
1151 
1152 
1153  if((Vcb->MediaClassEx == CdMediaClass_DVDRW ||
1154  Vcb->MediaClassEx == CdMediaClass_DVDpRW ||
1155  Vcb->MediaClassEx == CdMediaClass_DVDRAM ||
1156  Vcb->MRWStatus == DiscInfo_BGF_Interrupted )
1157  && (Lba > Vcb->LastLBA)) {
1158 
1159  ULONG fLba;
1160  SIZE_T WrittenBytes;
1161  ULONG PSz = BCount << Vcb->BlockSizeBits;
1162 #ifdef _BROWSE_UDF_
1163  ULONG retry;
1164 #endif //_BROWSE_UDF_
1166 
1167  ASSERT((Vcb->LastLBA+1) == Vcb->NWA);
1168 
1169  if(Lba+BCount <= (Vcb->LastLBA+1) ) {
1170  UDFPrint(("DVD cont. fmt, LBA+BCount<=NWA, exiting\n"));
1171  return STATUS_SUCCESS;
1172  }
1173  if((Vcb->MRWStatus != DiscInfo_BGF_Interrupted) &&
1174  (Lba <= (Vcb->LastLBA+1)) ) {
1175  UDFPrint(("!PausedBGF + DVD cont. fmt, LBA<=NWA, exiting\n"));
1176  return STATUS_SUCCESS;
1177  }
1178 
1179  if(Vcb->MRWStatus == DiscInfo_BGF_Interrupted) {
1180  // This code also can restart background MRW formatting
1181  UDFPrint(("DVD cont. fmt, LastLBA %x, Lba %x\n", Vcb->LastLBA, Lba));
1182 
1184  if(ForBuf) {
1186  ForBuf->Flags.FlagsEx = FORMAT_UNIT_RESTART_MRW;
1187  ForBuf->BlockCount = 0xffffffff;
1188 
1189  RC = UDFPhSendIOCTL(IOCTL_CDRW_FORMAT_UNIT, Vcb->TargetDeviceObject,
1190  ForBuf,sizeof(FORMAT_CDRW_PARAMETERS_USER_IN),
1191  NULL,0,FALSE, NULL);
1192  DbgFreePool(ForBuf);
1193  if(OS_SUCCESS(RC)) {
1194  UDFPrint(("BGFormat restarted Interrupted->InProgress\n"));
1195  Vcb->MRWStatus = DiscInfo_BGF_InProgress;
1196  } else {
1198  if(!Vcb->Error) {
1199  Vcb->Error = (PGET_LAST_ERROR_USER_OUT)
1201  }
1202  Error = Vcb->Error;
1203  if(Error) {
1204  UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR, Vcb->TargetDeviceObject,
1205  NULL,0,
1207  TRUE,NULL);
1208  UDFPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n",
1209  Error->SenseKey, Error->AdditionalSenseCode, Error->AdditionalSenseCodeQualifier, Error->LastError));
1210  // check for Long Write In Progress
1211  if( (Error->SenseKey == SCSI_SENSE_NOT_READY) &&
1212  (Error->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) &&
1213  ((Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS) ||
1214  (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_FORMAT_IN_PROGRESS)) ) {
1215  RC = STATUS_SUCCESS;
1216  UDFPrint(("Seems, BGFormat already restarted\n"));
1217  Vcb->MRWStatus = DiscInfo_BGF_InProgress;
1218  }
1219  }
1220  }
1221  }
1222  } else {
1223  RC = STATUS_SUCCESS;
1224  }
1225 
1226  UDFPrint(("DVD cont. write, LastLBA %x, Lba %x\n", Vcb->LastLBA, Lba));
1227 
1228  ASSERT(Vcb->MediaClassEx == CdMediaClass_DVDRW);
1229  if(!Vcb->fZBuffer) {
1230  Vcb->fZBuffer = (PCHAR)DbgAllocatePoolWithTag(NonPagedPool, PSz, 'zNWD');
1231  RtlZeroMemory(Vcb->fZBuffer, PSz);
1232  Vcb->fZBufferSize = PSz;
1233  } else
1234  if(Vcb->fZBufferSize < PSz) {
1235  PSz = Vcb->fZBufferSize;
1236  }
1237  if(!Vcb->fZBuffer) {
1238  BrutePoint();
1240  } else {
1241  for(fLba = Vcb->NWA; fLba < Lba; fLba+=BCount) {
1242 #ifdef _BROWSE_UDF_
1243  retry = UDF_WRITE_MAX_RETRY;
1244 retry_1:
1245 #endif //_BROWSE_UDF_
1246  RC = UDFPhWriteVerifySynchronous(Vcb->TargetDeviceObject, Vcb->fZBuffer, PSz,
1247  ((uint64)fLba) << Vcb->BlockSizeBits, &WrittenBytes, PH_TMP_BUFFER);
1248  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
1249  UDFPrint(("Fmt status: %x\n", RC));
1250 #ifdef _BROWSE_UDF_
1251  if(!OS_SUCCESS(RC) &&
1252  OS_SUCCESS(RC = UDFRecoverFromError(Vcb, TRUE, RC, fLba, BCount, &retry)) ) {
1253  goto retry_1;
1254  UDFPrint(("Fmt retry\n"));
1255  }
1256 #endif //_BROWSE_UDF_
1257  if(!OS_SUCCESS(RC)) {
1258  BrutePoint();
1259  UDFPrint(("Fmt break on ERROR\n"));
1260  break;
1261  }
1262  UDFUpdateNWA(Vcb, fLba, BCount, RC);
1263  }
1264  }
1265  } else {
1266  UDFPrint((" no special processing\n"));
1267  }
1268 
1269  return RC;
1270  }
1271 #endif //UDF_READ_ONLY_BUILD
1272  UDFPrint((" no suitable track!\n"));
1273  return STATUS_INVALID_PARAMETER;
1274 } // end UDFPrepareForWriteOperation()
1275 
1276 //#ifdef _BROWSE_UDF_
1277 /*
1278  This routine tries to recover from hardware error
1279  Return: STATUS_SUCCESS - retry requst
1280  STATUS_XXX - unrecoverable error
1281  */
1282 OSSTATUS
1284  IN PVCB Vcb,
1285  IN BOOLEAN WriteOp,
1286  IN OSSTATUS status,
1287  IN uint32 Lba,
1288  IN uint32 BCount,
1289  IN OUT uint32* retry
1290  )
1291 {
1294 // OSSTATUS RC;
1295  uint32 i;
1296  BOOLEAN UpdateBB = FALSE;
1297 
1298  if(!(*retry) ||
1299  !(Vcb->VCBFlags & UDF_VCB_FLAGS_OUR_DEVICE_DRIVER) ||
1300  (Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM))
1301  return status;
1302  (*retry)--;
1303  // allocate tmp buffer
1304  _SEH2_TRY {
1305  if(!Vcb->Error) {
1306  if(!(Vcb->Error = (PGET_LAST_ERROR_USER_OUT)
1308  try_return(status);
1309  }
1310  if(status == STATUS_NO_SUCH_DEVICE) {
1311  UDFPrint(("Error recovery: STATUS_NO_SUCH_DEVICE, die.....\n"));
1313  try_return(status);
1314  }
1315 
1316 #ifdef _UDF_STRUCTURES_H_
1317  if(status == STATUS_NO_MEDIA_IN_DEVICE && !Vcb->EjectWaiter) {
1318  UDFPrint(("Error recovery: STATUS_NO_MEDIA_IN_DEVICE, prevent further remount.....\n"));
1319  // Make sure, that volume will never be quick-remounted
1320  // It is very important for ChkUdf utility and
1321  // some CD-recording libraries
1322  Vcb->SerialNumber--;
1323  try_return(status);
1324  }
1325 #endif //_UDF_STRUCTURES_H_
1326 
1327  Error = Vcb->Error;
1328  UDFPhSendIOCTL( IOCTL_CDRW_GET_LAST_ERROR, Vcb->TargetDeviceObject,
1329  NULL,0,
1331  TRUE,NULL);
1332  UDFPrint(("SK=%x ASC=%x, ASCQ=%x, IE=%x\n",
1333  Error->SenseKey, Error->AdditionalSenseCode, Error->AdditionalSenseCodeQualifier, Error->LastError));
1334  // check for Long Write In Progress
1335  if( ((Error->SenseKey == SCSI_SENSE_NOT_READY) &&
1336  (Error->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) &&
1337  (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_LONG_WRITE_IN_PROGRESS)) ) {
1338  // we should wait...
1339  if(WriteOp) {
1340  if((*retry) == UDF_WRITE_MAX_RETRY-1) {
1341  UDFPrint(("Error recovery: reserve retry count for write retries\n"));
1342  (*retry) = UDF_WRITE_MAX_RETRY*3;
1343  } else
1344  if((*retry) == UDF_WRITE_MAX_RETRY) {
1345  UDFPrint(("Error recovery: jump over UDF_WRITE_MAX_RETRY\n"));
1346  (*retry)--;
1347  }
1348  delay.QuadPart = -500000; // 0.05 sec
1350  if(WriteOp && ((*retry) > UDF_WRITE_MAX_RETRY-1)) {
1351  UDFPrint(("Error recovery: simple write retry with delay\n"));
1353  }
1354  } else {
1355  delay.QuadPart = -500000; // 0.05 sec
1357  if((*retry) == UDF_WRITE_MAX_RETRY-1) {
1358  UDFPrint(("Error recovery: retry read after small delay\n"));
1360  }
1361  }
1362  UDFPrint(("Error recovery: sync cache\n"));
1363  // ...flush device cache...
1364  UDFSyncCache(Vcb);
1365  // wait again & retry
1366  delay.QuadPart = -1000000; // 0.1 sec
1368 #ifdef _UDF_STRUCTURES_H_
1369  if(Vcb->BGWriters) (*retry)++;
1370 #endif //_UDF_STRUCTURES_H_
1372  } else
1373  // check for Long Write In Progress
1374  if((Error->SenseKey == SCSI_SENSE_NOT_READY) &&
1375  (Error->AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY) &&
1376  ((Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_FORMAT_IN_PROGRESS) ||
1377  (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_BECOMING_READY) ||
1378  (Error->AdditionalSenseCodeQualifier == SCSI_SENSEQ_OPERATION_IN_PROGRESS) ) ) {
1379  // we should wait & retry
1380  UDFPrint(("Error recovery: op. in progress, waiting 0.3 sec\n"));
1381  delay.QuadPart = -3000000; // 0.3 sec
1383 #ifdef _UDF_STRUCTURES_H_
1384  if(Vcb->BGWriters) (*retry)++;
1385 #endif //_UDF_STRUCTURES_H_
1386  Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_ATTEMPT;
1388  } else
1389  // check for non empty cache special case
1390  if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1391  (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_CMD_SEQUENCE)) {
1392  // we should wait & retry
1393  if(!WriteOp) {
1394  UDFPrint(("Error recovery: invalid command sequence on read\n"));
1395  delay.QuadPart = -1000000; // 0.1 sec
1397  UDFPrint(("Error recovery: sync cache\n"));
1398  // ...flush device cache...
1399  UDFSyncCache(Vcb);
1400  // wait again & retry
1401  delay.QuadPart = -1000000; // 0.1 sec
1403 #ifdef _UDF_STRUCTURES_H_
1404  if(Vcb->BGWriters) (*retry)++;
1405 #endif //_UDF_STRUCTURES_H_
1407  }
1408  goto reinit_sector_mode;
1409  } else
1410  // check for Bus Reset (sometimes it happends...)
1411  if((Error->SenseKey == SCSI_SENSE_UNIT_ATTENTION) &&
1412  (Error->AdditionalSenseCode == SCSI_ADSENSE_BUS_RESET) ) {
1413  // we should wait
1414  UDFPrint(("Error recovery: bus reset...\n"));
1415  Vcb->MediaChangeCount = Error->MediaChangeCount;
1416  delay.QuadPart = -1000000; // 0.1 sec
1418  // reset driver
1419  UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, FALSE);
1420  delay.QuadPart = -1000000; // 0.1 sec
1422  // lock it
1423 /* ((PPREVENT_MEDIA_REMOVAL_USER_IN)(Error))->PreventMediaRemoval = TRUE;
1424  UDFPhSendIOCTL( IOCTL_STORAGE_MEDIA_REMOVAL,
1425  Vcb->TargetDeviceObject,
1426  Error,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
1427  NULL,0,
1428  FALSE,NULL);
1429  delay.QuadPart = -1000000; // 0.1 sec
1430  KeDelayExecutionThread(KernelMode, FALSE, &delay);*/
1431 
1432  // reinit write mode the following is performed inside UDFResetDeviceDriver()
1433  //Vcb->LastModifiedTrack = 0;
1434  //Vcb->OPCDone = FALSE;
1435 
1436 reinit_sector_mode:
1437  // reinit sector mode
1438  Vcb->LastModifiedTrack = 0;
1439  UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1441  } else
1442  // check for Illegal Sector Mode.
1443  // We can get this error 'cause of 2 reasons:
1444  // a) Bus reset occured. We should reinit
1445  // b) CopyProtection settings missmatch
1446  // c) preblems with DNA of firmware developer, some TEACs fall into such state
1447  // after failed streaming read
1448  if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1449  (Error->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_MODE_FOR_THIS_TRACK)) {
1450 bad_rw_seek_recovery:
1451  if(WriteOp) {
1452 
1453  if((*retry) <= 1) {
1454  // Variate CopyProtection...
1455  for(i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) {
1456  if((Vcb->TrackMap[i].FirstLba > Lba) ||
1457  (Vcb->TrackMap[i].LastLba < Lba))
1458  continue;
1459  /* if(Vcb->TrackMap[i].Flags & TrackMap_CopyBit_variated)
1460  // Last chance....
1461  goto reinit_sector_mode;*/
1462 
1463  // check if we have successuflly completed WriteOp
1464  // using Variation.
1465  // We should not variate these bits again in this case.
1466  if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)
1467  break;
1468  Vcb->TrackMap[i].Flags &= ~TrackMap_Try_variation;
1469  /* if((Vcb->TrackMap[i].Flags & TrackMap_Try_variation) &&
1470  (Vcb->TrackMap[i].Flags & (TrackMap_AllowCopyBit_variated |
1471  TrackMap_CopyBit_variated)))
1472  break;*/
1473  /* if(Vcb->TrackMap[i].Flags & TrackMap_Use_variation)
1474  break;*/
1475  Vcb->TrackMap[i].Flags |= TrackMap_Try_variation;
1476  // Try variation.
1477  if(!(Vcb->TrackMap[i].Flags ^= TrackMap_AllowCopyBit_variated))
1478  Vcb->TrackMap[i].Flags ^= TrackMap_CopyBit_variated;
1479  if(Vcb->TrackMap[i].Flags & (TrackMap_AllowCopyBit_variated |
1481  (*retry) = 1;
1482  } else {
1483  Vcb->TrackMap[i].Flags &= ~TrackMap_Try_variation;
1484  }
1485  // reinit sector mode
1486  Vcb->LastModifiedTrack = 0;
1487  UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1488  break;
1489  }
1490  } else {
1491  // Reinit...
1492 //reinit_sector_mode:
1493  // we should wait
1494  delay.QuadPart = -1000000; // 0.1 sec
1496  // reinit sector mode
1497  goto reinit_sector_mode;
1498 /*
1499  Vcb->LastModifiedTrack = 0;
1500  UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1501  try_return(status = STATUS_SUCCESS);
1502 */
1503  }
1504  } else
1505  if((Vcb->CompatFlags & UDF_VCB_IC_BAD_RW_SEEK) &&
1506  (Vcb->IncrementalSeekState != INCREMENTAL_SEEK_DONE)) {
1507  UDFPrint(("Using incremental seek workaround...\n"));
1508  Vcb->IncrementalSeekState = INCREMENTAL_SEEK_WORKAROUND;
1510  } else {
1511  UDFPrint(("Seems to be BB @ %x\n", Lba));
1512  UpdateBB = TRUE;
1513  }
1514  } else
1515  if((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1516  (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_SESSION_MODE)) {
1517  if(WriteOp &&
1518  (Vcb->SavedFeatures & CDRW_FEATURE_STREAMING) &&
1519  Lba+BCount <= Vcb->LastLBA+1) {
1520  UDFPrint(("bad Session in streaming mode. Lba %x, try fix-up\n", Lba));
1521  // ...flush device cache...
1522  UDFSyncCache(Vcb);
1523  // we should wait
1524  delay.QuadPart = -10000000; // 1 sec
1527  }
1528  } else
1529  if((Error->LastError == CDRW_ERR_WRITE_IN_PROGRESS_BUSY) ||
1530  (status == STATUS_DEVICE_BUSY)) {
1531  delay.QuadPart = -5000000; // 0.5 sec
1532  UDFPrint(("CDRW_ERR_WRITE_IN_PROGRESS_BUSY || STATUS_DEVICE_BUSY\n"));
1534 #ifdef _UDF_STRUCTURES_H_
1535  if(Vcb->BGWriters) (*retry)++;
1536 #endif //_UDF_STRUCTURES_H_
1538  } else
1539  // some devices (SONY) return such a strange sequence....
1540  if( ((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1541  (Error->AdditionalSenseCode == SCSI_ADSENSE_INVALID_CDB)) &&
1542  WriteOp) {
1543  // reinit write mode
1544  Vcb->LastModifiedTrack = 0;
1545  UDFPrepareForWriteOperation(Vcb, Lba, BCount);
1547  } else
1548  // No seek on Read... to morgue, I'm afraid
1549  if((Error->SenseKey == SCSI_SENSE_MEDIUM_ERROR) /*&&
1550  ((Error->AdditionalSenseCode == SCSI_ADSENSE_CD_READ_ERROR) ||
1551  (Error->AdditionalSenseCode == SCSI_ADSENSE_NO_SENSE) ||
1552  (Error->AdditionalSenseCode == SCSI_ADSENSE_FORMAT_CORRUPTED) ||
1553  (Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR))*/ &&
1554  !WriteOp) {
1555  if(Error->AdditionalSenseCode == SCSI_ADSENSE_SEEK_ERROR) {
1556  UDFPrint(("Seek error\n"));
1557  if(Vcb->CompatFlags & UDF_VCB_IC_BAD_RW_SEEK) {
1558  UDFPrint(("try recovery\n"));
1559  goto bad_rw_seek_recovery;
1560  }
1561  UDFPrint(("map error to STATUS_NONEXISTENT_SECTOR\n"));
1563  }
1564  UDFPrint(("Seems to be BB @ %x (read 2)\n", Lba));
1565  UpdateBB = TRUE;
1566  } else
1567  // handle invalid block address
1568  if( ((Error->SenseKey == SCSI_SENSE_ILLEGAL_REQUEST) &&
1569  (Error->AdditionalSenseCode == SCSI_ADSENSE_ILLEGAL_BLOCK)) ) {
1570  if(!WriteOp &&
1571  (Vcb->SavedFeatures & CDRW_FEATURE_STREAMING) &&
1572  Lba+BCount <= Vcb->LastLBA+1) {
1573  UDFPrint(("bad LBA %x in streaming mode, try fix-up\n", Lba));
1574  // ...flush device cache...
1575  UDFSyncCache(Vcb);
1577  }
1578 
1579  if((Lba+BCount >= Vcb->LastLBA) &&
1580  (Vcb->MRWStatus == DiscInfo_BGF_Interrupted)) {
1581  UDFPrint(("stupid drive, cannot read beyond formatted area on DiscInfo_BGF_Interrupted\n"));
1582  UpdateBB = FALSE;
1584  }
1585  // prevent Bad Block Bitmap modification
1586  }
1587 
1588 try_exit: NOTHING;
1589 
1590  } _SEH2_FINALLY {
1591 #ifdef UDF_DBG
1592  if(OS_SUCCESS(status)) {
1593  UDFPrint(("Retry\n"));
1594  }
1595 #endif //UDF_DBG
1596  } _SEH2_END;
1597  if(!OS_SUCCESS(status)) {
1598  if((Vcb->MountPhErrorCount != (ULONG)-1) &&
1599  (Vcb->MountPhErrorCount < 0x7fffffff)) {
1600  Vcb->MountPhErrorCount++;
1601  }
1602 //#ifdef _UDF_STRUCTURES_H_
1603  if(UpdateBB && (BCount == 1)) {
1604  uint32* bm;
1605  if(!(bm = (uint32*)(Vcb->BSBM_Bitmap))) {
1606  bm = (uint32*)(Vcb->BSBM_Bitmap = (int8*)DbgAllocatePoolWithTag(NonPagedPool, (i = (Vcb->LastPossibleLBA+1+7)>>3), 'mNWD' ));
1607  if(bm) {
1608  RtlZeroMemory(bm, i);
1609  } else {
1610  UDFPrint(("Can't alloc BSBM for %x blocks\n", Vcb->LastPossibleLBA));
1611  }
1612  }
1613  if(bm) {
1614  UDFSetBit(bm, Lba);
1615  UDFPrint(("Set BB @ %#x\n", Lba));
1616  }
1617 #ifdef _BROWSE_UDF_
1618  bm = (uint32*)(Vcb->FSBM_Bitmap);
1619  if(bm) {
1620  UDFSetUsedBit(bm, Lba);
1621  UDFPrint(("Set BB @ %#x as used\n", Lba));
1622  }
1623 #endif //_BROWSE_UDF_
1624  }
1625 //#endif //_UDF_STRUCTURES_H_
1626  }
1627  return status;
1628 } // end UDFRecoverFromError()
1629 
1630 //#endif //_BROWSE_UDF_
1631 /*
1632  This routine attempts to read disk layout using ReadDisk/Track info cmd
1633  */
1634 OSSTATUS
1636  PDEVICE_OBJECT DeviceObject, // the target device object
1637  PVCB Vcb // Volume Control Block for ^ DevObj
1638  )
1639 {
1640  OSSTATUS RC = STATUS_SUCCESS;
1643  PTRACK_INFO_BLOCK_USER_IN TrackInfoIn = (PTRACK_INFO_BLOCK_USER_IN)TrackInfoOut;
1644  READ_CAPACITY_USER_OUT CapacityBuffer;
1645  LONG TrackNumber;
1646  BOOLEAN NotFP = FALSE;
1647  BOOLEAN ForceFP = FALSE;
1648  BOOLEAN PacketTrack = FALSE;
1649  BOOLEAN MRWRetry = FALSE;
1650 // BOOLEAN ReadCapacityOk = FALSE;
1651 #ifdef UDF_FORMAT_MEDIA
1652  PUDFFmtState fms = Vcb->fms;
1653 #endif
1654 
1655  _SEH2_TRY {
1656  if(!DiscInfo || !TrackInfoOut)
1658 
1659 MRWRetry_label:
1660 
1662  NULL, 0,
1663  DiscInfo,sizeof(DISC_INFO_BLOCK_USER_OUT), TRUE, NULL);
1664  if(!OS_SUCCESS(RC)) {
1665  UDFPrint(("ReadDiskInfo failed. Use default.\n"));
1666  if(Vcb->MediaClassEx == CdMediaClass_DVDRW ||
1667  Vcb->MediaClassEx == CdMediaClass_DVDpRW ||
1668  Vcb->MediaClassEx == CdMediaClass_DVDRAM) {
1669  Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD;
1670  } else
1671  if(Vcb->MediaClassEx == CdMediaClass_BDRE) {
1672  Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_BD;
1673  } else {
1674  Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD;
1675  }
1676  try_return(RC);
1677  }
1678 #ifdef UDF_FORMAT_MEDIA
1679  if(fms && fms->opt_disk_info) {
1680  UserPrint(("ReadDiskInfo OK\n"));
1681  }
1682 #endif //UDF_FORMAT_MEDIA
1683 
1685  NULL, 0,
1686  &CapacityBuffer,sizeof(READ_CAPACITY_USER_OUT), TRUE, NULL);
1687  if(!OS_SUCCESS(RC)) {
1688  UDFPrint(("ReadCapacity failed.\n"));
1689  if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
1690  Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD;
1691  }
1692  } else {
1693  UDFPrint(("ReadCapacity ok.\n"));
1694  UDFPrint(("Last possible LBA %#x.\n", CapacityBuffer.LogicalBlockAddress));
1695  if(!(CapacityBuffer.LogicalBlockAddress & 0xc0000000) &&
1696  (CapacityBuffer.LogicalBlockAddress != 0x7fffffff)) {
1697  // good value from ReadCapacity
1698  UDFPrint(("Update Last possible LBA %#x.\n", CapacityBuffer.LogicalBlockAddress));
1699  Vcb->LastPossibleLBA = CapacityBuffer.LogicalBlockAddress;
1700 // ReadCapacityOk = TRUE;
1701 #ifdef UDF_FORMAT_MEDIA
1702  if(fms && fms->opt_disk_info) {
1703  UserPrint(("ReadCapacity OK\n"));
1704  }
1705 #endif //UDF_FORMAT_MEDIA
1706  }
1707  }
1708 
1709 #ifdef _CONSOLE
1710  Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
1711 #endif //_CONSOLE
1712  Vcb->PhSerialNumber = *((uint32*)&(DiscInfo->DiskId));
1713  Vcb->PhErasable = DiscInfo->DiscStat.Flags & DiscInfo_Disk_Erasable;
1714  Vcb->PhDiskType = DiscInfo->DiskType;
1715  // save OPC info
1716  if(DiscInfo->OPCNum)
1717  Vcb->OPCNum = DiscInfo->OPCNum;
1718  UDFPrint(("DiskInfo: SN %x, OPCn %x(%x), Stat %x, Flg: %x\n",
1719  Vcb->PhSerialNumber, Vcb->OPCNum, DiscInfo->OPCNum, DiscInfo->DiscStat.Flags, DiscInfo->Flags.Flags));
1720 #ifdef UDF_FORMAT_MEDIA
1721  if(fms && fms->opt_disk_info) {
1722  UserPrint(("Media type: "));
1723  switch(Vcb->MediaClassEx) {
1724  case CdMediaClass_CDROM : UserPrint(("CD-ROM \n")); break;
1725  case CdMediaClass_CDR : UserPrint(("CD-R \n")); break;
1726  case CdMediaClass_CDRW : UserPrint(("CD-RW \n")); break;
1727  case CdMediaClass_DVDROM : UserPrint(("DVD-ROM \n")); break;
1728  case CdMediaClass_DVDRAM : UserPrint(("DVD-RAM \n")); break;
1729  case CdMediaClass_DVDR : UserPrint(("DVD-R \n")); break;
1730  case CdMediaClass_DVDRW : UserPrint(("DVD-RW \n")); break;
1731  case CdMediaClass_DVDpR : UserPrint(("DVD+R \n")); break;
1732  case CdMediaClass_DVDpRW : UserPrint(("DVD+RW \n")); break;
1733  case CdMediaClass_DDCDROM : UserPrint(("DDCD-ROM \n")); break;
1734  case CdMediaClass_DDCDR : UserPrint(("DDCD-R \n")); break;
1735  case CdMediaClass_DDCDRW : UserPrint(("DDCD-RW \n")); break;
1736  case CdMediaClass_BDROM : UserPrint(("BD-ROM \n")); break;
1737  case CdMediaClass_BDRE : UserPrint(("BD-RE \n")); break;
1738  case CdMediaClass_BDR : UserPrint(("BD-R \n")); break;
1739  case CdMediaClass_HD_DVDROM : UserPrint(("HD DVD-ROM \n")); break;
1740  case CdMediaClass_HD_DVDRAM : UserPrint(("HD DVD-RAM \n")); break;
1741  case CdMediaClass_HD_DVDR : UserPrint(("HD DVD-R \n")); break;
1742  case CdMediaClass_HD_DVDRW : UserPrint(("HD DVD-RW \n")); break;
1743  default: UserPrint(("Unknown\n")); break;
1744  }
1745  UserPrint(("SN %#x, OPCn %#x\n",
1746  Vcb->PhSerialNumber, Vcb->OPCNum, DiscInfo->OPCNum));
1747  UserPrint(("Disk State: "));
1748  switch(DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) {
1749  case DiscInfo_Disk_Empty:
1750  UserPrint(("Empty\n"));
1751  break;
1753  UserPrint(("Appendable\n"));
1754  break;
1756  UserPrint(("Complete\n"));
1757  break;
1758  case DiscInfo_Disk_OtherRW:
1759  UserPrint(("RW in unknown state\n"));
1760  break;
1761  }
1762  UserPrint(("Last Session State: "));
1763  switch(DiscInfo->DiscStat.Flags & DiscInfo_Ses_Mask) {
1764  case DiscInfo_Ses_Empty:
1765  UserPrint(("Empty\n"));
1766  break;
1768  UserPrint(("Incomplete\n"));
1769  break;
1770  case DiscInfo_Ses_Complete:
1771  UserPrint(("Complete\n"));
1772  break;
1773  default:
1774  UserPrint(("unknown state\n"));
1775  break;
1776  }
1777  UserPrint(("Erasable: %s\n",
1778  (DiscInfo->DiscStat.Flags & DiscInfo_Disk_Erasable) ? "yes" : "no"
1779  ));
1780  }
1781 #endif //UDF_FORMAT_MEDIA
1782  // Save disk status
1783  Vcb->DiscStat = DiscInfo->DiscStat.Flags;
1784  if((DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty) {
1785  UDFPrint(("Blank\n"));
1786  Vcb->BlankCD = TRUE;
1787  }
1788  if( (DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty ||
1789  (DiscInfo->DiscStat.Flags & DiscInfo_Ses_Mask) == DiscInfo_Ses_Incomplete) {
1790  // we shall mount empty disk to make it possible for
1791  // external applications to perform format operation
1792  // or something like this
1793  UDFPrint(("Try RAW_MOUNT\n"));
1794  Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
1795  PacketTrack = TRUE;
1796  }
1797 
1798 #ifndef _BROWSE_UDF_
1799  // If drive returned reasonable value from ReadCapacity, do not use
1800  // last LeadIn/LeadOut
1801  if(Vcb->MediaClassEx != CdMediaClass_DVDpRW &&
1802  !ReadCapacityOk) {
1803  // +RW returns bad value
1804  UDFPrint(("+RW returns bad value\n"));
1805  Vcb->LastPossibleLBA = (DiscInfo->LastSesLeadOutLBA & 0x80000000) ?
1806  0 : DiscInfo->LastSesLeadOutLBA;
1807  if(!(DiscInfo->LastSesLeadInLBA & 0x80000000)) {
1808  Vcb->LastPossibleLBA = max(DiscInfo->LastSesLeadInLBA, Vcb->LastPossibleLBA);
1809  }
1810  }
1811 #endif // _BROWSE_UDF_
1812  if((DiscInfo->Flags.Flags & DiscInfo_BGF_Mask) != 0) {
1813  UDFPrint(("ForceFP + MRW\n"));
1814  ForceFP = TRUE;
1815  Vcb->MRWStatus = DiscInfo->Flags.Flags & DiscInfo_BGF_Mask;
1816  // update addressing mode
1817  if(!MRWRetry) {
1818  UDFSetMRWMode(Vcb);
1819  MRWRetry = TRUE;
1820  goto MRWRetry_label;
1821  }
1822  }
1823  UDFPrint(("MRW state %x\n", Vcb->MRWStatus));
1824  if(Vcb->MediaClassEx == CdMediaClass_DVDRW) {
1825  if(Vcb->PhMediaCapFlags & CdCapFlags_RandomWritable) {
1826  UDFPrint(("DVD-RW Rewritable\n"));
1827  ForceFP = TRUE;
1828  } else
1829  if((DiscInfo->DiscStat.Flags & DiscInfo_Disk_Mask) == DiscInfo_Disk_Empty) {
1830  UDFPrint(("Blank DVD-RW\n"));
1831  ForceFP = TRUE;
1832  } else {
1833  UDFPrint(("DVD-RW Sequential\n"));
1834  NotFP = TRUE;
1835  }
1836  } else
1837  if(CdrwIsDvdOverwritable(Vcb->MediaClassEx)) {
1838  UDFPrint(("force Rewritable (2)\n"));
1839  ForceFP = TRUE;
1840  }
1841  // We have incomplete last session, so process each track from last to first
1842 // Vcb->LastPossibleLBA = DiscInfo->LastSesLeadInLBA;
1843 
1844  Vcb->LastSession = DiscInfo->Status.NumOfSes;
1845  Vcb->LastTrackNum = DiscInfo->Status.LastTrackNumLastSes;
1846  Vcb->FirstTrackNum = DiscInfo->FirstTrackNum;
1847  // some devices report LastTrackNum=0 for full disks
1848  Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum);
1849  if(!Vcb->LastTrackNum) {
1850  UDFPrint(("Try read 1st track...\n"));
1851  Vcb->LastTrackNum = 1;
1852  }
1853  UDFPrint(("DiskInfo: 1st trk %x, last trk %x\n", Vcb->FirstTrackNum, Vcb->LastTrackNum));
1854 #ifdef UDF_FORMAT_MEDIA
1855  if(fms && fms->opt_disk_info) {
1856  UserPrint(("First track: %d\n"
1857  "Last track: %d\n", Vcb->FirstTrackNum, Vcb->LastTrackNum));
1858  UserPrint(("------------------------------------------\n"));
1859  }
1860 #endif //UDF_FORMAT_MEDIA
1861 
1862  RC = UDFReallocTrackMap(Vcb, Vcb->LastTrackNum+1);
1863  if(!OS_SUCCESS(RC))
1864  try_return(RC);
1865 
1866  // Get last LBA from invisible track (if any)
1867  RtlZeroMemory(TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT));
1868 
1869  TrackInfoIn->LBA_TrkNum = 0; // invisible track
1870  TrackInfoIn->Track = TRUE;
1871 
1873  TrackInfoIn, sizeof(TRACK_INFO_BLOCK_USER_IN),
1874  TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT), TRUE, NULL);
1875  if(OS_SUCCESS(RC)) {
1876  if((Vcb->LastTrackNum < TrackInfoOut->TrackNum) &&
1877  TrackInfoOut->TrackLength &&
1878  (TrackInfoOut->TrackStartLBA != TrackInfoOut->NextWriteLBA)) {
1879  Vcb->LastTrackNum = TrackInfoOut->TrackNum;
1880  if(!(TrackInfoOut->NextWriteLBA & 0x80000000))
1881  Vcb->NWA = TrackInfoOut->NextWriteLBA;
1882  if(TrackInfoOut->TrackLength > 1) {
1883  Vcb->LastPossibleLBA =
1884  TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0);
1885  UDFPrint((" set LastPossibleLBA=%x\n", Vcb->LastPossibleLBA));
1886  }
1887  }
1888 
1889  UDFPrint(("Ses %d, Track %d (%x, len %x) PckSize %x: \n"
1890  " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
1891  " LRA: %x (%s) RC_LBA:%x\n",
1892  TrackInfoOut->SesNum,
1893  0,
1894  TrackInfoOut->TrackStartLBA,
1895  TrackInfoOut->TrackLength,
1896  TrackInfoOut->FixPacketSize,
1897 
1898  TrackInfoOut->NextWriteLBA,
1899  TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv",
1900  TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask,
1901  (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "",
1902  (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "",
1903  (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "",
1904  (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
1905 
1906  TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
1907  (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
1908  (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
1909 
1910  TrackInfoOut->LastRecordedAddr,
1911  (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
1912 
1913  TrackInfoOut->ReadCompatLBA
1914  ));
1915 #ifdef UDF_FORMAT_MEDIA
1916  if(fms && fms->opt_disk_info) {
1917  UserPrint(("Invisible track: \n"));
1918  UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n"
1919  " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
1920  " LRA: %x (%s) RC_LBA:%x\n",
1921  TrackInfoOut->SesNum,
1922  0,
1923  TrackInfoOut->TrackStartLBA,
1924  TrackInfoOut->TrackLength,
1925  TrackInfoOut->FixPacketSize,
1926 
1927  TrackInfoOut->NextWriteLBA,
1928  TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv",
1929  TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask,
1930  (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "",
1931  (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "",
1932  (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "",
1933  (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
1934 
1935  TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
1936  (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
1937  (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
1938 
1939  TrackInfoOut->LastRecordedAddr,
1940  (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
1941 
1942  TrackInfoOut->ReadCompatLBA
1943  ));
1944  }
1945 #endif //UDF_FORMAT_MEDIA
1946 
1947  }
1948 
1949  for (TrackNumber=(LONG)DiscInfo->FirstTrackNum;TrackNumber <= (LONG)Vcb->LastTrackNum;TrackNumber++) {
1950 
1951  RtlZeroMemory(TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT));
1952  TrackInfoIn->LBA_TrkNum = TrackNumber;
1953  TrackInfoIn->Track = TRUE;
1954 
1956  TrackInfoIn, sizeof(TRACK_INFO_BLOCK_USER_IN),
1957  TrackInfoOut,sizeof(TRACK_INFO_BLOCK_USER_OUT), TRUE, NULL);
1958  // fill sector type map
1959  if(TrackInfoOut->TrackStartLBA & 0x80000000) {
1960  UDFPrint(("TrkInfo: Bad FirstLba (%x), change to %x\n", TrackInfoOut->TrackStartLBA, 0));
1961  Vcb->TrackMap[TrackNumber].FirstLba = 0;
1962  } else {
1963  Vcb->TrackMap[TrackNumber].FirstLba = TrackInfoOut->TrackStartLBA;
1964  }
1965  if(TrackInfoOut->TrackLength & 0x80000000) {
1966  UDFPrint(("TrkInfo: Bad TrackLength (%x), change to %x\n", TrackInfoOut->TrackLength,
1967  Vcb->LastPossibleLBA - Vcb->TrackMap[TrackNumber].FirstLba + 1));
1968  TrackInfoOut->TrackLength = Vcb->LastPossibleLBA - Vcb->TrackMap[TrackNumber].FirstLba + 1;
1969  }
1970  Vcb->TrackMap[TrackNumber].LastLba = TrackInfoOut->TrackStartLBA +
1971  TrackInfoOut->TrackLength -
1972  (TrackInfoOut->TrackLength ? 1 : 0);
1973 
1974  Vcb->TrackMap[TrackNumber].TrackParam = TrackInfoOut->TrackParam.Flags;
1975  Vcb->TrackMap[TrackNumber].DataParam = TrackInfoOut->DataParam.Flags;
1976  Vcb->TrackMap[TrackNumber].NWA_V = TrackInfoOut->NWA_V;
1977  if((TrackInfoOut->NextWriteLBA & 0x80000000) ||
1978  (TrackInfoOut->NextWriteLBA < TrackInfoOut->TrackStartLBA)) {
1979  if(!(Vcb->TrackMap[TrackNumber].LastLba & 0x8000000)) {
1980  UDFPrint(("TrkInfo: set NWA to LastLba (%x)\n", Vcb->TrackMap[TrackNumber].LastLba));
1981  Vcb->TrackMap[TrackNumber].NWA =
1982  Vcb->TrackMap[TrackNumber].LastLba;
1983  } else {
1984  UDFPrint(("TrkInfo: set NWA to INV (1)\n"));
1985  Vcb->TrackMap[TrackNumber].NWA = 0;
1986  Vcb->TrackMap[TrackNumber].NWA_V = 0;
1987  }
1988  } else {
1989  if(!(TrackInfoOut->NextWriteLBA & 0x80000000)) {
1990  UDFPrint(("TrkInfo: Good NWA (%x)\n", TrackInfoOut->NextWriteLBA));
1991  Vcb->TrackMap[TrackNumber].NWA =
1992  TrackInfoOut->NextWriteLBA;
1993  } else {
1994  UDFPrint(("TrkInfo: set NWA to INV (2)\n"));
1995  Vcb->TrackMap[TrackNumber].NWA = 0;
1996  Vcb->TrackMap[TrackNumber].NWA_V = 0;
1997  }
1998  }
1999  Vcb->TrackMap[TrackNumber].Session = TrackInfoOut->SesNum;
2000  // for FP tracks we shall get PacketSize from returned info
2001  // otherwise set to default UDF value (0x20)
2002  if(NotFP) {
2003  UDFPrint(("Apply NotFP\n"));
2004  Vcb->TrackMap[TrackNumber].DataParam &= ~TrkInfo_FP;
2005 #ifdef DBG
2006  TrackInfoOut->DataParam.Flags &= ~TrkInfo_FP;
2007 #endif //DBG
2008  } else
2009  if(ForceFP) {
2010  UDFPrint(("Apply ForceFP\n"));
2011  PacketTrack = TRUE;
2012  Vcb->TrackMap[TrackNumber].DataParam |= TrkInfo_FP;
2013 #ifdef DBG
2014  TrackInfoOut->DataParam.Flags |= TrkInfo_FP;
2015 #endif //DBG
2016  }
2017  if(Vcb->TrackMap[TrackNumber].DataParam & TrkInfo_FP) {
2018  Vcb->TrackMap[TrackNumber].PacketSize = TrackInfoOut->FixPacketSize;
2019  Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2020  Vcb->FP_disc = TRUE;
2021  } else {
2022  Vcb->TrackMap[TrackNumber].PacketSize = PACKETSIZE_UDF;
2023  }
2024  // presence of Damaged track means, that we should mount this disk in RAW mode
2025  if(Vcb->TrackMap[TrackNumber].TrackParam & TrkInfo_Damage) {
2026  UDFPrint(("TrkInfo_Damage, Try RAW_MOUNT\n"));
2027  Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2028  }
2029  // presence of track with Unknown data type means, that we should mount
2030  // this disk in RAW mode
2031  if((TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask) == TrkInfo_Trk_unknown) {
2032  UDFPrint(("Unknown DatType, Try RAW_MOUNT\n"));
2033  Vcb->VCBFlags |= UDF_VCB_FLAGS_RAW_DISK;
2034  }
2035 
2036  PacketTrack |= ((TrackInfoOut->DataParam.Flags & TrkInfo_Packet) != 0);
2037 
2038  UDFPrint(("Ses %d, Track %d (%x - %x) PckSize %x: \n"
2039  " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
2040  " LRA: %x (%s) RC_LBA:%x\n",
2041  TrackInfoOut->SesNum,
2042  TrackNumber,
2043  Vcb->TrackMap[TrackNumber].FirstLba,
2044  Vcb->TrackMap[TrackNumber].LastLba,
2045  TrackInfoOut->FixPacketSize,
2046 
2047  TrackInfoOut->NextWriteLBA,
2048  TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv",
2049  TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask,
2050  (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "",
2051  (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "",
2052  (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "",
2053  (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
2054 
2055  TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
2056  (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
2057  (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
2058 
2059  TrackInfoOut->LastRecordedAddr,
2060  (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
2061 
2062  TrackInfoOut->ReadCompatLBA
2063  ));
2064 #ifdef UDF_FORMAT_MEDIA
2065  if(fms && fms->opt_disk_info) {
2066  UserPrint(("Track %d: \n", TrackNumber));
2067  UserPrint((" Ses %d, Track %d (%x, len %x) PckSize %x: \n"
2068  " NWA: %x (%s) DatType:%x, %s %s %s %s TrkType:%x %s %s\n"
2069  " LRA: %x (%s) RC_LBA:%x\n",
2070  TrackInfoOut->SesNum,
2071  TrackNumber,
2072  TrackInfoOut->TrackStartLBA,
2073  TrackInfoOut->TrackLength,
2074  TrackInfoOut->FixPacketSize,
2075 
2076  TrackInfoOut->NextWriteLBA,
2077  TrackInfoOut->NWA_V & TrkInfo_NWA_V ? "vld" : "inv",
2078  TrackInfoOut->DataParam.Flags & TrkInfo_Dat_Mask,
2079  (TrackInfoOut->DataParam.Flags & TrkInfo_Packet) ? "Pck" : "",
2080  (TrackInfoOut->DataParam.Flags & TrkInfo_FP) ? "FP" : "",
2081  (TrackInfoOut->DataParam.Flags & TrkInfo_Blank) ? "Blank" : "",
2082  (TrackInfoOut->DataParam.Flags & TrkInfo_RT) ? "RT" : "",
2083 
2084  TrackInfoOut->TrackParam.Flags & TrkInfo_Trk_Mask,
2085  (TrackInfoOut->TrackParam.Flags & TrkInfo_Copy) ? "Cpy" : "",
2086  (TrackInfoOut->TrackParam.Flags & TrkInfo_Damage) ? "Damage" : "",
2087 
2088  TrackInfoOut->LastRecordedAddr,
2089  (TrackInfoOut->NWA_V & TrkInfo_LRA_V) ? "vld" : "inv",
2090 
2091  TrackInfoOut->ReadCompatLBA
2092  ));
2093  }
2094 #endif //UDF_FORMAT_MEDIA
2095 
2096  if(TrackNumber == DiscInfo->FirstTrackNum) {
2097  if(!(Vcb->TrackMap[TrackNumber].FirstLba & 0x80000000)) {
2098  UDFPrint(("TrkInfo: Update FirstLBA (%x)\n", Vcb->TrackMap[TrackNumber].FirstLba));
2099  Vcb->FirstLBA = Vcb->TrackMap[TrackNumber].FirstLba;
2100  }
2101  }
2102  if((TrackInfoOut->SesNum == Vcb->LastSession) && !Vcb->FirstTrackNumLastSes) {
2103  if(!(Vcb->TrackMap[TrackNumber].FirstLba & 0x80000000)) {
2104  UDFPrint(("TrkInfo: Update FirstLBALastSes (%x)\n", Vcb->TrackMap[TrackNumber].FirstLba));
2105  Vcb->FirstLBALastSes = Vcb->TrackMap[TrackNumber].FirstLba;
2106  }
2107  Vcb->FirstTrackNumLastSes = TrackNumber;
2108  }
2109  }
2110 
2111  if(!(TrackInfoOut->NextWriteLBA & 0x80000000) &&
2112  !(TrackInfoOut->TrackLength & 0x80000000) &&
2113  (Vcb->NWA < TrackInfoOut->NextWriteLBA)
2114  ) {
2115  UDFPrint((" set NWA to %x\n", TrackInfoOut->NextWriteLBA));
2116  if(Vcb->MediaClassEx != CdMediaClass_DVDpRW) {
2117  Vcb->NWA = TrackInfoOut->NextWriteLBA;
2118  } else {
2119  Vcb->NWA =
2120  TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0);
2121  }
2122  }
2123  if(Vcb->MediaClassEx != CdMediaClass_DVDpRW &&
2124  !(TrackInfoOut->TrackLength & 0x80000000) &&
2125  TrackInfoOut->TrackLength > 1) {
2126  Vcb->LastPossibleLBA =
2127  TrackInfoOut->TrackStartLBA + TrackInfoOut->TrackLength - (TrackInfoOut->TrackLength ? 1 : 0);
2128  UDFPrint((" set LastPossibleLBA=%x\n", Vcb->LastPossibleLBA));
2129  }
2130  TrackNumber = Vcb->LastTrackNum;
2131  // quick formatted +RW returns bogus value
2132  if(Vcb->MediaClassEx == CdMediaClass_DVDpRW) {
2133  UDFPrint((" check quick formatted +RW\n"));
2134  if(Vcb->TrackMap[TrackNumber].LastLba &&
2135  !(Vcb->TrackMap[TrackNumber].LastLba & 0x80000000) &&
2136  Vcb->TrackMap[TrackNumber].LastLba < Vcb->LastPossibleLBA /*&&
2137  Vcb->TrackMap[TrackNumber].LastLba != Vcb->LastPossibleLBA*/
2138  ) {
2139  UDFPrint((" track LastLBA %x != LastPossibleLBA %x, verify\n",
2140  Vcb->TrackMap[TrackNumber].LastLba, Vcb->LastPossibleLBA));
2141 
2142  if(Vcb->MRWStatus == DiscInfo_BGF_Complete) {
2143  UDFPrint((" complete MRW state\n"));
2144 #ifdef _BROWSE_UDF_
2145  Vcb->LastPossibleLBA =
2146  Vcb->NWA =
2147  Vcb->LastLBA =
2148  Vcb->TrackMap[TrackNumber].LastLba;
2149  goto valid_track_length;
2150 #endif // _BROWSE_UDF_
2151  } else
2152  if(Vcb->MRWStatus) {
2153  uint8* buff;
2154  SIZE_T ReadBytes;
2155 
2156  UDFPrint((" MRW state %x\n", Vcb->MRWStatus));
2157 
2158  buff = (uint8*)DbgAllocatePoolWithTag(NonPagedPool, Vcb->WriteBlockSize, 'bNWD' );
2159  if(buff) {
2160  RC = UDFTRead(Vcb,
2161  buff,
2162  Vcb->WriteBlockSize,
2163  Vcb->TrackMap[TrackNumber].LastLba+1,
2164  &ReadBytes,
2165  PH_TMP_BUFFER);
2166  DbgFreePool(buff);
2167  if(!OS_SUCCESS(RC)) {
2168  UDFPrint((" Can't read beyond track LastLBA (%x)\n", Vcb->TrackMap[TrackNumber].LastLba+1));
2169  Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba;
2170  Vcb->NWA = Vcb->LastLBA+1;
2171  Vcb->TrackMap[TrackNumber].NWA_V = 1;
2172  Vcb->TrackMap[TrackNumber].NWA = Vcb->NWA;
2173  Vcb->TrackMap[TrackNumber].LastLba = Vcb->LastPossibleLBA;
2174  RC = STATUS_SUCCESS;
2175  goto valid_track_length;
2176  }
2177  }
2178  }
2179  }
2180  UDFPrint((" set track LastLBA %x\n", Vcb->LastPossibleLBA));
2181  Vcb->NWA =
2182  Vcb->LastLBA =
2183  Vcb->TrackMap[TrackNumber].LastLba =
2184  Vcb->LastPossibleLBA;
2185  }
2186 valid_track_length:
2187  // Test for last empty session
2188  if((Vcb->TrackMap[TrackNumber].Session !=
2189  Vcb->TrackMap[TrackNumber-1].Session) &&
2190  (Vcb->LastSession > 1)) {
2191  // Note: some devices return negative track length
2192  if((Vcb->TrackMap[TrackNumber].LastLba <=
2193  Vcb->TrackMap[TrackNumber].FirstLba) ||
2194  (Vcb->TrackMap[TrackNumber].FirstLba ==
2195  Vcb->TrackMap[TrackNumber].NWA)) {
2196  // empty last session...
2197  Vcb->LastTrackNum--;
2198 // TrackNumber--;
2199 /* for(SesNum = Vcb->TrackMap[TrackNumber].Session;
2200  Vcb->TrackMap[TrackNumber].Session == SesNum;
2201  TrackNumber--) {
2202  }*/
2203  if(TrackNumber>1)
2204  Vcb->LastSession = Vcb->TrackMap[TrackNumber-1].Session;
2205  }
2206  }
2207 
2208  TrackNumber = Vcb->LastTrackNum;
2209 #ifdef _BROWSE_UDF_
2210  Vcb->LastLBA = min(Vcb->TrackMap[TrackNumber].LastLba, Vcb->TrackMap[TrackNumber].NWA);
2211 #endif //_BROWSE_UDF_
2212 
2213  if(Vcb->TrackMap[TrackNumber].NWA_V & TrkInfo_NWA_V) {
2214  UDFPrint((" NWA ok, set LastLBA to min(Last %x, NWA %x\n",
2215  Vcb->TrackMap[TrackNumber].LastLba,
2216  Vcb->TrackMap[TrackNumber].NWA));
2217  Vcb->LastLBA = min(Vcb->TrackMap[TrackNumber].LastLba, Vcb->TrackMap[TrackNumber].NWA);
2218  } else {
2219  UDFPrint((" no NWA, set LastLBA to Last %x\n", Vcb->TrackMap[TrackNumber].LastLba));
2220  Vcb->LastLBA = Vcb->TrackMap[TrackNumber].LastLba;
2221  }
2222 
2223  Vcb->VCBFlags |= UDF_VCB_FLAGS_TRACKMAP;
2224  if(!PacketTrack && Vcb->MediaClassEx != CdMediaClass_DVDRAM ) {
2225  UDFPrint((" disable Raw mount\n"));
2226  Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
2227  }
2228 
2229 try_exit: NOTHING;
2230 
2231  } _SEH2_FINALLY {
2232  if(DiscInfo) MyFreePool__(DiscInfo);
2233  if(TrackInfoOut) MyFreePool__(TrackInfoOut);
2234  } _SEH2_END;
2235 
2236  return RC;
2237 } // end UDFReadDiscTrackInfo()
2238 
2239 /*
2240  This routine attempts to read disk layout using ReadFullTOC cmd
2241  */
2242 OSSTATUS
2244  PDEVICE_OBJECT DeviceObject, // the target device object
2245  PVCB Vcb
2246  )
2247 {
2248  OSSTATUS RC = STATUS_SUCCESS;
2250  uint32 index;
2251  uint8 POINT;
2252  uint8 CurTrack = 0;
2253  uint32 LastLeadOut = 0;
2254 // BOOLEAN IsMRW = FALSE;
2255 
2256  UDFPrint(("UDFReadAndProcessFullToc\n"));
2257 
2258  if(!toc) return STATUS_INSUFFICIENT_RESOURCES;
2259  Vcb->FirstTrackNum = 0xFF;
2260 
2262 
2264  NULL,0,
2265  toc,sizeof(READ_FULL_TOC_USER_OUT),
2266  TRUE,NULL);
2267 
2268  if(!OS_SUCCESS(RC)) {
2269 
2270  MyFreePool__(toc);
2271  return RC;
2272  }
2273 
2274 #ifdef _CONSOLE
2275  Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
2276 #endif //_CONSOLE
2277  Vcb->LastSession = toc->Sessions.Last_TrackSes;
2278 
2279  RC = UDFReallocTrackMap(Vcb, 0x100);
2280  if(!OS_SUCCESS(RC)) {
2281  MyFreePool__(toc);
2282  return RC;
2283  }
2284 
2285  // get LastPossibleLBA
2286 
2287  // Note: some drives return Full TOC items unordered.
2288  // So, LeadOut position may come before Track definition.
2289  // In order to handle such situation, we must initialize
2290  // CurTrack when First or Last Track descriptor comes
2292 /* if((toc->SessionData[index].Adr == TOC_ADR_TrackInfo) &&
2293  ((toc->SessionData[index].Control == TOC_CTL_MRWTrackInfo) || (toc->SessionData[index].Control == TOC_CTL_MRWLastSes))) {
2294  IsMRW = TRUE;
2295  }*/
2296  if(toc->SessionData[index].Adr == 1) {
2297  switch (POINT = toc->SessionData[index].POINT) {
2298  case POINT_FirstTrackNum: {
2299  Vcb->FirstTrackNum = toc->SessionData[index].Params.FirstTrackNum.FirstTrackNum;
2300  if(!CurTrack)
2301  CurTrack = (uint8)(Vcb->FirstTrackNum);
2302  break;
2303  }
2304  case POINT_LastTrackNum: {
2305  Vcb->LastTrackNum = toc->SessionData[index].Params.LastTrackNum.LastTrackNum;
2306  if(CurTrack < Vcb->LastTrackNum)
2307  CurTrack = (uint8)(Vcb->FirstTrackNum);
2308  break;
2309  }
2311 #define TempMSF toc->SessionData[index].Params.StartPositionOfLeadOut.MSF
2312  Vcb->TrackMap[CurTrack].LastLba = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2]);
2313  LastLeadOut = max(LastLeadOut, Vcb->TrackMap[CurTrack].LastLba);
2314 #undef TempMSF
2315  break;
2316  }
2317  default: {
2318  if( (Vcb->FirstTrackNum != 0x0FF) &&
2319  (toc->SessionData[index].POINT == Vcb->FirstTrackNum) ) {
2320 #define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF
2321  Vcb->FirstLBA = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2]);
2322  if(Vcb->FirstLBA & 0x80000000) {
2323  Vcb->FirstLBA = 0;
2324  }
2325 #undef TempMSF
2326  }
2327  break;
2328  }
2329  }
2332 #define TempMSF toc->SessionData[index].Params.StartPositionOfTrack.MSF
2333  Vcb->TrackMap[POINT].FirstLba = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2])-1;
2334  if(Vcb->TrackMap[POINT].FirstLba & 0x80000000) {
2335  if(POINT == 1) {
2336  Vcb->TrackMap[POINT].FirstLba = 0;
2337  } else {
2338  if(Vcb->TrackMap[POINT-1].LastLba) {
2339  Vcb->TrackMap[POINT].FirstLba = Vcb->TrackMap[POINT-1].LastLba+1;
2340  }
2341  }
2342  }
2343 #undef TempMSF
2345  Vcb->TrackMap[POINT-1].LastLba = Vcb->TrackMap[POINT].FirstLba-1;
2346  }
2347  CurTrack = POINT;
2348  }
2349  } else
2350  if(toc->SessionData[index].Adr == 5) {
2351  switch (POINT = toc->SessionData[index].POINT) {
2353 #define TempMSF toc->SessionData[index].Params.StartPositionOfNextProgramArea.MaxLeadOut_MSF
2354  Vcb->LastPossibleLBA = MSF_TO_LBA(TempMSF[0],TempMSF[1],TempMSF[2]);
2355 #undef TempMSF
2356  break;
2357  }
2358  default: {
2359  break;
2360  }
2361  }
2362  }
2363 
2364  }
2365 
2366 /* if(!IsMRW) {
2367  UDFPrint(("No MRW\n"));
2368  Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2369  }*/
2370 // Vcb->CompatFlags &= ~UDF_VCB_IC_MRW_ADDR_PROBLEM;
2371  // some devices report LastTrackNum=0 for full disks
2372  Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum);
2373  Vcb->TrackMap[Vcb->LastTrackNum].LastLba = max(LastLeadOut, Vcb->TrackMap[Vcb->LastTrackNum].LastLba);
2374 
2375  Vcb->LastLBA = Vcb->TrackMap[Vcb->LastTrackNum].LastLba;
2376 
2377  MyFreePool__(toc);
2378 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2379  return STATUS_SUCCESS;
2380 } // end UDFReadAndProcessFullToc()
2381 
2382 /*
2383  use standard way to determine disk layout (ReadTOC cmd)
2384  */
2385 OSSTATUS
2387  PDEVICE_OBJECT DeviceObject, // the target device object
2388  PVCB Vcb // Volume control block from this DevObj
2389  )
2390 {
2391  OSSTATUS RC = STATUS_SUCCESS;
2394  uint32 LocalTrackCount;
2395 // uint32 LocalTocLength;
2396  uint32 TocEntry;
2397 #ifdef _BROWSE_UDF_
2398  uint32 OldTrkNum;
2399  uint32 TrkNum;
2400  SIZE_T ReadBytes, i, len;
2401 #endif //_BROWSE_UDF_
2402 #ifdef UDF_FORMAT_MEDIA
2403  PUDFFmtState fms = Vcb->fms;
2404 #else
2405  #define fms FALSE
2406 #endif //UDF_FORMAT_MEDIA
2407 
2408  UDFPrint(("UDFUseStandard\n"));
2409 
2410  _SEH2_TRY {
2411 
2412  if(!toc || !LastSes) {
2414  }
2415  RtlZeroMemory(toc,sizeof(READ_TOC_TOC));
2416 
2417  Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_STD;
2418 
2420  toc,sizeof(READ_TOC_USER_OUT),
2421  toc,sizeof(READ_TOC_USER_OUT),
2422  TRUE,NULL );
2423 
2424  if((RC == STATUS_DEVICE_NOT_READY) || (RC == STATUS_NO_MEDIA_IN_DEVICE)) {
2425  try_return(RC);
2426  }
2427 #ifdef UDF_FORMAT_MEDIA
2428  if(fms->opt_media == MT_none) {
2430  }
2431 #endif //UDF_FORMAT_MEDIA
2432 
2433  // If even standard read toc does not work, then use default values
2434  if(!OS_SUCCESS(RC)) {
2435 
2436  RC = UDFReallocTrackMap(Vcb, 2);
2437  if(!OS_SUCCESS(RC)) {
2438  try_return(RC);
2439  }
2440 
2441  Vcb->LastSession=1;
2442  Vcb->FirstTrackNum=1;
2443 // Vcb->FirstLBA=0;
2444  Vcb->LastTrackNum=1;
2445  Vcb->TrackMap[1].FirstLba = Vcb->FirstLBA;
2446  Vcb->TrackMap[1].LastLba = Vcb->LastLBA;
2447  Vcb->TrackMap[1].PacketSize = PACKETSIZE_UDF;
2448 #ifdef UDF_FORMAT_MEDIA
2449  if(!fms) {
2450 #endif //UDF_FORMAT_MEDIA
2451 
2452 #ifdef _BROWSE_UDF_
2453 #ifdef UDF_HDD_SUPPORT
2455  try_return(RC = STATUS_SUCCESS);
2456  }
2457 #endif //UDF_HDD_SUPPORT
2458 #endif //_BROWSE_UDF_
2459 
2460 #ifdef UDF_FORMAT_MEDIA
2461  } else {
2462 
2463  if(fms->opt_media == MT_HD) {
2464  Vcb->LastPossibleLBA = Vcb->LastLBA;
2465  try_return(RC = STATUS_SUCCESS);
2466  }
2467  }
2468 #endif //UDF_FORMAT_MEDIA
2469  Vcb->LastPossibleLBA = max(Vcb->LastLBA, DEFAULT_LAST_LBA_FP_CD);
2470  Vcb->TrackMap[1].DataParam = TrkInfo_Dat_XA | TrkInfo_FP | TrkInfo_Packet;
2471  Vcb->TrackMap[1].TrackParam = TrkInfo_Trk_XA;
2472  Vcb->TrackMap[1].NWA = 0xffffffff;
2473  Vcb->NWA = DEFAULT_LAST_LBA_FP_CD + 7 + 1;
2474  try_return(RC = STATUS_SUCCESS);
2475  }
2476 
2477 #ifdef _CONSOLE
2478  Vcb->PhDeviceType = FILE_DEVICE_CD_ROM;
2479 #endif //_CONSOLE
2480 
2481  LocalTrackCount = toc->Tracks.Last_TrackSes - toc->Tracks.First_TrackSes + 1;
2482 // LocalTocLength = PtrOffset( toc, &(toc->TrackData[LocalTrackCount + 1]) ); /* FIXME ReactOS Assume PtrOffset is not changing it's arguments? */
2483 
2484  // Get out if there is an immediate problem with the TOC.
2485  if(toc->Tracks.First_TrackSes > toc->Tracks.Last_TrackSes) {
2487  }
2488 
2489 #ifdef _BROWSE_UDF_
2490  Vcb->LastTrackNum=toc->Tracks.Last_TrackSes;
2491  Vcb->FirstTrackNum=toc->Tracks.First_TrackSes;
2492  // some devices report LastTrackNum=0 for full disks
2493  Vcb->LastTrackNum = max(Vcb->LastTrackNum, Vcb->FirstTrackNum);
2494 
2496 /* if(Vcb->TrackMap) {
2497  MyFreePool__(Vcb->TrackMap);
2498  Vcb->TrackMap = NULL;
2499  }
2500  Vcb->TrackMap = (PUDFTrackMap)
2501  MyAllocatePool__(NonPagedPool, (MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2502  if(!Vcb->TrackMap) {
2503  MyFreePool__(toc);
2504  return STATUS_INSUFFICIENT_RESOURCES;
2505  }
2506  RtlZeroMemory(Vcb->TrackMap,(MAXIMUM_NUMBER_OF_TRACKS+1)*sizeof(UDFTrackMap));
2507 */
2508  if(!OS_SUCCESS(RC)) {
2509  BrutePoint();
2510  try_return(RC);
2511  }
2512  // find 1st and last session
2514  LastSes,sizeof(GET_LAST_SESSION_USER_OUT),
2515  LastSes,sizeof(GET_LAST_SESSION_USER_OUT),
2516  TRUE,NULL );
2517 
2518  if(OS_SUCCESS(RC)) {
2519  TrkNum = LastSes->LastSes_1stTrack.TrackNum;
2520  Vcb->LastSession = LastSes->Sessions.First_TrackSes;
2521  for(TocEntry=0;TocEntry<LocalTrackCount + 1;TocEntry++) {
2522  if(toc->TrackData[TocEntry].TrackNum == TrkNum) {
2523  Vcb->TrackMap[TrkNum].Session = Vcb->LastSession;
2524  }
2525  }
2526  }
2527 
2528  OldTrkNum = 0;
2529  // Scan toc for first & last LBA
2530  for(TocEntry=0;TocEntry<LocalTrackCount + 1;TocEntry++) {
2531 #define TempMSF toc->TrackData[TocEntry].LBA
2532  TrkNum = toc->TrackData[TocEntry].TrackNum;
2533 #ifdef UDF_DBG
2534  if (TrkNum >= MAXIMUM_NUMBER_OF_TRACKS &&
2535  TrkNum != TOC_LastTrack_ID) {
2536  UDFPrint(("UDFUseStandard: Array out of bounds\n"));
2537  BrutePoint();
2538  try_return(RC = STATUS_SUCCESS);
2539  }
2540  UDFPrint(("Track N %d (0x%x) first LBA %ld (%lx) \n",TrkNum,TrkNum,
2541  MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]),
2542  MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])));
2543 #endif // UDF_DBG
2544  if(Vcb->FirstTrackNum == TrkNum) {
2545  Vcb->FirstLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]);
2546  if(Vcb->FirstLBA & 0x80000000) {
2547  Vcb->FirstLBA = 0;
2548  }
2549  }
2550  if(TOC_LastTrack_ID == TrkNum) {
2551  Vcb->LastLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])-1;
2552  Vcb->TrackMap[OldTrkNum].LastLba = Vcb->LastLBA-1;
2553  UDFPrint(("UDFUseStandard: Last track entry, break TOC scan\n"));
2554 // continue;
2555  break;
2556  } else {
2557  Vcb->TrackMap[TrkNum].FirstLba = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]);
2558  if(Vcb->TrackMap[TrkNum].FirstLba & 0x80000000)
2559  Vcb->TrackMap[TrkNum].FirstLba = 0;
2560  if(TrkNum) {
2561  if (TOC_LastTrack_ID == OldTrkNum) {
2562  UDFPrint(("UDFUseStandard: Wrong previous track number\n"));
2563  BrutePoint();
2564  } else {
2565  Vcb->TrackMap[OldTrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-1;
2566  }
2567  }
2568  }
2569  // check track type
2570  switch(toc->TrackData[TocEntry].Control & TocControl_TrkMode_Mask) {
2573  Vcb->TrackMap[TrkNum].DataParam = TrkInfo_Dat_XA;
2574  Vcb->TrackMap[TrkNum].TrackParam = TrkInfo_Trk_XA;
2575  break;
2576  default:
2577  Vcb->TrackMap[TrkNum].DataParam = TrkInfo_Dat_unknown;
2578  Vcb->TrackMap[TrkNum].TrackParam = TrkInfo_Trk_unknown;
2579  }
2580  OldTrkNum = TrkNum;
2581 #undef TempMSF
2582  }
2583 
2584  TrkNum = Vcb->LastTrackNum;
2585  RC = STATUS_SUCCESS;
2586  // find last _valid_ track
2587  for(;TrkNum;TrkNum--) {
2588  if((Vcb->TrackMap[TrkNum].DataParam != TrkInfo_Dat_unknown) &&
2589  (Vcb->TrackMap[TrkNum].TrackParam != TrkInfo_Trk_unknown)) {
2590  RC = STATUS_UNSUCCESSFUL;
2591  Vcb->LastTrackNum = TrkNum;
2592  break;
2593  }
2594  }
2595  // no valid tracks...
2596  if(!TrkNum) {
2597  UDFPrint(("UDFUseStandard: no valid tracks...\n"));
2599  }
2600  i = 0;
2601 
2602  // Check for last VP track. Some last sectors may belong to Link-data &
2603  // be unreadable. We should forget about them, because UDF needs
2604  // last _readable_ sector.
2605  while(!OS_SUCCESS(RC) && (i<8)) {
2606  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, (int8*)toc, Vcb->BlockSize,
2607  ((uint64)(Vcb->TrackMap[TrkNum].LastLba-i)) << Vcb->BlockSizeBits, &ReadBytes, PH_TMP_BUFFER);
2608  i++;
2609  }
2610  if(OS_SUCCESS(RC)) {
2611  Vcb->LastLBA = Vcb->TrackMap[TrkNum].LastLba-i+1;
2612 /* if(i) {
2613  Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;
2614  Vcb->TrackMap[TrkNum].;
2615  }*/
2616  } else {
2617 
2618  // Check for FP track. READ_TOC reports actual track length, but
2619  // Link-data is hidden & unreadable for us. So, available track
2620  // length may be less than actual. Here we assume that Packet-size
2621  // is PACKETSIZE_UDF.
2622  i = 0;
2623  len = Vcb->TrackMap[TrkNum].LastLba - Vcb->TrackMap[TrkNum].FirstLba + 1;
2625 
2626  while(!OS_SUCCESS(RC) && (i<9)) {
2627  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, (int8*)toc, Vcb->BlockSize,
2628  ((uint64)(Vcb->TrackMap[TrkNum].FirstLba-i+len)) << Vcb->BlockSizeBits, &ReadBytes, PH_TMP_BUFFER);
2629  i++;
2630  }
2631  if(OS_SUCCESS(RC)) {
2632  Vcb->LastLBA =
2633  Vcb->TrackMap[TrkNum].LastLba = Vcb->TrackMap[TrkNum].FirstLba-i+len+1;
2634  Vcb->TrackMap[TrkNum].PacketSize = PACKETSIZE_UDF;
2635 // Vcb->TrackMap[TrkNum].;
2636  } else
2637  if(RC == STATUS_INVALID_DEVICE_REQUEST) {
2638  // wrap return code from Audio-disk
2639  RC = STATUS_SUCCESS;
2640  }
2641  }
2642 
2643 #ifdef UDF_CDRW_EMULATION_ON_ROM
2644  Vcb->LastPossibleLBA = Vcb->LastLBA+7+1+1024;
2645  Vcb->NWA = Vcb->LastLBA+7+1;
2646 #else
2647  Vcb->LastPossibleLBA =
2648  Vcb->NWA = Vcb->LastLBA+7+1;
2649 #endif //UDF_CDRW_EMULATION_ON_ROM
2650 
2651 #else //_BROWSE_UDF_
2652 
2653  Vcb->FirstTrackNum=toc->Tracks.Last_TrackSes;
2654  Vcb->LastTrackNum=toc->Tracks.First_TrackSes;
2655 
2656  // Scan toc for first & last LBA
2657  for(TocEntry=0;TocEntry<LocalTrackCount + 1;TocEntry++) {
2658 #define TempMSF toc->TrackData[TocEntry].LBA
2659  if(Vcb->FirstTrackNum == toc->TrackData[TocEntry].TrackNum) {
2660  Vcb->FirstLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3]);
2661  if(Vcb->FirstLBA & 0x80000000) {
2662  Vcb->FirstLBA = 0;
2663  }
2664  }
2665  if(TOC_LastTrack_ID == toc->TrackData[TocEntry].TrackNum) {
2666  Vcb->LastLBA = MSF_TO_LBA(TempMSF[1],TempMSF[2],TempMSF[3])-1;
2667  }
2668 #undef TempMSF
2669  }
2670 
2671 // Vcb->LastLBA=PacketVariable2Fixed(Vcb->LastLBA)-2;
2672  Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_FP_CD;
2673 #endif //_BROWSE_UDF_
2674 try_exit: NOTHING;
2675  } _SEH2_FINALLY {
2676  if(toc) MyFreePool__(toc);
2677  if(LastSes) MyFreePool__(LastSes);
2678  } _SEH2_END;
2679 
2680  return RC;
2681 } // end UDFUseStandard()
2682 
2683 /*
2684  Get block size (for read operation)
2685  */
2686 OSSTATUS
2688  IN PDEVICE_OBJECT DeviceObject, // the target device object
2689  IN PVCB Vcb // Volume control block from this DevObj
2690  )
2691 {
2692  OSSTATUS RC = STATUS_SUCCESS;
2695 #ifdef UDF_FORMAT_MEDIA
2696  PUDFFmtState fms = Vcb->fms;
2697 #else
2698  #define fms FALSE
2699 #endif //UDF_FORMAT_MEDIA
2700 
2701  if(!DiskGeometry || !PartitionInfo)
2703 
2704 #ifdef _BROWSE_UDF_
2705 
2706 #ifdef UDF_HDD_SUPPORT
2707  if(!fms) {
2709  UDFPrint(("UDFGetBlockSize: HDD\n"));
2711  0,NULL,
2712  DiskGeometry,sizeof(DISK_GEOMETRY),
2713  TRUE,NULL );
2714  Vcb->BlockSize = (OS_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 512;
2715  if(!NT_SUCCESS(RC))
2716  try_return(RC);
2718  0,NULL,
2720  TRUE,NULL );
2721  if(!NT_SUCCESS(RC)) {
2722  UDFPrint(("UDFGetBlockSize: IOCTL_DISK_GET_PARTITION_INFO failed\n"));
2723  if(RC == STATUS_INVALID_DEVICE_REQUEST) /* ReactOS Code Change (was =) */
2725  try_return(RC);
2726  }
2727  if(PartitionInfo->PartitionType != PARTITION_IFS) {
2728  UDFPrint(("UDFGetBlockSize: PartitionInfo->PartitionType != PARTITION_IFS\n"));
2730  }
2731  } else {
2732 #endif //UDF_HDD_SUPPORT
2734  DiskGeometry,sizeof(DISK_GEOMETRY),
2735  DiskGeometry,sizeof(DISK_GEOMETRY),
2736  TRUE,NULL );
2737 
2738  if(RC == STATUS_DEVICE_NOT_READY) {
2739  // probably, the device is really busy, may be by CD/DVD recording
2740  UserPrint((" busy (0)\n"));
2741  try_return(RC);
2742  }
2743 
2744  Vcb->BlockSize = (OS_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 2048;
2745 #ifdef UDF_HDD_SUPPORT
2746  }
2747  }
2748 #endif //UDF_HDD_SUPPORT
2749 
2750 #endif //_BROWSE_UDF_
2751 
2752 #ifdef UDF_FORMAT_MEDIA
2753  if(fms) {
2755  DiskGeometry,sizeof(DISK_GEOMETRY),
2756  DiskGeometry,sizeof(DISK_GEOMETRY),
2757  FALSE, NULL );
2758 
2759  if(!NT_SUCCESS(RC)) {
2761  DiskGeometry,sizeof(DISK_GEOMETRY),
2762  DiskGeometry,sizeof(DISK_GEOMETRY),
2763  FALSE, NULL );
2764  if(NT_SUCCESS(RC)) {
2765  fms->opt_media = MT_HD;
2767  NULL,0,
2769  FALSE, NULL );
2770  if(!NT_SUCCESS(RC)) {
2771  LONG HiOffs=0;
2772  RC = SetFilePointer(DeviceObject->h,0,&HiOffs,FILE_END);
2773  }
2774  }
2775  }
2776 
2777  if(RC == STATUS_DEVICE_NOT_READY) {
2778  // probably, the device is really busy, may be by CD/DVD recording
2779  UserPrint((" busy\n"));
2780  try_return(RC );
2781  }
2782 
2783  Vcb->BlockSize = (NT_SUCCESS(RC)) ? DiskGeometry->BytesPerSector : 2048;
2784  }
2785 #endif //UDF_FORMAT_MEDIA
2786 
2787  // Block size must be an even multiple of 512
2788  switch (Vcb->BlockSize) {
2789  case 2048: Vcb->BlockSizeBits = 11; break;
2790 #ifdef UDF_HDD_SUPPORT
2791  case 512: Vcb->BlockSizeBits = 9; break;
2792  case 1024: Vcb->BlockSizeBits = 10; break;
2793  case 4096: Vcb->BlockSizeBits = 12; break;
2794  case 8192: Vcb->BlockSizeBits = 13; break;
2795 #endif //UDF_HDD_SUPPORT
2796  default:
2797  {
2798  UserPrint(("UDF: Bad block size (%ld)\n", Vcb->BlockSize));
2800  }
2801  }
2802 
2803 #ifdef UDF_HDD_SUPPORT
2804  if(
2805 #ifdef _BROWSE_UDF_
2807  ||
2808 #endif //_BROWSE_UDF_
2809 #ifdef UDF_FORMAT_MEDIA
2810  (fms && fms->opt_media == MT_HD)
2811  ||
2812 #endif //UDF_FORMAT_MEDIA
2813  FALSE ) {
2814 
2815 #ifdef UDF_FORMAT_MEDIA
2816  if(fms && !NT_SUCCESS(RC))
2818 #endif //UDF_FORMAT_MEDIA
2819 
2820  Vcb->FirstLBA=0;//(ULONG)(PartitionInfo->StartingOffset.QuadPart >> Vcb->BlockSizeBits);
2821  Vcb->LastPossibleLBA =
2822  Vcb->LastLBA = (uint32)(PartitionInfo->PartitionLength.QuadPart >> Vcb->BlockSizeBits)/* + Vcb->FirstLBA*/ - 1;
2823  } else {
2824 #endif //UDF_HDD_SUPPORT
2825  Vcb->FirstLBA=0;
2826  if(OS_SUCCESS(RC)) {
2827  Vcb->LastLBA = (uint32)(DiskGeometry->Cylinders.QuadPart *
2828  DiskGeometry->TracksPerCylinder *
2829  DiskGeometry->SectorsPerTrack - 1);
2830  if(Vcb->LastLBA == 0x7fffffff) {
2832  }
2833  } else {
2835  }
2836  Vcb->LastPossibleLBA = Vcb->LastLBA;
2837 #ifdef UDF_HDD_SUPPORT
2838  }
2839 #endif //UDF_HDD_SUPPORT
2840 
2841 #ifdef _BROWSE_UDF_
2842 // if(UDFGetDevType(DeviceObject) == FILE_DEVICE_DISK) {
2843  Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2844 // } else {
2845 // Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2846 // }
2847 #else //_BROWSE_UDF_
2848  if(fms->opt_media == MT_HD) {
2849  Vcb->WriteBlockSize = Vcb->BlockSize;
2850  } else {
2851  Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
2852  }
2853 #endif //_BROWSE_UDF_
2854 
2855  RC = STATUS_SUCCESS;
2856 
2857 try_exit: NOTHING;
2858 
2859  UDFPrint(("UDFGetBlockSize:\nBlock size is %x, Block size bits %x, Last LBA is %x\n",
2860  Vcb->BlockSize, Vcb->BlockSizeBits, Vcb->LastLBA));
2861 
2863  MyFreePool__(DiskGeometry);
2864  return RC;
2865 
2866 } // end UDFGetBlockSize()
2867 
2868 #ifdef _BROWSE_UDF_
2869 
2870 OSSTATUS
2871 UDFCheckTrackFPAddressing(
2872 // IN PDEVICE_OBJECT DeviceObject, // the target device object
2873  IN PVCB Vcb, // Volume control block from this DevObj
2874  IN ULONG TrackNum
2875  )
2876 {
2877  OSSTATUS RC = STATUS_SUCCESS;
2878 // OSSTATUS RC2 = STATUS_UNSUCCESSFUL;
2879  uint32 lba=0;
2880  uint32 i;
2881  uint8* Buffer;
2882 // SIZE_T ReadBytes;
2883 
2884  uint8 user_data;
2885 
2886  ULONG FirstChunkLen = 0;
2887 
2888  ULONG NextChunkLen = 0;
2889  ULONG NextChunkLenCount = 0;
2890 
2891  ULONG NextChunkLenOth = 0;
2892  ULONG NextChunkLenOthCount = 0;
2893 // ULONG MRW_Offset = 0;
2894 
2895  PLL_READ_USER_IN pLLR_in;
2896  PCD_SECTOR_HEADER pHdr;
2897 /* uint8 cMSF[3] = {0,2,0};
2898  uint8 cMSF1[3] = {0,2,1};*/
2899 
2900 
2901  if(!Vcb->TrackMap) {
2902  Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM;
2903  return STATUS_SUCCESS;
2904  }
2905 
2907  sizeof(LL_READ_USER_IN)+16), 'pNWD');
2908  if(!Buffer)
2910  pLLR_in = (PLL_READ_USER_IN)Buffer;
2911  pHdr = (PCD_SECTOR_HEADER)(Buffer+sizeof(LL_READ_USER_IN));
2912 
2913 /* if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
2914  MRW_Offset = (MRW_DMA_OFFSET/32)*39;
2915  }*/
2916 
2917  user_data = 0;
2918  for(i=0; i<=0x200; i++) {
2919 
2920  RtlZeroMemory(pLLR_in, sizeof(pLLR_in)+16);
2922  pLLR_in->LBA = i;
2923  pLLR_in->NumOfBlocks = 1;
2924  pLLR_in->Flags.Flags = ReadCd_Header_Hdr;
2925 // pLLR_in->UseMFS = FALSE; // already zero
2926 // MOV_MSF(pLLR_in->Starting_MSF, cMSF);
2927 // MOV_MSF(pLLR_in->Ending_MSF, cMSF1);
2928  RtlZeroMemory(pHdr, sizeof(CD_SECTOR_HEADER));
2929  RC = UDFPhSendIOCTL(IOCTL_CDRW_LL_READ, Vcb->TargetDeviceObject,
2930  pLLR_in, sizeof(LL_READ_USER_IN),
2931  pHdr, sizeof(CD_SECTOR_HEADER),
2932  TRUE, NULL );
2933 
2934 /* RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, Buffer, Vcb->BlockSize,
2935  ((uint64)(i+MRW_Offset)) << Vcb->BlockSizeBits, &ReadBytes, 0);*/
2936 
2937  // skip unreadable
2938  if(!OS_SUCCESS(RC)) {
2939  UDFPrint((" Read error at lba %x\n", i));
2940  continue;
2941  }
2942 
2943  // skip strange (damaged ?) blocks
2944  if((pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask) != WParam_SubHdr_Mode1 &&
2945  (pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask) != WParam_SubHdr_Mode2) {
2946  UDFPrint((" Unexpected data type (%x) at lba %x\n", pHdr->Mode.Flags & WParam_SubHdr_Mode_Mask, i));
2947  continue;
2948  }
2949 
2951  !user_data) {
2952  lba = i;
2953  }
2954 
2955 /* if(OS_SUCCESS(RC) && !OS_SUCCESS(RC2)) {
2956  lba = i;
2957  }*/
2958 
2960  user_data) {
2961 // if(!OS_SUCCESS(RC) && OS_SUCCESS(RC2)) {
2962  UDFPrint((" %x - %x (%x sectors)\n", lba, i-1, i-lba));
2963  if(!FirstChunkLen) {
2964  FirstChunkLen = i-lba;
2965  } else {
2966  if(!NextChunkLen) {
2967  NextChunkLen = i-lba;
2968  NextChunkLenCount++;
2969  } else {
2970  if(NextChunkLen == i-lba) {
2971  NextChunkLenCount++;
2972  } else {
2973  if((NextChunkLenOth+1) % (NextChunkLen+1)) {
2974  NextChunkLenOth = i-lba;
2975  NextChunkLenOthCount++;
2976  } else {
2977  NextChunkLenCount++;
2978  }
2979  }
2980  }
2981  }
2982  }
2983  user_data = ((pHdr->Mode.Flags & WParam_SubHdr_Format_Mask) == WParam_SubHdr_Format_UserData);
2984 // RC2 = RC;
2985  }
2986 
2988 
2989  if(!NextChunkLenCount && !NextChunkLenOthCount) {
2990  Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM;
2991  return STATUS_SUCCESS;
2992  }
2993  if(NextChunkLenOthCount > NextChunkLenCount) {
2994  NextChunkLen = NextChunkLenOth;
2995  }
2996  if(NextChunkLen > PACKETSIZE_UDF+7) {
2997  Vcb->CompatFlags &= ~UDF_VCB_IC_FP_ADDR_PROBLEM;
2998  return STATUS_SUCCESS;
2999  }
3000  Vcb->TrackMap[TrackNum].DataParam &= ~TrkInfo_Dat_Mask;
3001  Vcb->TrackMap[TrackNum].DataParam |= TrkInfo_Dat_XA;
3002  Vcb->TrackMap[TrackNum].Flags |= TrackMap_FixFPAddressing;
3003  Vcb->TrackMap[TrackNum].PacketSize = 1;
3004  while(NextChunkLen >> Vcb->TrackMap[TrackNum].PacketSize) {
3005  Vcb->TrackMap[TrackNum].PacketSize++;
3006  }
3007  Vcb->TrackMap[TrackNum].PacketSize = 1 << (Vcb->TrackMap[TrackNum].PacketSize-1);
3008  Vcb->TrackMap[TrackNum].TrackFPOffset = NextChunkLen - FirstChunkLen; // !!!!!
3009  Vcb->TrackMap[TrackNum].PacketFPOffset = Vcb->TrackMap[TrackNum].TrackFPOffset;//0;//NextChunkLenOth - FirstChunkLen;
3010  Vcb->TrackMap[TrackNum].LastLba = (Vcb->TrackMap[TrackNum].LastLba*Vcb->TrackMap[TrackNum].PacketSize) /
3011  (Vcb->TrackMap[TrackNum].PacketSize + 7);
3012 
3013  return STATUS_SUCCESS;
3014 } // end UDFCheckTrackFPAddressing()
3015 
3016 uint32
3017 UDFFixFPAddress(
3018  IN PVCB Vcb, // Volume control block from this DevObj
3019  IN uint32 Lba
3020  )
3021 {
3022  uint32 i = Vcb->LastReadTrack;
3023  uint32 pk;
3024  uint32 rel;
3025 
3026 // if(Vcb->CompatFlags & UDF_VCB_IC_MRW_ADDR_PROBLEM) {
3027  if(Vcb->TrackMap[i].Flags & TrackMap_FixMRWAddressing) {
3028  pk = Lba / MRW_DA_SIZE;
3029  rel = Lba % MRW_DA_SIZE;
3030  Lba = pk*MRW_DMA_SEGMENT_SIZE + rel;
3031  Lba += MRW_DMA_OFFSET;
3032  }
3033  if(Vcb->TrackMap[i].Flags & TrackMap_FixFPAddressing) {
3034  if(Lba < 0x20)
3035  return Lba;
3036  pk = Lba / Vcb->TrackMap[i].PacketSize;
3037  rel = Lba % Vcb->TrackMap[i].PacketSize;
3038  UDFPrint(("FixFPAddr: %x -> %x\n", Lba, pk*(Vcb->TrackMap[i].PacketSize+7) + rel));
3039  return pk*(Vcb->TrackMap[i].PacketSize+7) + rel /*- Vcb->TrackMap[i].PacketFPOffset*/;
3040  }
3041  return Lba;
3042 } // end UDFFixFPAddress()
3043 
3044 #endif //_BROWSE_UDF_
3045 
3046 /*
3047  detect device driver & try to read disk layout (use all methods)
3048  */
3049 OSSTATUS
3051  IN PDEVICE_OBJECT DeviceObject, // the target device object
3052  IN PVCB Vcb // Volume control block from this DevObj
3053  )
3054 {
3056  int8* ioBuf = (int8*)MyAllocatePool__(NonPagedPool,4096);
3057  uint8 MediaType;
3058  PLUN_WRITE_PERF_DESC_USER WPerfDesc;
3059  uint32 i;
3060 // BOOLEAN MRW_problem = FALSE;
3061  uint32 SavedFeatures = 0;
3062 #ifdef UDF_FORMAT_MEDIA
3063  PUDFFmtState fms = Vcb->fms;
3064 #else
3065  #define fms FALSE
3066 #endif //UDF_FORMAT_MEDIA
3067 
3068  UDFPrint(("UDFGetDiskInfo\n"));
3069 
3070  if(!ioBuf) {
3072  }
3073 
3074  _SEH2_TRY {
3076  if(!OS_SUCCESS(RC)) try_return(RC);
3077 
3078 
3079  // Get lower driver signature
3081  ioBuf,sizeof(GET_SIGNATURE_USER_OUT),
3082  ioBuf,sizeof(GET_SIGNATURE_USER_OUT),
3083  TRUE,NULL);
3084 
3085  if(!OS_SUCCESS(RC)) {
3086 
3088 #ifdef _BROWSE_UDF_
3089  if(!NT_SUCCESS(RC) || fms)
3090  try_return(RC);
3091 
3092  // assume Device Recordable for now
3093  goto GetSignatureFailed;
3094 #endif //_BROWSE_UDF_
3095  }
3096 
3097  UDFPrint(("UDF: Signature of low driver is : %s \n",
3098  ((PGET_SIGNATURE_USER_OUT)(ioBuf))->VendorId));
3099 
3100  if(!strncmp( (const char *)(&( ((PGET_SIGNATURE_USER_OUT)(ioBuf))->VendorId[0]) ),
3101  Signature,strlen(Signature) )) {
3102  UDFPrint(("UDF: *****************************************\n"));
3103  UDFPrint(("UDF: ********* Our Device Driver Found ******\n"));
3104  UDFPrint(("UDF: *****************************************\n"));
3105 
3106  (Vcb->VCBFlags) |= UDF_VCB_FLAGS_OUR_DEVICE_DRIVER;
3107 #ifndef _BROWSE_UDF_
3108  // reset driver
3109 #ifdef UDF_FORMAT_MEDIA
3110  if(!fms->opt_probe) {
3111 #endif //UDF_FORMAT_MEDIA
3112  UDFResetDeviceDriver(Vcb, Vcb->TargetDeviceObject, FALSE);
3113  // lock it
3114  ((PPREVENT_MEDIA_REMOVAL_USER_IN)(ioBuf))->PreventMediaRemoval = TRUE;
3116  DeviceObject,
3117  ioBuf,sizeof(PREVENT_MEDIA_REMOVAL_USER_IN),
3118  NULL,0,
3119  FALSE, NULL);
3120 #ifdef UDF_FORMAT_MEDIA
3121  }
3122 #endif //UDF_FORMAT_MEDIA
3123 #endif //_BROWSE_UDF_
3124 //#else //_BROWSE_UDF_
3125  // get device features
3127  DeviceObject,
3128  NULL,0,
3129  ioBuf,sizeof(GET_DEVICE_INFO_USER_OUT),
3130  FALSE,NULL);
3131 
3132  Vcb->SavedFeatures =
3133  SavedFeatures = ((PGET_DEVICE_INFO_USER_OUT)ioBuf)->Features;
3134  if(!(SavedFeatures & CDRW_FEATURE_SYNC_ON_WRITE)) {
3135  UDFPrint(("UDFGetDiskInfo: UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE\n"));
3136  Vcb->CompatFlags |= UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE;
3137  }
3138  if(!(SavedFeatures & CDRW_FEATURE_FORCE_SYNC_BEFORE_READ)) {
3139  UDFPrint(("UDFGetDiskInfo: UDF_VCB_IC_SYNCCACHE_BEFORE_READ\n"));
3140  Vcb->CompatFlags |= UDF_VCB_IC_SYNCCACHE_BEFORE_READ;
3141  }
3142  if(SavedFeatures & CDRW_FEATURE_BAD_RW_SEEK) {
3143  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_RW_SEEK\n"));
3144  Vcb->CompatFlags |= UDF_VCB_IC_BAD_RW_SEEK;
3145  }
3146  // we must check if this is FP-formatted disk in old devices
3147  // independently of MediaType they report
3148  if(SavedFeatures & CDRW_FEATURE_FP_ADDRESSING_PROBLEM) {
3149  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FP_ADDRESSING_PROBLEM ?\n"));
3150  Vcb->CompatFlags |= UDF_VCB_IC_FP_ADDR_PROBLEM;
3151  }
3152  if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) {
3153  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM ?\n"));
3154  }
3155  if(SavedFeatures & CDRW_FEATURE_FORCE_SYNC_ON_WRITE) {
3156  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FORCE_SYNC_ON_WRITE\n"));
3157  Vcb->VCBFlags |= UDF_VCB_FLAGS_FORCE_SYNC_CACHE;
3158  }
3159  if(SavedFeatures & CDRW_FEATURE_BAD_DVD_LAST_LBA) {
3160  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_BAD_DVD_LAST_LBA\n"));
3161  Vcb->CompatFlags |= UDF_VCB_IC_BAD_DVD_LAST_LBA;
3162  }
3163  if(SavedFeatures & CDRW_FEATURE_STREAMING) {
3164  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_STREAMING\n"));
3165  }
3166  if(SavedFeatures & CDRW_FEATURE_OPC) {
3167  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_OPC -> assume OPCNum=1\n"));
3168  Vcb->OPCNum = 1;
3169  }
3170 #ifdef UDF_FORMAT_MEDIA
3171  if(SavedFeatures & CDRW_FEATURE_FULL_BLANK_ON_FORMAT) {
3172  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_FULL_BLANK_ON_FORMAT\n"));
3173  if((fms->opt_probe || fms->opt_smart_f)/* &&
3174  (fms->format_media && fms->blank_media*/) {
3175  UDFPrint(("UDFGetDiskInfo: force Full Erase\n"));
3176  fms->opt_qblank = FALSE;
3177  }
3178  }
3179 #endif //UDF_FORMAT_MEDIA
3180 #ifdef _BROWSE_UDF_
3181  // get device buffer size
3183  DeviceObject,
3184  NULL,0,
3185  ioBuf,sizeof(BUFFER_CAPACITY_BLOCK_USER_OUT),
3186  FALSE,NULL);
3187  if(NT_SUCCESS(RC)) {
3188  Vcb->CdrwBufferSize = ((PBUFFER_CAPACITY_BLOCK_USER_OUT)ioBuf)->BufferLength;
3189  } else {
3190  Vcb->CdrwBufferSize = 0;
3191  }
3192  UDFPrint(("UDFGetDiskInfo: CdrwBufferSize = %dKb\n", Vcb->CdrwBufferSize / 1024));
3193  Vcb->CdrwBufferSizeCounter = 0;
3194 #endif //_BROWSE_UDF_
3195  // get media type
3197  NULL,0,ioBuf,sizeof(GET_MEDIA_TYPE_USER_OUT),
3198  FALSE, NULL);
3199  if(!OS_SUCCESS(RC)) goto Try_FullToc;
3200  Vcb->MediaType =
3201  MediaType = ((PGET_MEDIA_TYPE_USER_OUT)ioBuf)->MediaType;
3202  UDFPrint(("UDFGetDiskInfo: MediaType %x\n", MediaType));
3203 
3204 #ifndef UDF_FORMAT_MEDIA
3205  // we shall ignore audio-disks
3206  switch(MediaType) {
3213 // case :
3214  UDFPrint(("UDFGetDiskInfo: we shall ignore audio-disks...\n"));
3216  }
3217 #endif //UDF_FORMAT_MEDIA
3218 
3219  UDFPrint(("UDFGetDiskInfo: Check DVD-disks...\n"));
3221  NULL,0,ioBuf,sizeof(GET_MEDIA_TYPE_EX_USER_OUT),
3222  FALSE, NULL);
3223  if(!OS_SUCCESS(RC)) goto Try_FullToc;
3224  Vcb->MediaClassEx =
3225  MediaType = (((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->MediaClass);
3226  UDFPrint(("UDFGetDiskInfo: MediaClassEx %x\n", MediaType));
3227 
3228 #ifdef _BROWSE_UDF_
3229  if(!fms) {
3230 
3231  switch(MediaType) {
3232 
3233  case CdMediaClass_CDR:
3234  case CdMediaClass_DVDR:
3235  case CdMediaClass_DVDpR:
3236  case CdMediaClass_HD_DVDR:
3237  case CdMediaClass_BDR:
3238  UDFPrint(("UDFGetDiskInfo: MediaClass R\n"));
3239  Vcb->MediaType = MediaType_UnknownSize_CDR;
3240  break;
3241  case CdMediaClass_CDRW:
3242 
3243  if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) {
3244  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3245  Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM;
3246  }
3247 
3248  case CdMediaClass_DVDRW:
3249  case CdMediaClass_DVDpRW:
3250  case CdMediaClass_DVDRAM:
3251  case CdMediaClass_HD_DVDRW:
3253  case CdMediaClass_BDRE:
3254  UDFPrint(("UDFGetDiskInfo: MediaClass RW\n"));
3255  Vcb->MediaType = MediaType_UnknownSize_CDRW;
3256  break;
3257  case CdMediaClass_CDROM:
3258  case CdMediaClass_DVDROM:
3260  case CdMediaClass_BDROM:
3261  UDFPrint(("UDFGetDiskInfo: MediaClass ROM\n"));
3262  Vcb->MediaType = MediaType_Unknown;
3263  // Vcb->MediaType = MediaType_UnknownSize_CDROM;
3264  break;
3265  default:
3266  UDFPrint(("UDFGetDiskInfo: MediaClass Unknown\n"));
3267  Vcb->MediaType = MediaType_Unknown;
3268  break;
3269  }
3270  MediaType = Vcb->MediaType;
3271 
3272  }
3273 #endif //_BROWSE_UDF_
3274 
3275 #ifdef UDF_FORMAT_MEDIA
3276 
3277  if(fms) {
3278 
3279  switch(MediaType) {
3280  case CdMediaClass_CDR:
3281  UDFPrint(("CdMediaClass_CDR\n"));
3282  MediaType = MediaType_UnknownSize_CDR;
3283  if(fms->opt_media == MT_AUTO)
3284  fms->opt_media = MT_CDR;
3285  break;
3286  case CdMediaClass_DVDR:
3287  UDFPrint(("CdMediaClass_DVDR -> MediaType_UnknownSize_CDR\n"));
3288  MediaType = MediaType_UnknownSize_CDR;
3289  if(fms->opt_media == MT_AUTO)
3290  fms->opt_media = MT_DVDR;
3291  break;
3292  case CdMediaClass_DVDpR:
3293  UDFPrint(("CdMediaClass_DVDpR -> MediaType_UnknownSize_CDR\n"));
3294  MediaType = MediaType_UnknownSize_CDR;
3295  if(fms->opt_media == MT_AUTO)
3296  fms->opt_media = MT_DVDpR;
3297  break;
3298  case CdMediaClass_HD_DVDR:
3299  UDFPrint(("CdMediaClass_HD_DVDR -> MediaType_UnknownSize_CDR\n"));
3300  MediaType = MediaType_UnknownSize_CDR;
3301  if(fms->opt_media == MT_AUTO)
3302  fms->opt_media = MT_DVDR;
3303  break;
3304  case CdMediaClass_BDR:
3305  UDFPrint(("CdMediaClass_BDR -> MediaType_UnknownSize_CDR\n"));
3306  MediaType = MediaType_UnknownSize_CDR;
3307  if(fms->opt_media == MT_AUTO)
3308  fms->opt_media = MT_DVDR;
3309  break;
3310  case CdMediaClass_CDRW:
3311  UDFPrint(("CdMediaClass_CDRW\n"));
3312  MediaType = MediaType_UnknownSize_CDRW;
3313  if(fms->opt_media == MT_AUTO)
3314  fms->opt_media = MT_CDRW;
3315  if(SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) {
3316  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on CD-RW\n"));
3317  Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM;
3318  }
3319  break;
3320  case CdMediaClass_DVDRW:
3321  UDFPrint((" CdMediaClass_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3322  if(fms->opt_media == MT_AUTO)
3323  fms->opt_media = MT_DVDRW;
3324  MediaType = MediaType_UnknownSize_CDRW;
3325  break;
3326  case CdMediaClass_DVDpRW:
3327  UDFPrint((" CdMediaClass_DVDpRW -> MediaType_UnknownSize_CDRW\n"));
3328  if(fms->opt_media == MT_AUTO)
3329  fms->opt_media = MT_DVDpRW;
3330  MediaType = MediaType_UnknownSize_CDRW;
3331  break;
3332  case CdMediaClass_DVDRAM:
3333  UDFPrint((" CdMediaClass_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3334  if(fms->opt_media == MT_AUTO)
3335  fms->opt_media = MT_DVDRAM;
3336  MediaType = MediaType_UnknownSize_CDRW;
3337  break;
3338  case CdMediaClass_HD_DVDRW:
3339  UDFPrint((" CdMediaClass_HD_DVDRW -> MediaType_UnknownSize_CDRW\n"));
3340  if(fms->opt_media == MT_AUTO)
3341  fms->opt_media = MT_DVDRW;
3342  MediaType = MediaType_UnknownSize_CDRW;
3343  break;
3345  UDFPrint((" CdMediaClass_HD_DVDRAM -> MediaType_UnknownSize_CDRW\n"));
3346  if(fms->opt_media == MT_AUTO)
3347  fms->opt_media = MT_DVDRAM;
3348  MediaType = MediaType_UnknownSize_CDRW;
3349  break;
3350  case CdMediaClass_BDRE:
3351  UDFPrint((" CdMediaClass_BDRE -> MediaType_UnknownSize_CDRW\n"));
3352  if(fms->opt_media == MT_AUTO)
3353  fms->opt_media = MT_DVDRW;
3354  MediaType = MediaType_UnknownSize_CDRW;
3355  break;
3357  UDFPrint((" CdMediaClass_NoDiscPresent -> MediaType_NoDiscPresent\n"));
3358  MediaType = MediaType_NoDiscPresent;
3359  fms->opt_media = MT_none;
3360  break;
3361  case CdMediaClass_DoorOpen:
3362  UDFPrint((" CdMediaClass_DoorOpen -> MediaType_DoorOpen\n"));
3363  MediaType = MediaType_DoorOpen;
3364  fms->opt_media = MT_none;
3365  break;
3366  default:
3367  UDFPrint((" MediaType_Unknown\n"));
3368  MediaType = MediaType_Unknown;
3369  break;
3370  }
3371  if(!apply_force_r(fms)) {
3373  }
3374  }
3375 
3376 #endif //UDF_FORMAT_MEDIA
3377 
3378  Vcb->DVD_Mode = (((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->MediaClassEx == CdMediaClassEx_DVD);
3379  Vcb->PhMediaCapFlags = ((PGET_MEDIA_TYPE_EX_USER_OUT)ioBuf)->CapFlags;
3380  Vcb->WriteParamsReq = (Vcb->PhMediaCapFlags & CdCapFlags_WriteParamsReq) ? TRUE : FALSE;
3381  if(Vcb->DVD_Mode &&
3382  !(Vcb->PhMediaCapFlags & CdCapFlags_RandomWritable)) {
3383  UDFPrint(("UDFGetDiskInfo: DVD && !CdCapFlags_RandomWritable\n"));
3384  UDFPrint((" Read-only volume\n"));
3385 // BrutePoint();
3386 #ifndef UDF_CDRW_EMULATION_ON_ROM
3387  Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
3388 #endif
3389  }
3390 #ifdef UDF_FORMAT_MEDIA
3391  if(fms) {
3392  if((MediaType == MediaType_NoDiscPresent) ||
3393  (MediaType == MediaType_DoorOpen)) {
3394  UserPrint(("No media in device\n"));
3396  }
3397  }
3398 #endif //UDF_FORMAT_MEDIA
3399  if(!Vcb->WriteParamsReq) {
3400  UDFPrint(("UDFGetDiskInfo: do not use WriteParams\n"));
3401  }
3402  if(Vcb->PhMediaCapFlags & CdCapFlags_Cav) {
3403  UDFPrint(("UDFGetDiskInfo: Use CAV (1)\n"));
3404  Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_CAV;
3405  }
3406 
3407 #ifdef _BROWSE_UDF_
3408  if(!fms) {
3409  // check if this device is capable to write on such media
3410  if(UDFIsDvdMedia(Vcb)) {
3411  //RC =
3412  UDFPrint(("UDFGetDiskInfo: update defaulted LastLBA\n"));
3414  //if(!OS_SUCCESS(RC)) goto Try_FullToc;
3415  } else {
3416  if((SavedFeatures & CDRW_FEATURE_MRW_ADDRESSING_PROBLEM) &&
3417  (SavedFeatures & UDF_VCB_IC_FP_ADDR_PROBLEM)) {
3418  UDFPrint(("UDFGetDiskInfo: CDRW_FEATURE_MRW_ADDRESSING_PROBLEM on old CD-ROM\n"));
3419  Vcb->CompatFlags |= UDF_VCB_IC_MRW_ADDR_PROBLEM;
3420  }
3421  }
3422  }
3423 #endif //_BROWSE_UDF_
3424 
3425 /*#ifdef UDF_FORMAT_MEDIA
3426  if(fms) {
3427  if(MediaType == CdMediaClass_DVDRW) {
3428  UserPrint(("Not empty media. Erase required.\n"));
3429  my_exit(fms, MKUDF_BLANK_FORMAT_REQUIRED);
3430  }
3431  }
3432 #endif //UDF_FORMAT_MEDIA*/
3433 
3434 #define cap ((PGET_CAPABILITIES_3_USER_OUT)ioBuf)
3435  // get device capabilities
3437  NULL,0,ioBuf,sizeof(GET_CAPABILITIES_3_USER_OUT),
3438  FALSE, NULL);
3439  if(!OS_SUCCESS(RC)) goto Try_FullToc;
3440 
3441  // check if this device is capable to write on such media
3443  NULL,0,NULL,0,FALSE, NULL);
3444  if(RC != STATUS_SUCCESS) {
3445  UDFPrint(("IS_WRITABLE - false, doing additional check...\n"));
3446  if( ((MediaType >= MediaType_UnknownSize_CDRW) && !(cap->WriteCap & DevCap_write_cd_rw)) ||
3447  ((MediaType >= MediaType_UnknownSize_CDR) && !(cap->WriteCap & DevCap_write_cd_r)) ||
3448  (MediaType < MediaType_UnknownSize_CDR) ) {
3449  UserPrint(("Hardware Read-only volume\n"));
3450 #ifndef UDF_CDRW_EMULATION_ON_ROM
3451  Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
3452 #endif //UDF_CDRW_EMULATION_ON_ROM
3453 #ifdef UDF_FORMAT_MEDIA
3454  if(fms && !fms->opt_read_iso)
3455  my_exit(fms, MKUDF_HW_READ_ONLY);
3456 #endif //UDF_FORMAT_MEDIA
3457  }
3458  } else {
3459  UDFPrint(("Writable disk\n"));
3460  }
3461  Vcb->MaxWriteSpeed = cap->MaximumWriteSpeedSupported;
3462  Vcb->MaxReadSpeed = cap->MaximumSpeedSupported;
3463  if(cap->PageLength >= (sizeof(GET_CAPABILITIES_3_USER_OUT)-2)) {
3464  Vcb->CurSpeed = max(cap->CurrentSpeed, cap->CurrentWriteSpeed3);
3465  if(cap->LunWPerfDescriptorCount && cap->LunWPerfDescriptorCount != 0xffff) {
3466  ULONG n;
3467  UDFPrint(("Write performance descriptor(s) found: %x\n", cap->LunWPerfDescriptorCount));
3468  n = (4096 - sizeof(GET_CAPABILITIES_3_USER_OUT)) / sizeof(LUN_WRITE_PERF_DESC_USER);
3469  n = min(n, cap->LunWPerfDescriptorCount);
3470  // get device capabilities
3474  TRUE,NULL);
3475  if(OS_SUCCESS(RC)) {
3476  WPerfDesc = (PLUN_WRITE_PERF_DESC_USER)(ioBuf + sizeof(GET_CAPABILITIES_3_USER_OUT));
3477  n = FALSE;
3478  for(i = 0; i<n; i++) {
3479  if((WPerfDesc[i].RotationControl & LunWPerf_RotCtrl_Mask) == LunWPerf_RotCtrl_CAV) {
3480  Vcb->VCBFlags |= UDF_VCB_FLAGS_USE_CAV;
3481  if(!n) {
3482  Vcb->CurSpeed = WPerfDesc[i].WriteSpeedSupported;
3483  n = TRUE;
3484  UDFPrint(("Use CAV\n"));
3485  } else {
3486  Vcb->CurSpeed = max(WPerfDesc[i].WriteSpeedSupported, Vcb->CurSpeed);
3487  }
3488  UDFPrint(("supports speed %dX\n", Vcb->CurSpeed/176));
3489  //break;
3490  }
3491  }
3492  if(n) {
3493  UDFPrint(("Set r/w speeds to %dX\n", Vcb->CurSpeed/176));
3494  Vcb->MaxWriteSpeed =
3495  Vcb->MaxReadSpeed = Vcb->CurSpeed;
3496  }
3497  }
3498  }
3499  } else {
3500  Vcb->CurSpeed = max(cap->CurrentSpeed, cap->CurrentWriteSpeed);
3501  }
3502  UDFPrint((" Speeds r/w %dX/%dX\n", Vcb->CurSpeed/176, cap->CurrentWriteSpeed/176));
3503 
3504  if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) {
3505  // limit both read & write speed to last write speed for CAV mode
3506  // some drives damage data when speed is adjusted during recording process
3507  // even in packet mode
3508  UDFSetSpeeds(Vcb);
3509  }
3510  UDFSetCaching(Vcb);
3511 
3512 #undef cap
3513 #ifdef UDF_FORMAT_MEDIA
3514  if(fms) {
3515  if( (fms->auto_media || (fms->opt_media == MT_AUTO)) &&
3516  (fms->opt_media < MT_DVDR) ) {
3517  if(MediaType < MediaType_UnknownSize_CDRW) {
3518  fms->opt_media = MT_CDR;
3519  } else {
3520  fms->opt_media = MT_CDRW;
3521  }
3522  }
3523  if(!apply_force_r(fms)) {
3525  }
3526  }
3527 #endif //UDF_FORMAT_MEDIA
3529 
3530  if(!OS_SUCCESS(RC)) {
3531  // may be we have a CD-ROM device
3532 Try_FullToc:
3533  UDFPrint(("Hardware Read-only volume (2)\n"));
3534 // BrutePoint();
3535 #ifndef UDF_CDRW_EMULATION_ON_ROM
3536  Vcb->VCBFlags |= UDF_VCB_FLAGS_VOLUME_READ_ONLY;
3537 #endif
3538 
3540 
3541  if(!OS_SUCCESS(RC)) {
3543  if(!OS_SUCCESS(RC)) try_return(RC);
3544  }
3545 
3546  }
3547  } else {
3548 #ifdef _BROWSE_UDF_
3549 GetSignatureFailed:
3550 #endif
3552  if(!OS_SUCCESS(RC)) try_return(RC);
3553  }
3554 
3555 try_exit: NOTHING;
3556 
3557  } _SEH2_FINALLY {
3558 
3559  if(ioBuf) MyFreePool__(ioBuf);
3560 
3561  if(UDFIsDvdMedia(Vcb) &&
3562  (Vcb->CompatFlags & UDF_VCB_IC_BAD_DVD_LAST_LBA) &&
3563  (Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) &&
3564  Vcb->LastLBA &&
3565  (Vcb->LastLBA < DEFAULT_LAST_LBA_DVD)) {
3566  UDFPrint(("UDF: Bad DVD last LBA %x, fixup!\n", Vcb->LastLBA));
3567  Vcb->LastLBA = DEFAULT_LAST_LBA_DVD;
3568  Vcb->NWA = 0;
3569  }
3570 
3571 
3572  if(UDFIsDvdMedia(Vcb) && !Vcb->FirstLBA && !Vcb->LastPossibleLBA) {
3573  UDFPrint(("UDF: Empty DVD. Use bogus values for now\n"));
3574  Vcb->LastPossibleLBA = DEFAULT_LAST_LBA_DVD;
3575  Vcb->LastLBA = 0;
3576  }
3577 
3578  if((Vcb->LastPossibleLBA & 0x80000000) || (Vcb->LastPossibleLBA < Vcb->LastLBA)) {
3579  UDFPrint(("UDF: bad LastPossibleLBA %x -> %x\n", Vcb->LastPossibleLBA, Vcb->LastLBA));
3580  Vcb->LastPossibleLBA = Vcb->LastLBA;
3581  }
3582  if(!Vcb->WriteBlockSize)
3583  Vcb->WriteBlockSize = PACKETSIZE_UDF*Vcb->BlockSize;
3584 
3585 #ifdef _BROWSE_UDF_
3586  if(Vcb->TrackMap) {
3587  if(Vcb->TrackMap[Vcb->LastTrackNum].LastLba > Vcb->NWA) {
3588  if(Vcb->NWA) {
3589  if(Vcb->TrackMap[Vcb->LastTrackNum].DataParam & TrkInfo_FP) {
3590  Vcb->LastLBA = Vcb->NWA-1;
3591  } else {
3592  Vcb->LastLBA = Vcb->NWA-7-1;
3593  }
3594  }
3595  } else {
3596  if((Vcb->LastTrackNum > 1) &&
3597  (Vcb->TrackMap[Vcb->LastTrackNum-1].FirstLba >= Vcb->TrackMap[Vcb->LastTrackNum-1].LastLba)) {
3598  Vcb->LastLBA = Vcb->TrackMap[Vcb->LastTrackNum-1].LastLba;
3599  }
3600  }
3601  }
3602 
3603  for(i=0; i<32; i++) {
3604  if(!(Vcb->LastPossibleLBA >> i))
3605  break;
3606  }
3607  if(i > 20) {
3608  Vcb->WCacheBlocksPerFrameSh = max(Vcb->WCacheBlocksPerFrameSh, (2*i)/5+2);
3609  Vcb->WCacheBlocksPerFrameSh = min(Vcb->WCacheBlocksPerFrameSh, 16);
3610  }
3611 
3612  if(Vcb->CompatFlags & UDF_VCB_IC_FP_ADDR_PROBLEM) {
3613  // Check first 0x200 blocks
3614  UDFCheckTrackFPAddressing(Vcb, Vcb->FirstTrackNum);
3615  // if we really have such a problem, fix LastLBA
3616  if(Vcb->CompatFlags & UDF_VCB_IC_FP_ADDR_PROBLEM) {
3617  UDFPrint(("UDF: Fix LastLBA: %x -> %x\n", Vcb->LastLBA, (Vcb->LastLBA*32) / 39));
3618  Vcb->LastLBA = (Vcb->LastLBA*32) / 39;
3619  }
3620  }
3621 #endif //_BROWSE_UDF_
3622 
3623  if(Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY) {
3624  if(!Vcb->BlankCD && Vcb->MediaType != MediaType_UnknownSize_CDRW) {
3625  UDFPrint(("UDFGetDiskInfo: R/O+!Blank+!RW -> !RAW\n"));
3626  Vcb->VCBFlags &= ~UDF_VCB_FLAGS_RAW_DISK;
3627  } else {
3628  UDFPrint(("UDFGetDiskInfo: Blank or RW\n"));
3629  }
3630  }
3631 
3632  UDFPrint(("UDF: ------------------------------------------\n"));
3633  UDFPrint(("UDF: Media characteristics\n"));
3634  UDFPrint(("UDF: Last session: %d\n",Vcb->LastSession));
3635  UDFPrint(("UDF: First track in first session: %d\n",Vcb->FirstTrackNum));
3636  UDFPrint(("UDF: First track in last session: %d\n",Vcb->FirstTrackNumLastSes));
3637  UDFPrint(("UDF: Last track in last session: %d\n",Vcb->LastTrackNum));
3638  UDFPrint(("UDF: First LBA in first session: %x\n",Vcb->FirstLBA));
3639  UDFPrint(("UDF: First LBA in last session: %x\n",Vcb->FirstLBALastSes));
3640  UDFPrint(("UDF: Last LBA in last session: %x\n",Vcb->LastLBA));
3641  UDFPrint(("UDF: First writable LBA (NWA) in last session: %x\n",Vcb->NWA));
3642  UDFPrint(("UDF: Last available LBA beyond end of last session: %x\n",Vcb->LastPossibleLBA));
3643  UDFPrint(("UDF: blocks per frame: %x\n",1 << Vcb->WCacheBlocksPerFrameSh));
3644  UDFPrint(("UDF: Flags: %s%s\n",
3645  Vcb->VCBFlags & UDF_VCB_FLAGS_RAW_DISK ? "RAW " : "",
3646  Vcb->VCBFlags & UDF_VCB_FLAGS_VOLUME_READ_ONLY ? "R/O " : "WR "
3647  ));
3648  UDFPrint(("UDF: ------------------------------------------\n"));
3649 
3650 #ifdef UDF_FORMAT_MEDIA
3651  if(fms && fms->opt_disk_info) {
3652  UserPrint(("------------------------------------------\n"));
3653  UserPrint(("Media characteristics:\n"));
3654  UserPrint((" First writable LBA (NWA) in last session: %x\n",Vcb->NWA));
3655  UserPrint((" Last available LBA beyond end of last session: %x\n",Vcb->LastPossibleLBA));
3656  UserPrint(("------------------------------------------\n"));
3657  }
3658 #endif //UDF_FORMAT_MEDIA
3659 
3660  } _SEH2_END;
3661 
3662  UDFPrint(("UDFGetDiskInfo: %x\n", RC));
3663  return(RC);
3664 
3665 } // end UDFGetDiskInfo()
3666 
3667 //#ifdef _BROWSE_UDF_
3668 
3669 OSSTATUS
3671  IN PVCB Vcb,
3672  IN uint32 Lba,
3673  IN uint32 BCount
3674  )
3675 {
3676  if( (Vcb->FsDeviceType != FILE_DEVICE_CD_ROM_FILE_SYSTEM) ) {
3677  Vcb->VCBFlags &= ~UDF_VCB_LAST_WRITE;
3678  return STATUS_SUCCESS;
3679  }
3680  uint32 i = Vcb->LastReadTrack;
3681  BOOLEAN speed_changed = FALSE;
3682 #ifdef _BROWSE_UDF_
3683  PUCHAR tmp;
3684  OSSTATUS RC;
3685  SIZE_T ReadBytes;
3686 #endif //_BROWSE_UDF_
3687 
3688 #ifdef _UDF_STRUCTURES_H_
3689  if(Vcb->BSBM_Bitmap) {
3690  ULONG i;
3691  for(i=0; i<BCount; i++) {
3692  if(UDFGetBit((uint32*)(Vcb->BSBM_Bitmap), Lba+i)) {
3693  UDFPrint(("R: Known BB @ %#x\n", Lba));
3694  //return STATUS_FT_WRITE_RECOVERY; // this shall not be treated as error and
3695  // we shall get IO request to BAD block
3696  return STATUS_DEVICE_DATA_ERROR;
3697  }
3698  }
3699  }
3700 #endif //_UDF_STRUCTURES_H_
3701 
3702  if(!UDFIsDvdMedia(Vcb) &&
3703  (Vcb->VCBFlags & UDF_VCB_LAST_WRITE) &&
3704  !(Vcb->VCBFlags & UDF_VCB_FLAGS_NO_SYNC_CACHE) &&
3705  !(Vcb->CompatFlags & UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE)){
3706 
3707 // OSSTATUS RC;
3708 
3709  RC = UDFSyncCache(Vcb);
3710  }
3711  if( (Vcb->VCBFlags & UDF_VCB_LAST_WRITE) &&
3712  !(Vcb->VCBFlags & UDF_VCB_FLAGS_NO_SYNC_CACHE) &&
3713 #ifndef UDF_FORMAT_MEDIA
3714  (Vcb->CompatFlags & UDF_VCB_IC_SYNCCACHE_BEFORE_READ) &&
3715 #endif //UDF_FORMAT_MEDIA
3716  TRUE)
3717  {
3718 // OSSTATUS RC;
3719  UDFSyncCache(Vcb);
3720  }
3721 
3722 #ifdef _BROWSE_UDF_
3723  if(!UDFIsDvdMedia(Vcb)) {
3724  // limit read speed after write operation
3725  // to avoid performance degrade durring speed-up/down
3726  // on read/write mode switching
3727  if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) {
3728  // limit both read & write speed to last write speed for CAV mode
3729  // some drives damage data when speed is adjusted during recording process
3730  // even in packet mode
3731  if(Vcb->CurSpeed != Vcb->MaxWriteSpeed ||
3732  Vcb->CurSpeed != Vcb->MaxReadSpeed) {
3733  Vcb->CurSpeed = Vcb->MaxWriteSpeed;
3734  speed_changed = TRUE;
3735  }
3736  } else
3737  if(Vcb->VCBFlags & UDF_VCB_LAST_WRITE) {
3738  // limit read speed to last write speed
3739  if(Vcb->CurSpeed > Vcb->MaxWriteSpeed) {
3740  Vcb->CurSpeed = Vcb->MaxWriteSpeed;
3741  speed_changed = TRUE;
3742  }
3743  } else
3744  if(Vcb->CurSpeed < Vcb->MaxReadSpeed ) {
3745  // increment read speed (+1X)
3746  Vcb->CurSpeed += 176/1;
3747  speed_changed = TRUE;
3748  }
3749 
3750  if(Vcb->CurSpeed > Vcb->MaxReadSpeed) {
3751  Vcb->CurSpeed = Vcb->MaxReadSpeed;
3752  }
3753  // send speed limits to drive
3754  if(speed_changed) {
3755  RtlZeroMemory(&(Vcb->SpeedBuf), sizeof(SET_CD_SPEED_EX_USER_IN));
3756  Vcb->SpeedBuf.ReadSpeed = Vcb->CurSpeed;
3757  Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed;
3758  if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) {
3759  Vcb->SpeedBuf.RotCtrl = CdSpeed_RotCtrl_CAV;
3760  }
3761  UDFPrint((" UDFPrepareForReadOperation: set speed to %s %dX/%dX\n",
3762  (Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) ? "CAV" : "CLV",
3763  Vcb->SpeedBuf.ReadSpeed,
3764  Vcb->SpeedBuf.WriteSpeed));
3766  Vcb->TargetDeviceObject,
3767  &(Vcb->SpeedBuf),sizeof(SET_CD_SPEED_EX_USER_IN),
3768  NULL,0,TRUE,NULL);
3769  }
3770  }
3771 
3772  if(UDFIsDvdMedia(Vcb))
3773  return STATUS_SUCCESS;
3774 
3775  if(Vcb->LastReadTrack &&
3776  ((Vcb->TrackMap[i].FirstLba <= Lba) || (Vcb->TrackMap[i].FirstLba & 0x80000000)) &&
3777  (Vcb->TrackMap[i].LastLba >= Lba)) {
3778 check_for_data_track:
3779  // check track mode (Mode1/XA)
3780  switch((Vcb->TrackMap[i].DataParam & TrkInfo_Dat_Mask)) {
3781  case TrkInfo_Dat_Mode1: // Mode1
3782  case TrkInfo_Dat_XA: // XA Mode2
3783  case TrkInfo_Dat_Unknown: // for some stupid irons
3784  UDFSetMRWMode(Vcb);
3785  break;
3786  default:
3787  Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE;
3788  return STATUS_INVALID_PARAMETER;
3789  }
3790  } else {
3791  for(i=Vcb->FirstTrackNum; i<=Vcb->LastTrackNum; i++) {
3792  if(((Vcb->TrackMap[i].FirstLba > Lba) && !(Vcb->TrackMap[i].FirstLba & 0x80000000)) ||
3793  (Vcb->TrackMap[i].LastLba < Lba))
3794  continue;
3795  Vcb->LastReadTrack = i;
3796  goto check_for_data_track;
3797  }
3798  Vcb->LastReadTrack = 0;
3799  }
3800  if(Vcb->IncrementalSeekState != INCREMENTAL_SEEK_WORKAROUND) {
3801  Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE;
3802  return STATUS_SUCCESS;
3803  }
3804  UDFPrint((" UDFPrepareForReadOperation: seek workaround...\n"));
3805  Vcb->IncrementalSeekState = INCREMENTAL_SEEK_DONE;
3806 
3807  tmp = (PUCHAR)DbgAllocatePoolWithTag(NonPagedPool, Vcb->BlockSize, 'bNWD');
3808  if(!tmp) {
3809  Vcb->IncrementalSeekState = INCREMENTAL_SEEK_NONE;
3811  }
3812  for(i=0x1000; i<=Lba; i+=0x1000) {
3813  RC = UDFPhReadSynchronous(Vcb->TargetDeviceObject, tmp, Vcb->BlockSize,
3814  ((uint64)UDFFixFPAddress(Vcb,i)) << Vcb->BlockSizeBits, &ReadBytes, 0);
3815  UDFPrint((" seek workaround, LBA %x, status %x\n", i, RC));
3816  }
3817  DbgFreePool(tmp);
3818 #endif //_BROWSE_UDF_
3819 
3820  return STATUS_SUCCESS;
3821 } // end UDFPrepareForReadOperation()
3822 
3823 //#endif //_BROWSE_UDF_
3824 
3825 void
3827  PVCB Vcb,
3828  uint32 LBA, // physical
3829  uint32 BCount,
3830  OSSTATUS RC
3831  )
3832 {
3833 #ifndef UDF_READ_ONLY_BUILD
3834 #ifdef _BROWSE_UDF_
3835  if(!OS_SUCCESS(RC)) {
3836  return;
3837  }
3838  if(!Vcb->CDR_Mode) {
3839 
3840  if((Vcb->MediaClassEx == CdMediaClass_DVDRW ||
3841  Vcb->MediaClassEx == CdMediaClass_DVDpRW ||
3842  Vcb->MediaClassEx == CdMediaClass_DVDRAM ||
3843  Vcb->MRWStatus == DiscInfo_BGF_Interrupted ||
3844  Vcb->MRWStatus == DiscInfo_BGF_InProgress)
3845  && (LBA+BCount-1) > Vcb->LastLBA) {
3846  ASSERT(Vcb->NWA > Vcb->LastLBA);
3847  Vcb->NWA = LBA+BCount;
3848  Vcb->LastLBA = Vcb->NWA-1;
3849  }
3850  if(Vcb->VCBFlags & UDF_VCB_FLAGS_FORCE_SYNC_CACHE)
3851  goto sync_cache;
3852 /* if(Vcb->CdrwBufferSize) {
3853  Vcb->CdrwBufferSizeCounter += BCount * 2048;
3854  if(Vcb->CdrwBufferSizeCounter >= Vcb->CdrwBufferSize + 2*2048) {
3855  UDFPrint((" UDFUpdateNWA: buffer is full, sync...\n"));
3856  Vcb->CdrwBufferSizeCounter = 0;
3857  goto sync_cache;
3858  }
3859  }*/
3860  if(Vcb->SyncCacheState == SYNC_CACHE_RECOVERY_RETRY) {
3861  Vcb->VCBFlags |= UDF_VCB_FLAGS_FORCE_SYNC_CACHE;
3862  }
3863  Vcb->SyncCacheState = SYNC_CACHE_RECOVERY_NONE;
3864  return;
3865  }
3866  if(Vcb->LastLBA < (LBA+BCount))
3867  Vcb->LastLBA = LBA+BCount;
3868  if(Vcb->NWA)
3869  Vcb->NWA+=BCount+7;
3870 sync_cache:
3871  if(!(Vcb->CompatFlags & UDF_VCB_IC_NO_SYNCCACHE_AFTER_WRITE)) {
3872  UDFPrint((" UDFUpdateNWA: syncing...\n"));
3873  RC = UDFSyncCache(Vcb);
3874  }
3875 #endif //_BROWSE_UDF_
3876 #endif //UDF_READ_ONLY_BUILD
3877 } // end UDFUpdateNWA()
3878 
3879 
3880 /*
3881  This routine reads physical sectors
3882  */
3883 /*OSSTATUS
3884 UDFReadSectors(
3885  IN PVCB Vcb,
3886  IN BOOLEAN Translate, // Translate Logical to Physical
3887  IN uint32 Lba,
3888  IN uint32 BCount,
3889  OUT int8* Buffer,
3890  OUT PSIZE_T ReadBytes
3891  )
3892 {
3893 
3894  if(Vcb->FastCache.ReadProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
3895  return WCacheReadBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, ReadBytes);
3896  }
3897  return UDFTRead(Vcb, Buffer, BCount*Vcb->BlockSize, Lba, ReadBytes);
3898 } // end UDFReadSectors()*/
3899 
3900 #ifdef _BROWSE_UDF_
3901 
3902 /*
3903  This routine reads physical sectors
3904  */
3905 OSSTATUS
3907  IN PVCB Vcb,
3908  IN BOOLEAN Translate, // Translate Logical to Physical
3909  IN uint32 Lba,
3910  IN uint32 i, // offset in sector
3911  IN uint32 l, // transfer length
3912  IN BOOLEAN Direct, // Disable access to non-cached data
3913  OUT int8* Buffer,
3915  )
3916 {
3917  int8* tmp_buff;
3918  OSSTATUS status;
3919  SIZE_T _ReadBytes;
3920 
3921  (*ReadBytes) = 0;
3922  if(WCacheIsInitialized__(&(Vcb->FastCache)) && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
3923  status = WCacheDirect__(&(Vcb->FastCache), Vcb, Lba, FALSE, &tmp_buff, Direct);
3924  if(OS_SUCCESS(status)) {
3925  (*ReadBytes) += l;
3926  RtlCopyMemory(Buffer, tmp_buff+i, l);
3927  }
3928  if(!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb);
3929  } else {
3930  if(Direct) {
3931  return STATUS_INVALID_PARAMETER;
3932  }
3933  tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize);
3934  if(!tmp_buff) return STATUS_INSUFFICIENT_RESOURCES;
3935  status = UDFReadSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_ReadBytes);
3936  if(OS_SUCCESS(status)) {
3937  (*ReadBytes) += l;
3938  RtlCopyMemory(Buffer, tmp_buff+i, l);
3939  }
3940  MyFreePool__(tmp_buff);
3941  }
3942  return status;
3943 } // end UDFReadInSector()
3944 
3945 /*
3946  This routine reads data of unaligned offset & length
3947  */
3948 OSSTATUS
3949 UDFReadData(
3950  IN PVCB Vcb,
3951  IN BOOLEAN Translate, // Translate Logical to Physical
3952  IN int64 Offset,
3953  IN uint32 Length,
3954  IN BOOLEAN Direct, // Disable access to non-cached data
3955  OUT int8* Buffer,
3957  )
3958 {
3959  uint32 i, l, Lba, BS=Vcb->BlockSize;
3960  uint32 BSh=Vcb->BlockSizeBits;
3961  OSSTATUS status;
3962  SIZE_T _ReadBytes = 0;
3963  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
3964  uint32 to_read;
3965 
3966  (*ReadBytes) = 0;
3967  if(!Length) return STATUS_SUCCESS;
3968  if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD)
3969  return STATUS_NO_SUCH_DEVICE;
3970  // read tail of the 1st sector if Offset is not sector_size-aligned
3971  Lba = (uint32)(Offset >> BSh);
3972  if((i = (uint32)(Offset & (BS-1)))) {
3973  l = (BS - i) < Length ?
3974  (BS - i) : Length;
3975  // here we use 'ReadBytes' 'cause now it's set to zero
3976  status = UDFReadInSector(Vcb, Translate, Lba, i, l, Direct, Buffer, ReadBytes);
3977  if(!OS_SUCCESS(status)) return status;
3978  if(!(Length = Length - l)) return STATUS_SUCCESS;
3979  Lba ++;
3980  Buffer += l;
3981  }
3982  // read sector_size-aligned part
3983  i = Length >> BSh;
3984  while(i) {
3985  to_read = min(i, 64);
3986  status = UDFReadSectors(Vcb, Translate, Lba, to_read, Direct, Buffer, &_ReadBytes);
3987  (*ReadBytes) += _ReadBytes;
3988  if(!OS_SUCCESS(status)) {
3989  return status;
3990  }
3991  Buffer += to_read<<BSh;
3992  Length -= to_read<<BSh;
3993  Lba += to_read;
3994  i -= to_read;
3995  }
3996  // read head of the last sector
3997  if(!Length) return STATUS_SUCCESS;
3998  status = UDFReadInSector(Vcb, Translate, Lba, 0, Length, Direct, Buffer, &_ReadBytes);
3999  (*ReadBytes) += _ReadBytes;
4000 
4001  return status;
4002 } // end UDFReadData()
4003 
4004 #endif //_BROWSE_UDF_
4005 
4006 #ifndef UDF_READ_ONLY_BUILD
4007 /*
4008  This routine writes physical sectors. This routine supposes Lba & Length
4009  alignment on WriteBlock (packet) size.
4010  */
4011 OSSTATUS
4013  IN PVCB Vcb,
4014  IN BOOLEAN Translate, // Translate Logical to Physical
4015  IN uint32 Lba,
4016  IN uint32 BCount,
4017  IN BOOLEAN Direct, // Disable access to non-cached data
4018  IN int8* Buffer,
4019  OUT PSIZE_T WrittenBytes
4020  )
4021 {
4022  OSSTATUS status;
4023 
4024 #ifdef _BROWSE_UDF_
4025  if(!Vcb->Modified || (Vcb->IntegrityType == INTEGRITY_TYPE_CLOSE)) {
4027  if(Vcb->LVid && !Direct) {
4029  }
4030  }
4031 
4032  if(Vcb->CDR_Mode) {
4033  if(Vcb->LastLBA < Lba+BCount-1)
4034  Vcb->LastLBA = Lba+BCount-1;
4035  }
4036 #endif //_BROWSE_UDF_
4037 
4038  if(Vcb->FastCache.WriteProc && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
4039  status = WCacheWriteBlocks__(&(Vcb->FastCache), Vcb, Buffer, Lba, BCount, WrittenBytes, Direct);
4041 #ifdef _BROWSE_UDF_
4042  UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, BCount);
4043 #endif //_BROWSE_UDF_
4044  return status;
4045  }
4046 /* void* buffer;
4047  OSSTATUS status;
4048  SIZE_T _ReadBytes;
4049  (*WrittenBytes) = 0;
4050  buffer = DbgAllocatePool(NonPagedPool, Vcb->WriteBlockSize);
4051  if(!buffer) return STATUS_INSUFFICIENT_RESOURCES;
4052  status = UDFTRead(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, (Lba&~(Vcb->WriteBlockSize-1), _WrittenBytes);*/
4053 #ifdef UDF_DBG
4054  status = UDFTWrite(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, Lba, WrittenBytes);
4056  return status;
4057 #else // UDF_DBG
4058  return UDFTWrite(Vcb, Buffer, BCount<<Vcb->BlockSizeBits, Lba, WrittenBytes);
4059 #endif // UDF_DBG
4060 } // end UDFWriteSectors()
4061 
4062 OSSTATUS
4064  IN PVCB Vcb,
4065  IN BOOLEAN Translate, // Translate Logical to Physical
4066  IN uint32 Lba,
4067  IN uint32 i, // offset in sector
4068  IN uint32 l, // transfer length
4069  IN BOOLEAN Direct, // Disable access to non-cached data
4070  OUT int8* Buffer,
4071  OUT PSIZE_T WrittenBytes
4072  )
4073 {
4074  int8* tmp_buff;
4075  OSSTATUS status;
4076 #ifdef _BROWSE_UDF_
4077  SIZE_T _WrittenBytes;
4078  SIZE_T ReadBytes;
4079 
4080  if(!Vcb->Modified) {
4082  if(Vcb->LVid)
4084  }
4085 
4086  if(Vcb->CDR_Mode) {
4087  if(Vcb->LastLBA < Lba)
4088  Vcb->LastLBA = Lba;
4089  }
4090 #endif //_BROWSE_UDF_
4091 
4092  (*WrittenBytes) = 0;
4093 #ifdef _BROWSE_UDF_
4094  if(WCacheIsInitialized__(&(Vcb->FastCache)) && (KeGetCurrentIrql() < DISPATCH_LEVEL)) {
4095 #endif //_BROWSE_UDF_
4096  status = WCacheDirect__(&(Vcb->FastCache), Vcb, Lba, TRUE, &tmp_buff, Direct);
4097  if(OS_SUCCESS(status)) {
4098 #ifdef _BROWSE_UDF_
4099  UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba);
4100 #endif //_BROWSE_UDF_
4101  (*WrittenBytes) += l;
4102  RtlCopyMemory(tmp_buff+i, Buffer, l);
4103  }
4104  if(!Direct) WCacheEODirect__(&(Vcb->FastCache), Vcb);
4105 #ifdef _BROWSE_UDF_
4106  } else {
4107  // If Direct = TRUE we should never get here, but...
4108  if(Direct) {
4109  BrutePoint();
4110  return STATUS_INVALID_PARAMETER;
4111  }
4112  tmp_buff = (int8*)MyAllocatePool__(NonPagedPool, Vcb->BlockSize);
4113  if(!tmp_buff) {
4114  BrutePoint();
4116  }
4117  // read packet
4118  status = UDFReadSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &ReadBytes);
4119  if(!OS_SUCCESS(status)) goto EO_WrSctD;
4120  // modify packet
4121  RtlCopyMemory(tmp_buff+i, Buffer, l);
4122  // write modified packet
4123  status = UDFWriteSectors(Vcb, Translate, Lba, 1, FALSE, tmp_buff, &_WrittenBytes);
4124  if(OS_SUCCESS(status))
4125  (*WrittenBytes) += l;
4126 EO_WrSctD:
4127  MyFreePool__(tmp_buff);
4128  }
4130  if(!OS_SUCCESS(status)) {
4131  UDFPrint(("UDFWriteInSector() for LBA %x failed\n", Lba));
4132  }
4133 #endif //_BROWSE_UDF_
4134  return status;
4135 } // end UDFWriteInSector()
4136 
4137 /*
4138  This routine writes data at unaligned offset & length
4139  */
4140 OSSTATUS
4142  IN PVCB Vcb,
4143  IN BOOLEAN Translate, // Translate Logical to Physical
4144  IN int64 Offset,
4145  IN SIZE_T Length,
4146  IN BOOLEAN Direct, // setting this flag delays flushing of given
4147  // data to indefinite term
4148  IN int8* Buffer,
4149  OUT PSIZE_T WrittenBytes
4150  )
4151 {
4152  uint32 i, l, Lba, BS=Vcb->BlockSize;
4153  uint32 BSh=Vcb->BlockSizeBits;
4154  OSSTATUS status;
4155  SIZE_T _WrittenBytes;
4156  Vcb->VCBFlags |= UDF_VCB_SKIP_EJECT_CHECK;
4157 
4158  (*WrittenBytes) = 0;
4159  if(!Length) return STATUS_SUCCESS;
4160  if(Vcb->VCBFlags & UDF_VCB_FLAGS_DEAD)
4161  return STATUS_NO_SUCH_DEVICE;
4162  // write tail of the 1st sector if Offset is not sector_size-aligned
4163  Lba = (uint32)(Offset >> BSh);
4164  if((i = ((uint32)Offset & (BS-1)))) {
4165  l = (BS - i) < Length ?
4166  (BS - i) : Length;
4167  status = UDFWriteInSector(Vcb, Translate, Lba, i, l, Direct, Buffer, WrittenBytes);
4168  if(!OS_SUCCESS(status)) return status;
4169  if(!(Length = Length - l)) return STATUS_SUCCESS;
4170  Lba ++;
4171  Buffer += l;
4172  }
4173  // write sector_size-aligned part
4174  i = Length >> BSh;
4175  if(i) {
4176  status = UDFWriteSectors(Vcb, Translate, Lba, i, Direct, Buffer, &_WrittenBytes);
4177  (*WrittenBytes) += _WrittenBytes;
4178  if(!OS_SUCCESS(status)) return status;
4179  l = i<<BSh;
4180 #ifdef _BROWSE_UDF_
4181  UDFClrZeroBits(Vcb->ZSBM_Bitmap, Lba, i);
4182 #endif //_BROWSE_UDF_
4183  if(!(Length = Length - l)) return STATUS_SUCCESS;
4184  Lba += i;
4185  Buffer += l;
4186  }
4187  status = UDFWriteInSector(Vcb, Translate, Lba, 0, Length, Direct, Buffer, &_WrittenBytes);
4188  (*WrittenBytes) += _WrittenBytes;
4189 #ifdef _BROWSE_UDF_
4190  UDFClrZeroBit(Vcb->ZSBM_Bitmap, Lba);
4191 #endif //_BROWSE_UDF_
4192 
4193  return status;
4194 } // end UDFWriteData()
4195 
4196 #endif //UDF_READ_ONLY_BUILD
4197 
4198 OSSTATUS
4200  IN PVCB Vcb,
4202  IN BOOLEAN Unlock
4203  )
4204 {
4207  OSSTATUS RC;
4208  if(!tmp)
4211  tmp->UnlockTray = (Unlock ? 1 : 0);
4212  tmp->MagicWord = 0x3a6 | (Unlock ? 1 : 0);
4214  tmp, sizeof(CDRW_RESET_DRIVER_USER_IN), NULL, 0, TRUE,NULL);
4215  if(Vcb) {
4216  Vcb->LastReadTrack = 0;
4217  Vcb->LastModifiedTrack = 0;
4218  Vcb->OPCDone = FALSE;
4219  if((Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) &&
4220  Vcb->TargetDeviceObject) {
4221  // limit both read & write speed to last write speed for CAV mode
4222  // some drives damage data when speed is adjusted during recording process
4223  // even in packet mode
4224  UDFSetSpeeds(Vcb);
4225  }
4226  UDFSetCaching(Vcb);
4227  }
4228 
4229  MyFreePool__(tmp);
4230  return RC;
4231 } // end UDFResetDeviceDriver()
4232 
4233 OSSTATUS
4235  IN PVCB Vcb
4236  )
4237 {
4238  OSSTATUS RC;
4239 
4240  RtlZeroMemory(&(Vcb->SpeedBuf), sizeof(SET_CD_SPEED_EX_USER_IN));
4241  if(Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) {
4242  Vcb->SpeedBuf.RotCtrl = CdSpeed_RotCtrl_CAV;
4243  Vcb->CurSpeed =
4244  Vcb->SpeedBuf.ReadSpeed =
4245  Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed;
4246  } else {
4247  Vcb->SpeedBuf.ReadSpeed = Vcb->CurSpeed;
4248  Vcb->SpeedBuf.WriteSpeed = Vcb->MaxWriteSpeed;
4249  }
4250  UDFPrint((" UDFSetSpeeds: set speed to %s %dX/%dX\n",
4251  (Vcb->VCBFlags & UDF_VCB_FLAGS_USE_CAV) ? "CAV" : "CLV",
4252  Vcb->SpeedBuf.ReadSpeed / 176,
4253  Vcb->SpeedBuf.WriteSpeed / 176));
4255  Vcb->TargetDeviceObject,
4256  &(Vcb->SpeedBuf),sizeof(SET_CD_SPEED_EX_USER_IN),
4257  NULL,0,TRUE,NULL);
4258  UDFPrint(("UDFSetSpeeds: %x\n", RC));
4259  return RC;
4260 } // end UDFSetSpeeds()
4261 
4262 NTSTATUS
4264  IN PVCB Vcb
4265  )
4266 {
4267 #pragma pack(push,1)
4268  struct {
4271  CHAR Padding [16];
4272  } CachingPage;
4273 
4274  struct {
4277  CHAR Padding [16];
4278  } RecoveryPage;
4279 #ifdef _MSC_VER
4280 #pragma pack(pop,1)
4281 #else
4282 #pragma pack(pop)
4283 #endif
4284 
4285  MODE_SENSE_USER_IN ModeSenseCtl;
4286  OSSTATUS RC;
4287 
4288  UDFPrint(("UDFSetCaching:\n"));
4289 
4290  ModeSenseCtl.PageCode.Byte = MODE_PAGE_ERROR_RECOVERY;
4291  RC = UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE, Vcb->TargetDeviceObject,
4292  &ModeSenseCtl,sizeof(ModeSenseCtl),
4293  (PVOID)&RecoveryPage,sizeof(RecoveryPage),
4294  FALSE, NULL);
4295  if(OS_SUCCESS(RC)) {
4296  UDFPrint((" Error recovery page:\n"
4297  "PageCode %d\n"
4298  "PageLength %d\n"
4299 
4300  "DCRBit %d\n"
4301  "DTEBit %d\n"
4302  "PERBit %d\n"
4303  "EERBit %d\n"
4304  "RCBit %d\n"
4305  "TBBit %d\n"
4306  "ARRE %d\n"
4307  "AWRE %d\n"
4308 
4309  "ReadRetryCount %d\n"
4310  "CorrectionSpan %d\n"
4311  "HeadOffsetCount %d\n"
4312  "DataStrobOffsetCount %d\n"
4313 
4314  "ErrorRecoveryParam2.Fields.EMCDR %d\n"
4315 
4316  "WriteRetryCount %d\n",
4317 
4318  RecoveryPage.Data.PageCode,
4319  RecoveryPage.Data.PageLength,
4320 
4321  RecoveryPage.Data.ErrorRecoveryParam.Fields.DCRBit,
4322  RecoveryPage.Data.ErrorRecoveryParam.Fields.DTEBit,
4323  RecoveryPage.Data.ErrorRecoveryParam.Fields.PERBit,
4324  RecoveryPage.Data.ErrorRecoveryParam.Fields.EERBit,
4325  RecoveryPage.Data.ErrorRecoveryParam.Fields.RCBit,
4326  RecoveryPage.Data.ErrorRecoveryParam.Fields.TBBit,
4327  RecoveryPage.Data.ErrorRecoveryParam.Fields.ARRE,
4328  RecoveryPage.Data.ErrorRecoveryParam.Fields.AWRE,
4329 
4330  RecoveryPage.Data.ReadRetryCount,
4331  RecoveryPage.Data.CorrectionSpan,
4332  RecoveryPage.Data.HeadOffsetCount,
4333  RecoveryPage.Data.DataStrobOffsetCount,
4334 
4335  RecoveryPage.Data.ErrorRecoveryParam2.Fields.EMCDR,
4336 
4337  RecoveryPage.Data.WriteRetryCount
4338 
4339  ));
4340  }
4341 
4342  ModeSenseCtl.PageCode.Byte = MODE_PAGE_CACHING;
4343  RC = UDFPhSendIOCTL(IOCTL_CDRW_MODE_SENSE, Vcb->TargetDeviceObject,
4344  &ModeSenseCtl,sizeof(ModeSenseCtl),
4345  (PVOID)&CachingPage,sizeof(CachingPage),
4346  FALSE, NULL);
4347  if(!OS_SUCCESS(RC)) {
4348  return RC;
4349  }
4350 
4351  UDFPrint((" Caching page:\n"
4352  "PageCode %d\n"
4353  "PageLength %d\n"
4354  "ReadDisableCache %d\n"
4355  "MultiplicationFactor %d\n"
4356  "WriteCacheEnable %d\n"
4357  "WriteRetensionPriority %d\n"
4358  "ReadRetensionPriority %d\n",
4359 
4360  CachingPage.Data.PageCode,
4361  CachingPage.Data.PageLength,
4362  CachingPage.Data.ReadDisableCache,
4363  CachingPage.Data.MultiplicationFactor,
4364  CachingPage.Data.WriteCacheEnable,
4365  CachingPage.Data.WriteRetensionPriority,
4366  CachingPage.Data.ReadRetensionPriority
4367  ));
4368 
4369  RtlZeroMemory(&CachingPage.Header, sizeof(CachingPage.Header));
4370  CachingPage.Data.PageCode = MODE_PAGE_CACHING;
4371  CachingPage.Data.PageSavable = 0;
4372  if( CachingPage.Data.ReadDisableCache ||
4373  !CachingPage.Data.WriteCacheEnable) {
4374  CachingPage.Data.ReadDisableCache = 0;
4375  CachingPage.Data.WriteCacheEnable = 1;
4376  RC = UDFPhSendIOCTL(IOCTL_CDRW_MODE_SELECT, Vcb->TargetDeviceObject,
4377  (PVOID)&CachingPage,sizeof(CachingPage.Header) + 2 + CachingPage.Data.PageLength,
4378  NULL,0,
4379  FALSE, NULL);
4380  } else {
4381  RC = STATUS_SUCCESS;
4382  }
4383  UDFPrint(("UDFSetCaching: %x\n", RC));
4384  return RC;
4385 } // end UDFSetCaching()
#define TrackMap_CopyBit_variated
Definition: cdrw_usr.h:1638
unsigned long long uint64
Definition: platform.h:18
#define TrkInfo_Trk_unknown
Definition: cdrw_hw.h:2393