ReactOS 0.4.16-dev-125-g798ea90
cddata.c
Go to the documentation of this file.
1
2/*++
3
4Copyright (c) 1989-2000 Microsoft Corporation
5
6Module Name:
7
8 CdData.c
9
10Abstract:
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
23BOOLEAN CdTestTopLevel = TRUE;
24BOOLEAN CdTestRaisedStatus = TRUE;
25BOOLEAN CdBreakOnAnyRaise = FALSE;
26BOOLEAN CdTraceRaises = FALSE;
27NTSTATUS 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)
38//
39// Global data structures
40//
41
44
45//
46// Reserved directory strings.
47//
48
51
53 { 2, 2, CdUnicodeSelfArray},
55};
56
57//
58// Volume descriptor identifier strings.
59//
60
61CHAR CdHsgId[] = { 'C', 'D', 'R', 'O', 'M' };
62CHAR CdIsoId[] = { 'C', 'D', '0', '0', '1' };
63CHAR CdXaId[] = { 'C', 'D', '-', 'X', 'A', '0', '0', '1' };
64
65//
66// Volume label for audio disks.
67//
68
69WCHAR 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
76CHAR CdAudioFileName[] = { 'T', 'r', 'a', 'c', 'k', '0', '0', '.', 'c', 'd', 'a' };
81
82//
83// Escape sequences for mounting Unicode volumes.
84//
85
86PCHAR 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
187CDFS_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
214NTAPI
215CdFsdDispatch (
218 )
219
220/*++
221
222Routine 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
242Arguments:
243
244 DeviceObject - Supplies the volume device object for this request
245
246 Irp - Supplies the Irp being processed
247
248Return Value:
249
250 NTSTATUS - The FSD status for the IRP
251
252--*/
253
254{
255 THREAD_CONTEXT ThreadContext = {0};
256 PIRP_CONTEXT IrpContext = NULL;
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
410
411 Status = CdCommonDevControl( IrpContext, Irp );
412 break;
413
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
462VOID
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
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
524LONG
526 _Inout_ PIRP_CONTEXT IrpContext,
527 _In_ PEXCEPTION_POINTERS ExceptionPointer
528 )
529
530/*++
531
532Routine 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
539Arguments:
540
541 ExceptionCode - Supplies the exception code to being checked.
542
543Return 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
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
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_)
617CdProcessException (
618 _In_opt_ PIRP_CONTEXT IrpContext,
621 )
622
623/*++
624
625Routine 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
636Arguments:
637
638 Irp - Supplies the Irp being processed
639
640 ExceptionCode - Supplies the normalized exception status being handled
641
642Return 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 }
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
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
913VOID
915 _Inout_opt_ PIRP_CONTEXT IrpContext,
918 )
919
920/*++
921
922Routine Description:
923
924 This routine completes a Irp and cleans up the IrpContext. Either or
925 both of these may not be specified.
926
927Arguments:
928
929 Irp - Supplies the Irp being processed.
930
931 Status - Supplies the status to complete the Irp with
932
933Return 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
980VOID
982 _Inout_ PIRP_CONTEXT IrpContext,
983 _In_ PTHREAD_CONTEXT ThreadContext
984 )
985
986/*++
987
988Routine 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
999Arguments:
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
1006Return 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)
1093BOOLEAN
1094NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
1103 _When_(return != FALSE, _Post_equal_to_(_Old_(IoStatus)))
1104 _When_(return == FALSE, _Post_valid_)
1107 )
1108
1109/*++
1110
1111Routine Description:
1112
1113 This routine checks if fast i/o is possible for a read/write operation
1114
1115Arguments:
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
1133Return 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
1184ULONG
1188 )
1189/*++
1190
1191Routine 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
1197Arguments:
1198
1199 Buffer - Pointer to the buffer to generate the ID for.
1200
1201 ByteCount - Number of bytes in the buffer.
1202
1203Return 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
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
#define PAGED_CODE()
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
#define SECTOR_SIZE
Definition: fs.h:22
LONG CdAudioPlayHeader[]
Definition: cddata.c:102
LONG CdXAAudioPhileHeader[]
Definition: cddata.c:136
USHORT CdAudioLabelLength
Definition: cddata.c:70
WCHAR CdAudioLabel[]
Definition: cddata.c:69
UCHAR CdAudioFileNameLength
Definition: cddata.c:77
WCHAR CdUnicodeSelfArray[]
Definition: cddata.c:49
VOID CdCompleteRequest(_Inout_opt_ PIRP_CONTEXT IrpContext, _Inout_opt_ PIRP Irp, _In_ NTSTATUS Status)
Definition: cddata.c:914
WCHAR CdUnicodeParentArray[]
Definition: cddata.c:50
ULONG CdSerial32(_In_reads_bytes_(ByteCount) PCHAR Buffer, _In_ ULONG ByteCount)
Definition: cddata.c:1185
CHAR CdHsgId[]
Definition: cddata.c:61
LONG CdExceptionFilter(_Inout_ PIRP_CONTEXT IrpContext, _In_ PEXCEPTION_POINTERS ExceptionPointer)
Definition: cddata.c:525
CHAR CdAudioFileName[]
Definition: cddata.c:76
ULONG CdAudioDirentsPerSector
Definition: cddata.c:79
LONG CdXAFileHeader[]
Definition: cddata.c:165
ULONG CdAudioDirentSize
Definition: cddata.c:78
CHAR CdIsoId[]
Definition: cddata.c:62
CD_DATA CdData
Definition: cddata.c:42
PCHAR CdJolietEscape[]
Definition: cddata.c:86
VOID CdSetThreadContext(_Inout_ PIRP_CONTEXT IrpContext, _In_ PTHREAD_CONTEXT ThreadContext)
Definition: cddata.c:981
FAST_IO_DISPATCH CdFastIoDispatch
Definition: cddata.c:43
UNICODE_STRING CdUnicodeDirectoryNames[]
Definition: cddata.c:52
CHAR CdXaId[]
Definition: cddata.c:63
ULONG CdAudioSystemUseOffset
Definition: cddata.c:80
#define ASSERT_IRP(I)
Definition: cddata.h:250
#define ASSERT_OPTIONAL_IRP_CONTEXT(IC)
Definition: cddata.h:249
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:248
#define ASSERT_OPTIONAL_IRP(I)
Definition: cddata.h:251
NTSTATUS CdCompleteMdl(_In_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: cachesup.c:411
_In_ PFCB _In_ LONGLONG FileOffset
Definition: cdprocs.h:160
VOID CdCleanupIrpContext(_In_ PIRP_CONTEXT IrpContext, _In_ BOOLEAN Post)
Definition: strucsup.c:1733
#define CanFsdWait(I)
Definition: cdprocs.h:2001
_Inout_ PIRP _In_ NTSTATUS ExceptionCode
Definition: cdprocs.h:1774
_Inout_ PFILE_OBJECT _In_ TYPE_OF_OPEN TypeOfOpen
Definition: cdprocs.h:589
INLINE DECLSPEC_NORETURN VOID CdRaiseStatusEx(_In_ PIRP_CONTEXT IrpContext, _In_ NTSTATUS Status, _In_ BOOLEAN NormalizeStatus, _In_ ULONG Fileid, _In_ ULONG Line)
Definition: cdprocs.h:1835
FAST_IO_CHECK_IF_POSSIBLE CdFastIoCheckIfPossible
Definition: cdprocs.h:1951
#define AssertVerifyDevice(C, S)
Definition: cdprocs.h:1810
@ UserFileOpen
Definition: cdprocs.h:577
#define AssertVerifyDeviceIrp(I)
Definition: cdprocs.h:1811
TYPE_OF_OPEN CdFastDecodeFileObject(_In_ PFILE_OBJECT FileObject, _Out_ PFCB *Fcb)
Definition: filobsup.c:206
_In_ PFCB Fcb
Definition: cdprocs.h:159
NTSTATUS CdCommonLockControl(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: lockctrl.c:35
enum _TYPE_OF_OPEN TYPE_OF_OPEN
NTSTATUS CdCommonDevControl(_Inout_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp)
Definition: devctrl.c:46
_Ret_valid_ PIRP_CONTEXT CdCreateIrpContext(_In_ PIRP Irp, _In_ BOOLEAN Wait)
Definition: strucsup.c:1573
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
#define IRP_CONTEXT_FLAG_FORCE_POST
Definition: cdstruc.h:1216
THREAD_CONTEXT * PTHREAD_CONTEXT
Definition: cdstruc.h:1386
#define IRP_CONTEXT_FLAG_DISABLE_POPUPS
Definition: cdstruc.h:1222
#define IRP_CONTEXT_FLAG_TOP_LEVEL
Definition: cdstruc.h:1217
#define IRP_CONTEXT_FLAG_MORE_PROCESSING
Definition: cdstruc.h:1214
Definition: bufpool.h:45
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NTSTATUS
Definition: precomp.h:21
#define CdBugCheck(A, B, C)
Definition: nodetype.h:103
#define CDFS_NTC_IRP_CONTEXT
Definition: nodetype.h:34
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
#define _IRQL_requires_same_
Definition: driverspecs.h:232
#define __drv_dispatchType(x)
Definition: driverspecs.h:267
#define _IRQL_requires_max_(irql)
Definition: driverspecs.h:230
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define APC_LEVEL
Definition: env_spec_w32.h:695
#define KeGetCurrentIrql()
Definition: env_spec_w32.h:706
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG LockKey
Definition: fatprocs.h:2666
IN OUT PVCB IN PDEVICE_OBJECT IN PVPB Vpb
Definition: fatprocs.h:1676
IN PLARGE_INTEGER IN ULONG IN BOOLEAN IN ULONG IN BOOLEAN CheckForReadOperation
Definition: fatprocs.h:2667
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:748
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
_In_opt_ PFILE_OBJECT _In_opt_ PETHREAD Thread
Definition: fltkernel.h:2653
#define FsRtlEnterFileSystem
#define FsRtlExitFileSystem
Status
Definition: gdiplustypes.h:25
TestStatus
Definition: global_mem.c:33
#define DbgPrint
Definition: hal.h:12
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
IoMarkIrpPending(Irp)
_In_ UINT Bytes
Definition: mmcopy.h:9
#define _Function_class_(x)
Definition: ms_sal.h:2946
#define _Success_(expr)
Definition: ms_sal.h:259
#define _In_reads_bytes_(size)
Definition: ms_sal.h:321
#define _Inout_
Definition: ms_sal.h:378
#define _Post_equal_to_(expr)
Definition: ms_sal.h:578
#define _Pre_notnull_
Definition: ms_sal.h:680
#define _Post_valid_
Definition: ms_sal.h:694
#define _Inout_opt_
Definition: ms_sal.h:379
#define _When_(expr, annos)
Definition: ms_sal.h:254
#define _In_
Definition: ms_sal.h:308
#define _In_opt_
Definition: ms_sal.h:309
__in UCHAR __in POWER_STATE __in_opt PVOID __in PIO_STATUS_BLOCK IoStatus
Definition: mxum.h:159
DRIVER_DISPATCH(nfs41_FsdDispatch)
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define ARGUMENT_PRESENT(ArgumentPointer)
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
NTSTATUS NTAPI FsRtlNormalizeNtstatus(IN NTSTATUS NtStatusToNormalize, IN NTSTATUS NormalizedNtStatus)
Definition: filter.c:90
#define ExRaiseStatus
Definition: ntoskrnl.h:114
VOID NTAPI IoRaiseHardError(IN PIRP Irp, IN PVPB Vpb, IN PDEVICE_OBJECT RealDeviceObject)
Definition: error.c:664
#define IoCompleteRequest
Definition: irp.c:1240
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
VOID NTAPI IoSetDeviceToVerify(IN PETHREAD Thread, IN PDEVICE_OBJECT DeviceObject)
Definition: util.c:304
VOID NTAPI IoGetStackLimits(OUT PULONG_PTR LowLimit, OUT PULONG_PTR HighLimit)
Definition: util.c:78
PDEVICE_OBJECT NTAPI IoGetDeviceToVerify(IN PETHREAD Thread)
Definition: util.c:336
BOOLEAN NTAPI KeAreAllApcsDisabled(VOID)
Definition: apc.c:985
#define STATUS_CANT_WAIT
Definition: ntstatus.h:452
#define STATUS_PENDING
Definition: ntstatus.h:82
#define STATUS_IN_PAGE_ERROR
Definition: ntstatus.h:243
#define STATUS_UNEXPECTED_IO_ERROR
Definition: ntstatus.h:469
#define L(x)
Definition: ntvdm.h:50
long LONG
Definition: pedump.c:60
unsigned short USHORT
Definition: pedump.c:61
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:165
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:66
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:164
#define IRP_MJ_DIRECTORY_CONTROL
Definition: rdpdr.c:51
#define IRP_MJ_CLOSE
Definition: rdpdr.c:45
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define IRP_MJ_QUERY_VOLUME_INFORMATION
Definition: rdpdr.c:50
#define IRP_MJ_LOCK_CONTROL
Definition: rdpdr.c:53
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define IRP_MJ_SET_INFORMATION
Definition: rdpdr.c:49
#define IRP_MJ_CREATE
Definition: rdpdr.c:44
#define IRP_MJ_QUERY_INFORMATION
Definition: rdpdr.c:48
#define STATUS_SUCCESS
Definition: shellext.h:65
Definition: ncftp.h:79
Definition: cdstruc.h:902
FILE_LOCK FileLock
Definition: fatstruc.h:1071
PFILE_OBJECT FileObject
Definition: iotypes.h:3169
IO_STATUS_BLOCK IoStatus
Definition: iotypes.h:189
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
uint32_t ULONG_PTR
Definition: typedefs.h:65
uint32_t ULONG
Definition: typedefs.h:59
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
#define STATUS_DRIVER_INTERNAL_ERROR
Definition: udferr_usr.h:177
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define STATUS_DISK_CORRUPT_ERROR
Definition: udferr_usr.h:147
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define NT_ERROR(Status)
Definition: umtypes.h:106
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ WDFCOLLECTION _In_ ULONG Index
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ WDFREQUEST _In_ WDFFILEOBJECT FileObject
Definition: wdfdevice.h:550
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
#define IoIsErrorUserInduced(Status)
Definition: iofuncs.h:2817
LOGICAL NTAPI IoWithinStackLimits(_In_ ULONG_PTR RegionStart, _In_ SIZE_T RegionSize)
#define IRP_MN_COMPLETE
Definition: iotypes.h:4420
#define IRP_INPUT_OPERATION
#define IRP_MJ_FILE_SYSTEM_CONTROL
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define IO_CD_ROM_INCREMENT
Definition: iotypes.h:599
* PFILE_OBJECT
Definition: iotypes.h:1998
#define IRP_MJ_SHUTDOWN
#define IRP_MJ_CLEANUP
#define PsGetCurrentProcess
Definition: psfuncs.h:17
#define NT_ASSERT
Definition: rtlfuncs.h:3324
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175