ReactOS  0.4.13-dev-99-g7e18b6d
cddata.c
Go to the documentation of this file.
1 
2 /*++
3 
4 Copyright (c) 1989-2000 Microsoft Corporation
5 
6 Module Name:
7 
8  CdData.c
9 
10 Abstract:
11 
12  This module declares the global data used by the Cdfs file system.
13 
14  This module also handles the dispath routines in the Fsd threads as well as
15  handling the IrpContext and Irp through the exception path.
16 
17 
18 --*/
19 
20 #include "cdprocs.h"
21 
22 #ifdef CD_SANITY
23 BOOLEAN CdTestTopLevel = TRUE;
24 BOOLEAN CdTestRaisedStatus = TRUE;
25 BOOLEAN CdBreakOnAnyRaise = FALSE;
26 BOOLEAN CdTraceRaises = FALSE;
27 NTSTATUS CdInterestingExceptionCodes[] = { STATUS_DISK_CORRUPT_ERROR,
29  0, 0, 0, 0, 0, 0, 0, 0 };
30 #endif
31 
32 //
33 // The Bug check file id for this module
34 //
35 
36 #define BugCheckFileId (CDFS_BUG_CHECK_CDDATA)
37 
38 //
39 // Global data structures
40 //
41 
44 
45 //
46 // Reserved directory strings.
47 //
48 
50 WCHAR CdUnicodeParentArray[] = { L'.', L'.' };
51 
53  { 2, 2, CdUnicodeSelfArray},
54  { 4, 4, CdUnicodeParentArray}
55 };
56 
57 //
58 // Volume descriptor identifier strings.
59 //
60 
61 CHAR CdHsgId[] = { 'C', 'D', 'R', 'O', 'M' };
62 CHAR CdIsoId[] = { 'C', 'D', '0', '0', '1' };
63 CHAR CdXaId[] = { 'C', 'D', '-', 'X', 'A', '0', '0', '1' };
64 
65 //
66 // Volume label for audio disks.
67 //
68 
69 WCHAR CdAudioLabel[] = { L'A', L'u', L'd', L'i', L'o', L' ', L'C', L'D' };
71 
72 //
73 // Pseudo file names for audio disks.
74 //
75 
76 CHAR CdAudioFileName[] = { 'T', 'r', 'a', 'c', 'k', '0', '0', '.', 'c', 'd', 'a' };
81 
82 //
83 // Escape sequences for mounting Unicode volumes.
84 //
85 
86 PCHAR CdJolietEscape[] = { "%/@", "%/C", "%/E" };
87 
88 //
89 // Audio Play Files consist completely of this header block. These
90 // files are readable in the root of any audio disc regardless of
91 // the capabilities of the drive.
92 //
93 // The "Unique Disk ID Number" is a calculated value consisting of
94 // a combination of parameters, including the number of tracks and
95 // the starting locations of those tracks.
96 //
97 // Applications interpreting CDDA RIFF files should be advised that
98 // additional RIFF file chunks may be added to this header in the
99 // future in order to add information, such as the disk and song title.
100 //
101 
103  0x46464952, // Chunk ID = 'RIFF'
104  4 * 11 - 8, // Chunk Size = (file size - 8)
105  0x41444443, // 'CDDA'
106  0x20746d66, // 'fmt '
107  24, // Chunk Size (of 'fmt ' subchunk) = 24
108  0x00000001, // WORD Format Tag, WORD Track Number
109  0x00000000, // DWORD Unique Disk ID Number
110  0x00000000, // DWORD Track Starting Sector (LBN)
111  0x00000000, // DWORD Track Length (LBN count)
112  0x00000000, // DWORD Track Starting Sector (MSF)
113  0x00000000 // DWORD Track Length (MSF)
114 };
115 
116 // Audio Philes begin with this header block to identify the data as a
117 // PCM waveform. AudioPhileHeader is coded as if it has no data included
118 // in the waveform. Data must be added in 2352-byte multiples.
119 //
120 // Fields marked 'ADJUST' need to be adjusted based on the size of the
121 // data: Add (nSectors*2352) to the DWORDs at offsets 1*4 and 10*4.
122 //
123 // File Size of TRACK??.WAV = nSectors*2352 + sizeof(AudioPhileHeader)
124 // RIFF('WAVE' fmt(1, 2, 44100, 176400, 16, 4) data( <CD Audio Raw Data> )
125 //
126 // The number of sectors in a CD-XA CD-DA file is (DataLen/2048).
127 // CDFS will expose these files to applications as if they were just
128 // 'WAVE' files, adjusting the file size so that the RIFF file is valid.
129 //
130 // NT NOTE: We do not do any fidelity adjustment. These are presented as raw
131 // 2352 byte sectors - 95 has the glimmer of an idea to allow CDFS to expose
132 // the CDXA CDDA data at different sampling rates in a virtual directory
133 // structure, but we will never do that.
134 //
135 
137  0x46464952, // Chunk ID = 'RIFF'
138  -8, // Chunk Size = (file size - 8) ADJUST1
139  0x45564157, // 'WAVE'
140  0x20746d66, // 'fmt '
141  16, // Chunk Size (of 'fmt ' subchunk) = 16
142  0x00020001, // WORD Format Tag WORD nChannels
143  44100, // DWORD nSamplesPerSecond
144  2352 * 75, // DWORD nAvgBytesPerSec
145  0x00100004, // WORD nBlockAlign WORD nBitsPerSample
146  0x61746164, // 'data'
147  -44 // <CD Audio Raw Data> ADJUST2
148 };
149 
150 //
151 // XA Files begin with this RIFF header block to identify the data as
152 // raw CD-XA sectors. Data must be added in 2352-byte multiples.
153 //
154 // This header is added to all CD-XA files which are marked as having
155 // mode2form2 sectors.
156 //
157 // Fields marked 'ADJUST' need to be adjusted based on the size of the
158 // data: Add file size to the marked DWORDS.
159 //
160 // File Size of TRACK??.WAV = nSectors*2352 + sizeof(XAFileHeader)
161 //
162 // RIFF('CDXA' FMT(Owner, Attr, 'X', 'A', FileNum, 0) data ( <CDXA Raw Data> )
163 //
164 
166  0x46464952, // Chunk ID = 'RIFF'
167  -8, // Chunk Size = (file size - 8) ADJUST
168  0x41584443, // 'CDXA'
169  0x20746d66, // 'fmt '
170  16, // Chunk Size (of CDXA chunk) = 16
171  0, // DWORD Owner ID
172  0x41580000, // WORD Attributes
173  // BYTE Signature byte 1 'X'
174  // BYTE Signature byte 2 'A'
175  0, // BYTE File Number
176  0, // BYTE Reserved[7]
177  0x61746164, // 'data'
178  -44 // <CD-XA Raw Sectors> ADJUST
179 };
180 
181 #ifdef CDFS_TELEMETRY_DATA
182 
183 //
184 // Telemetry Data for reporting
185 //
186 
187 CDFS_TELEMETRY_DATA_CONTEXT CdTelemetryData;
188 
189 #endif // CDFS_TELEMETRY_DATA
190 
191 #ifdef ALLOC_PRAGMA
192 #pragma alloc_text(PAGE, CdFastIoCheckIfPossible)
193 #pragma alloc_text(PAGE, CdSerial32)
194 #pragma alloc_text(PAGE, CdSetThreadContext)
195 #endif
196 
213 NTSTATUS
214 NTAPI
215 CdFsdDispatch (
218  )
219 
220 /*++
221 
222 Routine Description:
223 
224  This is the driver entry to all of the Fsd dispatch points.
225 
226  Conceptually the Io routine will call this routine on all requests
227  to the file system. We case on the type of request and invoke the
228  correct handler for this type of request. There is an exception filter
229  to catch any exceptions in the CDFS code as well as the CDFS process
230  exception routine.
231 
232  This routine allocates and initializes the IrpContext for this request as
233  well as updating the top-level thread context as necessary. We may loop
234  in this routine if we need to retry the request for any reason. The
235  status code STATUS_CANT_WAIT is used to indicate this. Suppose the disk
236  in the drive has changed. An Fsd request will proceed normally until it
237  recognizes this condition. STATUS_VERIFY_REQUIRED is raised at that point
238  and the exception code will handle the verify and either return
239  STATUS_CANT_WAIT or STATUS_PENDING depending on whether the request was
240  posted.
241 
242 Arguments:
243 
244  DeviceObject - Supplies the volume device object for this request
245 
246  Irp - Supplies the Irp being processed
247 
248 Return Value:
249 
250  NTSTATUS - The FSD status for the IRP
251 
252 --*/
253 
254 {
255  THREAD_CONTEXT ThreadContext = {0};
256  PIRP_CONTEXT IrpContext = NULL;
257  BOOLEAN Wait;
258 
259 #ifdef CD_SANITY
260  PVOID PreviousTopLevel;
261 #endif
262 
264 
265 #if DBG
266 
267  KIRQL SaveIrql = KeGetCurrentIrql();
268 
269 #endif
270 
272 
274 
276 
277 #ifdef CD_SANITY
278  PreviousTopLevel = IoGetTopLevelIrp();
279 #endif
280 
281  //
282  // Loop until this request has been completed or posted.
283  //
284 
285  do {
286 
287  //
288  // Use a try-except to handle the exception cases.
289  //
290 
291  _SEH2_TRY {
292 
293  //
294  // If the IrpContext is NULL then this is the first pass through
295  // this loop.
296  //
297 
298  if (IrpContext == NULL) {
299 
300  //
301  // Decide if this request is waitable an allocate the IrpContext.
302  // If the file object in the stack location is NULL then this
303  // is a mount which is always waitable. Otherwise we look at
304  // the file object flags.
305  //
306 
308 
309  Wait = TRUE;
310 
311  } else {
312 
313  Wait = CanFsdWait( Irp );
314  }
315 
316  IrpContext = CdCreateIrpContext( Irp, Wait );
317 
318  //
319  // Update the thread context information.
320  //
321 
322  CdSetThreadContext( IrpContext, &ThreadContext );
323 
324 #ifdef CD_SANITY
325  NT_ASSERT( !CdTestTopLevel ||
326  SafeNodeType( IrpContext->TopLevel ) == CDFS_NTC_IRP_CONTEXT );
327 #endif
328 
329  //
330  // Otherwise cleanup the IrpContext for the retry.
331  //
332 
333  } else {
334 
335  //
336  // Set the MORE_PROCESSING flag to make sure the IrpContext
337  // isn't inadvertently deleted here. Then cleanup the
338  // IrpContext to perform the retry.
339  //
340 
341  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
342  CdCleanupIrpContext( IrpContext, FALSE );
343  }
344 
345  //
346  // Case on the major irp code.
347  //
348 
349  switch (IrpContext->MajorFunction) {
350 
351  case IRP_MJ_CREATE :
352 
353  Status = CdCommonCreate( IrpContext, Irp );
354  break;
355 
356  case IRP_MJ_CLOSE :
357 
358  Status = CdCommonClose( IrpContext, Irp );
359  break;
360 
361  case IRP_MJ_READ :
362 
363  //
364  // If this is an Mdl complete request, don't go through
365  // common read.
366  //
367 
368  if (FlagOn( IrpContext->MinorFunction, IRP_MN_COMPLETE )) {
369 
370  Status = CdCompleteMdl( IrpContext, Irp );
371 
372  } else {
373 
374  Status = CdCommonRead( IrpContext, Irp );
375  }
376 
377  break;
378 
379  case IRP_MJ_WRITE :
380 
381  Status = CdCommonWrite( IrpContext, Irp );
382  break;
383 
385 
386  Status = CdCommonQueryInfo( IrpContext, Irp );
387  break;
388 
390 
391  Status = CdCommonSetInfo( IrpContext, Irp );
392  break;
393 
395 
396  Status = CdCommonQueryVolInfo( IrpContext, Irp );
397  break;
398 
400 
401  Status = CdCommonDirControl( IrpContext, Irp );
402  break;
403 
405 
406  Status = CdCommonFsControl( IrpContext, Irp );
407  break;
408 
409  case IRP_MJ_DEVICE_CONTROL :
410 
411  Status = CdCommonDevControl( IrpContext, Irp );
412  break;
413 
414  case IRP_MJ_LOCK_CONTROL :
415 
416  Status = CdCommonLockControl( IrpContext, Irp );
417  break;
418 
419  case IRP_MJ_CLEANUP :
420 
421  Status = CdCommonCleanup( IrpContext, Irp );
422  break;
423 
424  case IRP_MJ_PNP :
425 
426  Status = CdCommonPnp( IrpContext, Irp );
427  break;
428 
429  case IRP_MJ_SHUTDOWN :
430 
431  Status = CdCommonShutdown( IrpContext, Irp );
432  break;
433 
434  default :
435 
437  CdCompleteRequest( IrpContext, Irp, Status );
438  }
439 
441 
442  Status = CdProcessException( IrpContext, Irp, _SEH2_GetExceptionCode() );
443  } _SEH2_END;
444 
445  } while (Status == STATUS_CANT_WAIT);
446 
447 #ifdef CD_SANITY
448  NT_ASSERT( !CdTestTopLevel ||
449  (PreviousTopLevel == IoGetTopLevelIrp()) );
450 #endif
451 
453 
454  NT_ASSERT( SaveIrql == KeGetCurrentIrql( ));
455 
456  return Status;
457 }
458 
459 
460 #ifdef CD_SANITY
461 
462 VOID
464  _In_ PIRP_CONTEXT IrpContext,
466  _In_ BOOLEAN NormalizeStatus,
467  _In_opt_ ULONG FileId,
469  )
470 {
471  BOOLEAN BreakIn = FALSE;
472 
473  AssertVerifyDevice( IrpContext, Status);
474 
475  if (CdTraceRaises) {
476 
477  DbgPrint( "%p CdRaiseStatusEx 0x%x @ fid %d, line %d\n", PsGetCurrentThread(), Status, FileId, Line);
478  }
479 
480  if (CdTestRaisedStatus && !CdBreakOnAnyRaise) {
481 
482  ULONG Index;
483 
484  for (Index = 0;
485  Index < (sizeof( CdInterestingExceptionCodes) / sizeof( CdInterestingExceptionCodes[0]));
486  Index++) {
487 
488  if ((STATUS_SUCCESS != CdInterestingExceptionCodes[Index]) &&
489  (CdInterestingExceptionCodes[Index] == Status)) {
490 
491  BreakIn = TRUE;
492  break;
493  }
494  }
495  }
496 
497  if (BreakIn || CdBreakOnAnyRaise) {
498 
499  DbgPrint( "CDFS: Breaking on raised status %08x (BI=%d,BA=%d)\n", Status, BreakIn, CdBreakOnAnyRaise);
500  DbgPrint( "CDFS: (FILEID %d LINE %d)\n", FileId, Line);
501  DbgPrint( "CDFS: Contact CDFS.SYS component owner for triage.\n");
502  DbgPrint( "CDFS: 'eb %p 0;eb %p 0' to disable this alert.\n", &CdTestRaisedStatus, &CdBreakOnAnyRaise);
503 
504  NT_ASSERT(FALSE);
505  }
506 
507  if (NormalizeStatus) {
508 
509  IrpContext->ExceptionStatus = FsRtlNormalizeNtstatus( Status, STATUS_UNEXPECTED_IO_ERROR);
510  }
511  else {
512 
513  IrpContext->ExceptionStatus = Status;
514  }
515 
516  IrpContext->RaisedAtLineFile = (FileId << 16) | Line;
517 
518  ExRaiseStatus( IrpContext->ExceptionStatus);
519 }
520 
521 #endif
522 
523 
524 LONG
526  _Inout_ PIRP_CONTEXT IrpContext,
527  _In_ PEXCEPTION_POINTERS ExceptionPointer
528  )
529 
530 /*++
531 
532 Routine Description:
533 
534  This routine is used to decide whether we will handle a raised exception
535  status. If CDFS explicitly raised an error then this status is already
536  in the IrpContext. We choose which is the correct status code and
537  either indicate that we will handle the exception or bug-check the system.
538 
539 Arguments:
540 
541  ExceptionCode - Supplies the exception code to being checked.
542 
543 Return Value:
544 
545  ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks
546 
547 --*/
548 
549 {
552 
553  ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
554 
555  ExceptionCode = ExceptionPointer->ExceptionRecord->ExceptionCode;
556 
557  //
558  // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code
559  // from the exception record.
560  //
561 
563  (ExceptionPointer->ExceptionRecord->NumberParameters >= 3)) {
564 
565  ExceptionCode =
566  (NTSTATUS)ExceptionPointer->ExceptionRecord->ExceptionInformation[2];
567  }
568 
569  //
570  // If there is an Irp context then check which status code to use.
571  //
572 
573  if (ARGUMENT_PRESENT( IrpContext )) {
574 
575  if (IrpContext->ExceptionStatus == STATUS_SUCCESS) {
576 
577  //
578  // Store the real status into the IrpContext.
579  //
580 
581  IrpContext->ExceptionStatus = ExceptionCode;
582 
583  } else {
584 
585  //
586  // No need to test the status code if we raised it ourselves.
587  //
588 
589  TestStatus = FALSE;
590  }
591  }
592 
593  AssertVerifyDevice( IrpContext, IrpContext->ExceptionStatus );
594 
595  //
596  // Bug check if this status is not supported.
597  //
598 
600 
601 #ifdef _MSC_VER
602 #pragma prefast( suppress: __WARNING_USE_OTHER_FUNCTION, "We're corrupted." )
603 #endif
604  CdBugCheck( (ULONG_PTR) ExceptionPointer->ExceptionRecord,
605  (ULONG_PTR) ExceptionPointer->ContextRecord,
606  (ULONG_PTR) ExceptionPointer->ExceptionRecord->ExceptionAddress );
607 
608  }
609 
611 }
612 
613 
614 
615 _Requires_lock_held_(_Global_critical_region_)
616 NTSTATUS
617 CdProcessException (
618  _In_opt_ PIRP_CONTEXT IrpContext,
619  _Inout_ PIRP Irp,
621  )
622 
623 /*++
624 
625 Routine Description:
626 
627  This routine processes an exception. It either completes the request
628  with the exception status in the IrpContext, sends this off to the Fsp
629  workque or causes it to be retried in the current thread if a verification
630  is needed.
631 
632  If the volume needs to be verified (STATUS_VERIFY_REQUIRED) and we can
633  do the work in the current thread we will translate the status code
634  to STATUS_CANT_WAIT to indicate that we need to retry the request.
635 
636 Arguments:
637 
638  Irp - Supplies the Irp being processed
639 
640  ExceptionCode - Supplies the normalized exception status being handled
641 
642 Return Value:
643 
644  NTSTATUS - Returns the results of either posting the Irp or the
645  saved completion status.
646 
647 --*/
648 
649 {
651  PVPB Vpb;
653 
654  ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
655  ASSERT_IRP( Irp );
656 
657  //
658  // If there is not an irp context, then complete the request with the
659  // current status code.
660  //
661 
662  if (!ARGUMENT_PRESENT( IrpContext )) {
663 
665  return ExceptionCode;
666  }
667 
668  //
669  // Get the real exception status from the IrpContext.
670  //
671 
672  ExceptionCode = IrpContext->ExceptionStatus;
673 
674  //
675  // Check if we are posting this request. One of the following must be true
676  // if we are to post a request.
677  //
678  // - Status code is STATUS_CANT_WAIT and the request is asynchronous
679  // or we are forcing this to be posted.
680  //
681  // - Status code is STATUS_VERIFY_REQUIRED and we are at APC level
682  // or higher, or within a guarded region. Can't wait for IO in
683  // the verify path in this case.
684  //
685  // Set the MORE_PROCESSING flag in the IrpContext to keep if from being
686  // deleted if this is a retryable condition.
687  //
688  //
689  // Note that (children of) CdFsdPostRequest can raise (Mdl allocation).
690  //
691 
692  _SEH2_TRY {
693 
695 
696  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_FORCE_POST )) {
697 
698  ExceptionCode = CdFsdPostRequest( IrpContext, Irp );
699  }
700  }
701  else if ((ExceptionCode == STATUS_VERIFY_REQUIRED) &&
702  FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ) &&
704 
705  ExceptionCode = CdFsdPostRequest( IrpContext, Irp );
706  }
707  }
709 
711  } _SEH2_END;
712  //
713  // If we posted the request or our caller will retry then just return here.
714  //
715 
716  if ((ExceptionCode == STATUS_PENDING) ||
718 
719  return ExceptionCode;
720  }
721 
722  ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_MORE_PROCESSING );
723 
724  //
725  // If we are not a top level request then we just complete the request
726  // with the current status code.
727  //
728 
729  if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL )) {
730 
731  CdCompleteRequest( IrpContext, Irp, ExceptionCode );
732  return ExceptionCode;
733  }
734 
735  //
736  // Store this error into the Irp for posting back to the Io system.
737  //
738 
739  Irp->IoStatus.Status = ExceptionCode;
740 
742 
743  //
744  // Check for the various error conditions that can be caused by,
745  // and possibly resolved my the user.
746  //
747 
749 
750  //
751  // Now we are at the top level file system entry point.
752  //
753  // If we have already posted this request then the device to
754  // verify is in the original thread. Find this via the Irp.
755  //
756 
757  Device = IoGetDeviceToVerify( Irp->Tail.Overlay.Thread );
758  IoSetDeviceToVerify( Irp->Tail.Overlay.Thread, NULL );
759 
760  //
761  // If there is no device in that location then check in the
762  // current thread.
763  //
764 
765  if (Device == NULL) {
766 
769 
770  NT_ASSERT( Device != NULL );
771 
772  }
773 
774  //
775  // It turns out some storage drivers really do set invalid non-NULL device
776  // objects to verify.
777  //
778  // To work around this, completely ignore the device to verify in the thread,
779  // and just use our real device object instead.
780  //
781 
782  if (IrpContext->Vcb) {
783 
784  Device = IrpContext->Vcb->Vpb->RealDevice;
785  }
786 
787  //
788  // Let's not BugCheck just because the device to verify is somehow still NULL.
789  //
790 
791  if (Device == NULL) {
792 
794 
795  CdCompleteRequest( IrpContext, Irp, ExceptionCode );
796 
797  return ExceptionCode;
798  }
799 
800  //
801  // CdPerformVerify() will do the right thing with the Irp.
802  // If we return STATUS_CANT_WAIT then the current thread
803  // can retry the request.
804  //
805 
806  return CdPerformVerify( IrpContext, Irp, Device );
807  }
808 
809  //
810  // The other user induced conditions generate an error unless
811  // they have been disabled for this request.
812  //
813 
814  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_DISABLE_POPUPS )) {
815 
816  CdCompleteRequest( IrpContext, Irp, ExceptionCode );
817 
818  return ExceptionCode;
819 
820  }
821  //
822  // Generate a pop-up.
823  //
824  else {
825 
827 
829 
830  } else {
831 
832  Vpb = NULL;
833  }
834 
835 
836  //
837  // The device to verify is either in my thread local storage
838  // or that of the thread that owns the Irp.
839  //
840 
841  Thread = Irp->Tail.Overlay.Thread;
843 
844  if (Device == NULL) {
845 
848 
849  NT_ASSERT( Device != NULL );
850  }
851 
852  //
853  // It turns out some storage drivers really do set invalid non-NULL device
854  // objects to verify.
855  //
856  // To work around this, completely ignore the device to verify in the thread,
857  // and just use our real device object instead.
858  //
859 
860  if (IrpContext->Vcb) {
861 
862  Device = IrpContext->Vcb->Vpb->RealDevice;
863  }
864 
865  //
866  // Let's not BugCheck just because the device to verify is somehow still NULL.
867  //
868 
869  if (Device == NULL) {
870 
871  CdCompleteRequest( IrpContext, Irp, ExceptionCode );
872 
873  return ExceptionCode;
874  }
875 
876  //
877  // This routine actually causes the pop-up. It usually
878  // does this by queuing an APC to the callers thread,
879  // but in some cases it will complete the request immediately,
880  // so it is very important to IoMarkIrpPending() first.
881  //
882 
885 
886  //
887  // We will be handing control back to the caller here, so
888  // reset the saved device object.
889  //
890 
892 
893  //
894  // The Irp will be completed by Io or resubmitted. In either
895  // case we must clean up the IrpContext here.
896  //
897 
898  CdCompleteRequest( IrpContext, NULL, STATUS_SUCCESS );
899  return STATUS_PENDING;
900  }
901  }
902 
903  //
904  // This is just a run of the mill error.
905  //
906 
907  CdCompleteRequest( IrpContext, Irp, ExceptionCode );
908 
909  return ExceptionCode;
910 }
911 
912 
913 VOID
915  _Inout_opt_ PIRP_CONTEXT IrpContext,
918  )
919 
920 /*++
921 
922 Routine Description:
923 
924  This routine completes a Irp and cleans up the IrpContext. Either or
925  both of these may not be specified.
926 
927 Arguments:
928 
929  Irp - Supplies the Irp being processed.
930 
931  Status - Supplies the status to complete the Irp with
932 
933 Return Value:
934 
935  None.
936 
937 --*/
938 
939 {
940  ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext );
942 
943  //
944  // Cleanup the IrpContext if passed in here.
945  //
946 
947  if (ARGUMENT_PRESENT( IrpContext )) {
948 
949  CdCleanupIrpContext( IrpContext, FALSE );
950  }
951 
952  //
953  // If we have an Irp then complete the irp.
954  //
955 
956  if (ARGUMENT_PRESENT( Irp )) {
957 
958  //
959  // Clear the information field in case we have used this Irp
960  // internally.
961  //
962 
963  if (NT_ERROR( Status ) &&
964  FlagOn( Irp->Flags, IRP_INPUT_OPERATION )) {
965 
966  Irp->IoStatus.Information = 0;
967  }
968 
969  Irp->IoStatus.Status = Status;
970 
972 
974  }
975 
976  return;
977 }
978 
979 
980 VOID
982  _Inout_ PIRP_CONTEXT IrpContext,
983  _In_ PTHREAD_CONTEXT ThreadContext
984  )
985 
986 /*++
987 
988 Routine Description:
989 
990  This routine is called at each Fsd/Fsp entry point set up the IrpContext
991  and thread local storage to track top level requests. If there is
992  not a Cdfs context in the thread local storage then we use the input one.
993  Otherwise we use the one already there. This routine also updates the
994  IrpContext based on the state of the top-level context.
995 
996  If the TOP_LEVEL flag in the IrpContext is already set when we are called
997  then we force this request to appear top level.
998 
999 Arguments:
1000 
1001  ThreadContext - Address on stack for local storage if not already present.
1002 
1003  ForceTopLevel - We force this request to appear top level regardless of
1004  any previous stack value.
1005 
1006 Return Value:
1007 
1008  None
1009 
1010 --*/
1011 
1012 {
1013  PTHREAD_CONTEXT CurrentThreadContext;
1014 #ifdef __REACTOS__
1015  ULONG_PTR StackTop;
1016  ULONG_PTR StackBottom;
1017 #endif
1018 
1019  PAGED_CODE();
1020 
1021  ASSERT_IRP_CONTEXT( IrpContext );
1022 
1023  //
1024  // Get the current top-level irp out of the thread storage.
1025  // If NULL then this is the top-level request.
1026  //
1027 
1028  CurrentThreadContext = (PTHREAD_CONTEXT) IoGetTopLevelIrp();
1029 
1030  if (CurrentThreadContext == NULL) {
1031 
1032  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL );
1033  }
1034 
1035  //
1036  // Initialize the input context unless we are using the current
1037  // thread context block. We use the new block if our caller
1038  // specified this or the existing block is invalid.
1039  //
1040  // The following must be true for the current to be a valid Cdfs context.
1041  //
1042  // Structure must lie within current stack.
1043  // Address must be ULONG aligned.
1044  // Cdfs signature must be present.
1045  //
1046  // If this is not a valid Cdfs context then use the input thread
1047  // context and store it in the top level context.
1048  //
1049 
1050 #ifdef __REACTOS__
1051  IoGetStackLimits( &StackTop, &StackBottom);
1052 #endif
1053 
1054 #ifdef _MSC_VER
1055 #pragma warning(suppress: 6011) // Bug in PREFast around bitflag operations
1056 #endif
1057  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL ) ||
1058 #ifndef __REACTOS__
1059  (!IoWithinStackLimits( (ULONG_PTR)CurrentThreadContext, sizeof( THREAD_CONTEXT ) ) ||
1060 #else
1061  (((ULONG_PTR) CurrentThreadContext > StackBottom - sizeof( THREAD_CONTEXT )) ||
1062  ((ULONG_PTR) CurrentThreadContext <= StackTop) ||
1063 #endif
1064  FlagOn( (ULONG_PTR) CurrentThreadContext, 0x3 ) ||
1065  (CurrentThreadContext->Cdfs != 0x53464443))) {
1066 
1067  ThreadContext->Cdfs = 0x53464443;
1068  ThreadContext->SavedTopLevelIrp = (PIRP) CurrentThreadContext;
1069  ThreadContext->TopLevelIrpContext = IrpContext;
1070  IoSetTopLevelIrp( (PIRP) ThreadContext );
1071 
1072  IrpContext->TopLevel = IrpContext;
1073  IrpContext->ThreadContext = ThreadContext;
1074 
1075  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS );
1076 
1077  //
1078  // Otherwise use the IrpContext in the thread context.
1079  //
1080 
1081  } else {
1082 
1083  IrpContext->TopLevel = CurrentThreadContext->TopLevelIrpContext;
1084  }
1085 
1086  return;
1087 }
1088 
1089 
1090 _Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
1092 _Success_(return != FALSE)
1093 BOOLEAN
1094 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1098  _In_ ULONG Length,
1099  _In_ BOOLEAN Wait,
1100  _In_ ULONG LockKey,
1103  _When_(return != FALSE, _Post_equal_to_(_Old_(IoStatus)))
1104  _When_(return == FALSE, _Post_valid_)
1107  )
1108 
1109 /*++
1110 
1111 Routine Description:
1112 
1113  This routine checks if fast i/o is possible for a read/write operation
1114 
1115 Arguments:
1116 
1117  FileObject - Supplies the file object used in the query
1118 
1119  FileOffset - Supplies the starting byte offset for the read/write operation
1120 
1121  Length - Supplies the length, in bytes, of the read/write operation
1122 
1123  Wait - Indicates if we can wait
1124 
1125  LockKey - Supplies the lock key
1126 
1127  CheckForReadOperation - Indicates if this is a check for a read or write
1128  operation
1129 
1130  IoStatus - Receives the status of the operation if our return value is
1131  FastIoReturnError
1132 
1133 Return Value:
1134 
1135  BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
1136  to take the long route.
1137 
1138 --*/
1139 
1140 {
1141  PFCB Fcb;
1143  LARGE_INTEGER LargeLength;
1144 
1145  PAGED_CODE();
1146 
1149 
1150  //
1151  // Decode the type of file object we're being asked to process and
1152  // make sure that is is only a user file open.
1153  //
1154 
1156 
1158 
1160  return TRUE;
1161  }
1162 
1163  LargeLength.QuadPart = Length;
1164 
1165  //
1166  // Check whether the file locks will allow for fast io.
1167  //
1168 
1169  if ((Fcb->FileLock == NULL) ||
1171  FileOffset,
1172  &LargeLength,
1173  LockKey,
1174  FileObject,
1175  PsGetCurrentProcess() )) {
1176 
1177  return TRUE;
1178  }
1179 
1180  return FALSE;
1181 }
1182 
1183 
1184 ULONG
1188  )
1189 /*++
1190 
1191 Routine Description:
1192 
1193  This routine is called to generate a 32 bit serial number. This is
1194  done by doing four separate checksums into an array of bytes and
1195  then treating the bytes as a ULONG.
1196 
1197 Arguments:
1198 
1199  Buffer - Pointer to the buffer to generate the ID for.
1200 
1201  ByteCount - Number of bytes in the buffer.
1202 
1203 Return Value:
1204 
1205  ULONG - The 32 bit serial number.
1206 
1207 --*/
1208 
1209 {
1210  union {
1211  UCHAR Bytes[4];
1212  ULONG SerialId;
1213  } Checksum;
1214 
1215  PAGED_CODE();
1216 
1217  //
1218  // Initialize the serial number.
1219  //
1220 
1221  Checksum.SerialId = 0;
1222 
1223  //
1224  // Continue while there are more bytes to use.
1225  //
1226 
1227  while (ByteCount--) {
1228 
1229  //
1230  // Increment this sub-checksum.
1231  //
1232 
1233  Checksum.Bytes[ByteCount & 0x3] += *(Buffer++);
1234  }
1235 
1236  //
1237  // Return the checksums as a ULONG.
1238  //
1239 
1240  return Checksum.SerialId;
1241 }
1242 
1243 
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
signed char * PCHAR
Definition: retypes.h:7
FILE_LOCK FileLock
Definition: fatstruc.h:1067
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1782
#define _IRQL_requires_same_
Definition: no_sal2.h:652
VOID CdSetThreadContext(_Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext)
Definition: cddata.c:981
#define AssertVerifyDeviceIrp(I)
Definition: cdprocs.h:1821
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define TRUE
Definition: types.h:120
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
BOOLEAN NTAPI FsRtlFastCheckLockForRead(IN PFILE_LOCK FileLock, IN PLARGE_INTEGER FileOffset, IN PLARGE_INTEGER Length, IN ULONG Key, IN PFILE_OBJECT FileObject, IN PVOID Process)
Definition: filelock.c:752
#define FsRtlEnterFileSystem
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2020
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define FsRtlExitFileSystem
#define DbgPrint
Definition: loader.c:25
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN OUT PIO_STATUS_BLOCK IoStatus
Definition: fatprocs.h:2650
#define IRP_CONTEXT_FLAG_FORCE_POST
Definition: cdstruc.h:1222
#define IRP_MJ_SHUTDOWN
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1220
WCHAR CdUnicodeParentArray[]
Definition: cddata.c:50
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
char CHAR
Definition: xmlstorage.h:175
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
LONG CdAudioPlayHeader[]
Definition: cddata.c:102
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2769
LONG NTSTATUS
Definition: precomp.h:26
FAST_IO_CHECK_IF_POSSIBLE CdFastIoCheckIfPossible
Definition: cdprocs.h:1961
LONG CdXAAudioPhileHeader[]
Definition: cddata.c:136
_In_ UINT Bytes
Definition: mmcopy.h:9
#define ExRaiseStatus
Definition: ntoskrnl.h:95
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
LOGICAL NTAPI IoWithinStackLimits(_In_ ULONG_PTR RegionStart, _In_ SIZE_T RegionSize)
CHAR CdIsoId[]
Definition: cddata.c:62
#define IRP_CONTEXT_FLAG_DISABLE_POPUPS
Definition: cdstruc.h:1228
PDEVICE_OBJECT NTAPI IoGetDeviceToVerify(IN PETHREAD Thread)
Definition: util.c:328
ULONG CdAudioDirentSize
Definition: cddata.c:78
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN CheckForReadOperation
Definition: fatprocs.h:2650
#define PAGED_CODE()
Definition: video.h:57
#define _In_opt_
Definition: no_sal2.h:213
#define CdBugCheck(A, B, C)
Definition: nodetype.h:103
_SEH2_TRY
Definition: create.c:4250
uint32_t ULONG_PTR
Definition: typedefs.h:63
#define IRP_MN_COMPLETE
Definition: iotypes.h:4063
UCHAR KIRQL
Definition: env_spec_w32.h:591
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:593
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
TYPE_OF_OPEN CdFastDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Out_ PFCB *Fcb)
Definition: filobsup.c:206
_IRQL_requires_max_(APC_LEVEL)
Definition: cddata.c:197
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:249
#define SECTOR_SIZE
Definition: winldr.h:34
long LONG
Definition: pedump.c:60
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
ULONG CdAudioSystemUseOffset
Definition: cddata.c:80
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
#define IoCompleteRequest
Definition: irp.c:1240
Definition: bufpool.h:45
#define IRP_MJ_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
WCHAR CdUnicodeSelfArray[]
Definition: cddata.c:49
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
TestStatus
Definition: global_mem.c:32
CHAR CdAudioFileName[]
Definition: cddata.c:76
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG LockKey
Definition: fatprocs.h:2650
PCHAR CdJolietEscape[]
Definition: cddata.c:86
#define ASSERT_OPTIONAL_IRP_CONTEXT(IC)
Definition: cddata.h:250
CD_DATA CdData
Definition: cddata.c:42
THREAD_CONTEXT * PTHREAD_CONTEXT
Definition: cdstruc.h:1392
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define STATUS_PENDING
Definition: ntstatus.h:82
ULONG CdAudioDirentsPerSector
Definition: cddata.c:79
_Requires_lock_held_(_Global_critical_region_)
Definition: cddata.c:615
#define ARGUMENT_PRESENT(ArgumentPointer)
#define IRP_MJ_FILE_SYSTEM_CONTROL
#define _Success_(expr)
Definition: no_sal2.h:635
static const UCHAR Index[8]
Definition: usbohci.c:18
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define _Inout_
Definition: no_sal2.h:244
#define NT_ERROR(Status)
Definition: umtypes.h:106
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
* PFILE_OBJECT
Definition: iotypes.h:1954
#define CanFsdWait(I)
Definition: cdprocs.h:2011
#define __drv_dispatchType(x)
Definition: driverspecs.h:249
NTSTATUS CdCompleteMdl(_In_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: cachesup.c:411
Definition: ncftp.h:79
#define STATUS_DRIVER_INTERNAL_ERROR
Definition: udferr_usr.h:177
#define AssertVerifyDevice(C, S)
Definition: cdprocs.h:1820
unsigned char UCHAR
Definition: xmlstorage.h:181
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
static const WCHAR L[]
Definition: oid.c:1250
#define NTSTATUS
Definition: precomp.h:20
#define _Post_valid_
Definition: no_sal2.h:466
NTSTATUS CdCommonDevControl(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: devctrl.c:46
enum _TYPE_OF_OPEN TYPE_OF_OPEN
UNICODE_STRING CdUnicodeDirectoryNames[]
Definition: cddata.c:52
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
USHORT CdAudioLabelLength
Definition: cddata.c:70
UCHAR CdAudioFileNameLength
Definition: cddata.c:77
#define _Pre_notnull_
Definition: no_sal2.h:496
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1060
Status
Definition: gdiplustypes.h:24
#define ASSERT_IRP(I)
Definition: cddata.h:251
#define _In_
Definition: no_sal2.h:204
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
PFILE_OBJECT FileObject
Definition: iotypes.h:2812
_Function_class_(FAST_IO_CHECK_IF_POSSIBLE)
Definition: cddata.c:1090
#define IO_CD_ROM_INCREMENT
Definition: iotypes.h:566
_SEH2_END
Definition: create.c:4424
FAST_IO_DISPATCH CdFastIoDispatch
Definition: cddata.c:43
CHAR CdHsgId[]
Definition: cddata.c:61
#define IRP_INPUT_OPERATION
unsigned short USHORT
Definition: pedump.c:61
LONG CdExceptionFilter(_Inout_ PIRP_CONTEXT IrpContext, _In_ PEXCEPTION_POINTERS ExceptionPointer)
Definition: cddata.c:525
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:151
#define IRP_CONTEXT_FLAG_TOP_LEVEL
Definition: cdstruc.h:1223
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
#define ASSERT_OPTIONAL_IRP(I)
Definition: cddata.h:252
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
VOID NTAPI IoGetStackLimits(OUT PULONG_PTR LowLimit, OUT PULONG_PTR HighLimit)
Definition: util.c:78
#define _When_(expr, annos)
Definition: no_sal2.h:639
ULONG CdSerial32(_In_reads_bytes_(ByteCount) PCHAR Buffer, _In_ ULONG ByteCount)
Definition: cddata.c:1185
NTSTATUS CdCommonLockControl(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: lockctrl.c:35
#define CDFS_NTC_IRP_CONTEXT
Definition: nodetype.h:34
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:455
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define _Post_equal_to_(expr)
Definition: no_sal2.h:456
#define IRP_MJ_CLEANUP
WCHAR CdAudioLabel[]
Definition: cddata.c:69
Definition: iotypes.h:166
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
unsigned int ULONG
Definition: retypes.h:1
INLINE DECLSPEC_NORETURN VOID CdRaiseStatusEx(_In_ PIRP_CONTEXT IrpContext, _In_ NTSTATUS Status, _In_ BOOLEAN NormalizeStatus, _In_ ULONG Fileid, _In_ ULONG Line)
Definition: cdprocs.h:1845
LONG CdXAFileHeader[]
Definition: cddata.c:165
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
VOID NTAPI IoRaiseHardError(IN PIRP Irp, IN PVPB Vpb, IN PDEVICE_OBJECT RealDeviceObject)
Definition: error.c:656
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:229
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
NTSTATUS NTAPI FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize, IN NTSTATUS NormalizedNtStatus)
Definition: filter.c:90
_Ret_valid_ PIRP_CONTEXT CdCreateIrpContext(_In_ PIRP Irp, _In_ BOOLEAN Wait)
Definition: strucsup.c:1573
_In_ PFCB Fcb
Definition: cdprocs.h:151
return STATUS_SUCCESS
Definition: btrfs.c:2725
IoMarkIrpPending(Irp)
#define APC_LEVEL
Definition: env_spec_w32.h:695
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1664
VOID NTAPI IoSetDeviceToVerify(IN PETHREAD Thread, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:304
LONGLONG QuadPart
Definition: typedefs.h:112
CHAR CdXaId[]
Definition: cddata.c:63
#define _Inout_opt_
Definition: no_sal2.h:258
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
IN BOOLEAN Wait
Definition: fatprocs.h:1529
#define NT_ASSERT
Definition: rtlfuncs.h:3312