4 Copyright (c) 1989-2000 Microsoft Corporation
12 This module declares the global data used by the Cdfs file system.
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.
23 BOOLEAN CdTestTopLevel
= TRUE
;
24 BOOLEAN CdTestRaisedStatus
= TRUE
;
25 BOOLEAN CdBreakOnAnyRaise
= FALSE
;
26 BOOLEAN CdTraceRaises
= FALSE
;
27 NTSTATUS CdInterestingExceptionCodes
[] = { STATUS_DISK_CORRUPT_ERROR
,
28 STATUS_FILE_CORRUPT_ERROR
,
29 0, 0, 0, 0, 0, 0, 0, 0 };
33 // The Bug check file id for this module
36 #define BugCheckFileId (CDFS_BUG_CHECK_CDDATA)
39 // Global data structures
43 FAST_IO_DISPATCH CdFastIoDispatch
;
46 // Reserved directory strings.
49 WCHAR CdUnicodeSelfArray
[] = { L
'.' };
50 WCHAR CdUnicodeParentArray
[] = { L
'.', L
'.' };
52 UNICODE_STRING CdUnicodeDirectoryNames
[] = {
53 { 2, 2, CdUnicodeSelfArray
},
54 { 4, 4, CdUnicodeParentArray
}
58 // Volume descriptor identifier strings.
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' };
66 // Volume label for audio disks.
69 WCHAR CdAudioLabel
[] = { L
'A', L
'u', L
'd', L
'i', L
'o', L
' ', L
'C', L
'D' };
70 USHORT CdAudioLabelLength
= sizeof( CdAudioLabel
);
73 // Pseudo file names for audio disks.
76 CHAR CdAudioFileName
[] = { 'T', 'r', 'a', 'c', 'k', '0', '0', '.', 'c', 'd', 'a' };
77 UCHAR CdAudioFileNameLength
= sizeof( CdAudioFileName
);
78 ULONG CdAudioDirentSize
= FIELD_OFFSET( RAW_DIRENT
, FileId
) + sizeof( CdAudioFileName
) + sizeof( SYSTEM_USE_XA
);
79 ULONG CdAudioDirentsPerSector
= SECTOR_SIZE
/ (FIELD_OFFSET( RAW_DIRENT
, FileId
) + sizeof( CdAudioFileName
) + sizeof( SYSTEM_USE_XA
));
80 ULONG CdAudioSystemUseOffset
= FIELD_OFFSET( RAW_DIRENT
, FileId
) + sizeof( CdAudioFileName
);
83 // Escape sequences for mounting Unicode volumes.
86 PCHAR CdJolietEscape
[] = { "%/@", "%/C", "%/E" };
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.
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.
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.
102 LONG CdAudioPlayHeader
[] = {
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)
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.
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.
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> )
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.
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.
136 LONG CdXAAudioPhileHeader
[] = {
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
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.
154 // This header is added to all CD-XA files which are marked as having
155 // mode2form2 sectors.
157 // Fields marked 'ADJUST' need to be adjusted based on the size of the
158 // data: Add file size to the marked DWORDS.
160 // File Size of TRACK??.WAV = nSectors*2352 + sizeof(XAFileHeader)
162 // RIFF('CDXA' FMT(Owner, Attr, 'X', 'A', FileNum, 0) data ( <CDXA Raw Data> )
165 LONG CdXAFileHeader
[] = {
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
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
182 #pragma alloc_text(PAGE, CdFastIoCheckIfPossible)
183 #pragma alloc_text(PAGE, CdSerial32)
189 IN PVOLUME_DEVICE_OBJECT VolumeDeviceObject
,
197 This is the driver entry to all of the Fsd dispatch points.
199 Conceptually the Io routine will call this routine on all requests
200 to the file system. We case on the type of request and invoke the
201 correct handler for this type of request. There is an exception filter
202 to catch any exceptions in the CDFS code as well as the CDFS process
205 This routine allocates and initializes the IrpContext for this request as
206 well as updating the top-level thread context as necessary. We may loop
207 in this routine if we need to retry the request for any reason. The
208 status code STATUS_CANT_WAIT is used to indicate this. Suppose the disk
209 in the drive has changed. An Fsd request will proceed normally until it
210 recognizes this condition. STATUS_VERIFY_REQUIRED is raised at that point
211 and the exception code will handle the verify and either return
212 STATUS_CANT_WAIT or STATUS_PENDING depending on whether the request was
217 VolumeDeviceObject - Supplies the volume device object for this request
219 Irp - Supplies the Irp being processed
223 NTSTATUS - The FSD status for the IRP
228 THREAD_CONTEXT ThreadContext
;
229 PIRP_CONTEXT IrpContext
= NULL
;
233 PVOID PreviousTopLevel
;
240 KIRQL SaveIrql
= KeGetCurrentIrql();
244 ASSERT_OPTIONAL_IRP( Irp
);
246 FsRtlEnterFileSystem();
249 PreviousTopLevel
= IoGetTopLevelIrp();
253 // Loop until this request has been completed or posted.
259 // Use a try-except to handle the exception cases.
265 // If the IrpContext is NULL then this is the first pass through
269 if (IrpContext
== NULL
) {
272 // Decide if this request is waitable an allocate the IrpContext.
273 // If the file object in the stack location is NULL then this
274 // is a mount which is always waitable. Otherwise we look at
275 // the file object flags.
278 if (IoGetCurrentIrpStackLocation( Irp
)->FileObject
== NULL
) {
284 Wait
= CanFsdWait( Irp
);
287 IrpContext
= CdCreateIrpContext( Irp
, Wait
);
290 // Update the thread context information.
293 CdSetThreadContext( IrpContext
, &ThreadContext
);
296 ASSERT( !CdTestTopLevel
||
297 SafeNodeType( IrpContext
->TopLevel
) == CDFS_NTC_IRP_CONTEXT
);
301 // Otherwise cleanup the IrpContext for the retry.
307 // Set the MORE_PROCESSING flag to make sure the IrpContext
308 // isn't inadvertently deleted here. Then cleanup the
309 // IrpContext to perform the retry.
312 SetFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_MORE_PROCESSING
);
313 CdCleanupIrpContext( IrpContext
, FALSE
);
317 // Case on the major irp code.
320 switch (IrpContext
->MajorFunction
) {
324 Status
= CdCommonCreate( IrpContext
, Irp
);
329 Status
= CdCommonClose( IrpContext
, Irp
);
335 // If this is an Mdl complete request, don't go through
339 if (FlagOn( IrpContext
->MinorFunction
, IRP_MN_COMPLETE
)) {
341 Status
= CdCompleteMdl( IrpContext
, Irp
);
345 Status
= CdCommonRead( IrpContext
, Irp
);
350 case IRP_MJ_QUERY_INFORMATION
:
352 Status
= CdCommonQueryInfo( IrpContext
, Irp
);
355 case IRP_MJ_SET_INFORMATION
:
357 Status
= CdCommonSetInfo( IrpContext
, Irp
);
360 case IRP_MJ_QUERY_VOLUME_INFORMATION
:
362 Status
= CdCommonQueryVolInfo( IrpContext
, Irp
);
365 case IRP_MJ_DIRECTORY_CONTROL
:
367 Status
= CdCommonDirControl( IrpContext
, Irp
);
370 case IRP_MJ_FILE_SYSTEM_CONTROL
:
372 Status
= CdCommonFsControl( IrpContext
, Irp
);
375 case IRP_MJ_DEVICE_CONTROL
:
377 Status
= CdCommonDevControl( IrpContext
, Irp
);
380 case IRP_MJ_LOCK_CONTROL
:
382 Status
= CdCommonLockControl( IrpContext
, Irp
);
385 case IRP_MJ_CLEANUP
:
387 Status
= CdCommonCleanup( IrpContext
, Irp
);
392 Status
= CdCommonPnp( IrpContext
, Irp
);
397 Status
= STATUS_INVALID_DEVICE_REQUEST
;
398 CdCompleteRequest( IrpContext
, Irp
, Status
);
401 } except( CdExceptionFilter( IrpContext
, GetExceptionInformation() )) {
403 Status
= CdProcessException( IrpContext
, Irp
, GetExceptionCode() );
406 } while (Status
== STATUS_CANT_WAIT
);
409 ASSERT( !CdTestTopLevel
||
410 (PreviousTopLevel
== IoGetTopLevelIrp()) );
413 FsRtlExitFileSystem();
415 ASSERT( SaveIrql
== KeGetCurrentIrql( ));
424 IN PIRP_CONTEXT IrpContext
,
426 IN BOOLEAN NormalizeStatus
,
427 IN OPTIONAL ULONG FileId
,
428 IN OPTIONAL ULONG Line
431 BOOLEAN BreakIn
= FALSE
;
433 AssertVerifyDevice( IrpContext
, Status
);
437 DbgPrint( "%p CdRaiseStatusEx 0x%x @ fid %d, line %d\n", PsGetCurrentThread(), Status
, FileId
, Line
);
440 if (CdTestRaisedStatus
&& !CdBreakOnAnyRaise
) {
445 Index
< (sizeof( CdInterestingExceptionCodes
) / sizeof( CdInterestingExceptionCodes
[0]));
448 if ((STATUS_SUCCESS
!= CdInterestingExceptionCodes
[Index
]) &&
449 (CdInterestingExceptionCodes
[Index
] == Status
)) {
457 if (BreakIn
|| CdBreakOnAnyRaise
) {
459 DbgPrint( "CDFS: Breaking on raised status %08x (BI=%d,BA=%d)\n", Status
, BreakIn
, CdBreakOnAnyRaise
);
460 DbgPrint( "CDFS: (FILEID %d LINE %d)\n", FileId
, Line
);
461 DbgPrint( "CDFS: Contact CDFS.SYS component owner for triage.\n");
462 DbgPrint( "CDFS: 'eb %p 0;eb %p 0' to disable this alert.\n", &CdTestRaisedStatus
, &CdBreakOnAnyRaise
);
467 if (NormalizeStatus
) {
469 IrpContext
->ExceptionStatus
= FsRtlNormalizeNtstatus( Status
, STATUS_UNEXPECTED_IO_ERROR
);
473 IrpContext
->ExceptionStatus
= Status
;
476 IrpContext
->RaisedAtLineFile
= (FileId
<< 16) | Line
;
478 ExRaiseStatus( IrpContext
->ExceptionStatus
);
485 IN PIRP_CONTEXT IrpContext
,
486 IN PEXCEPTION_POINTERS ExceptionPointer
493 This routine is used to decide whether we will handle a raised exception
494 status. If CDFS explicitly raised an error then this status is already
495 in the IrpContext. We choose which is the correct status code and
496 either indicate that we will handle the exception or bug-check the system.
500 ExceptionCode - Supplies the exception code to being checked.
504 ULONG - returns EXCEPTION_EXECUTE_HANDLER or bugchecks
509 NTSTATUS ExceptionCode
;
510 BOOLEAN TestStatus
= TRUE
;
512 ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext
);
514 ExceptionCode
= ExceptionPointer
->ExceptionRecord
->ExceptionCode
;
517 // If the exception is STATUS_IN_PAGE_ERROR, get the I/O error code
518 // from the exception record.
521 if ((ExceptionCode
== STATUS_IN_PAGE_ERROR
) &&
522 (ExceptionPointer
->ExceptionRecord
->NumberParameters
>= 3)) {
525 (NTSTATUS
)ExceptionPointer
->ExceptionRecord
->ExceptionInformation
[2];
529 // If there is an Irp context then check which status code to use.
532 if (ARGUMENT_PRESENT( IrpContext
)) {
534 if (IrpContext
->ExceptionStatus
== STATUS_SUCCESS
) {
537 // Store the real status into the IrpContext.
540 IrpContext
->ExceptionStatus
= ExceptionCode
;
545 // No need to test the status code if we raised it ourselves.
552 AssertVerifyDevice( IrpContext
, IrpContext
->ExceptionStatus
);
555 // Bug check if this status is not supported.
558 if (TestStatus
&& !FsRtlIsNtstatusExpected( ExceptionCode
)) {
560 CdBugCheck( (ULONG_PTR
) ExceptionPointer
->ExceptionRecord
,
561 (ULONG_PTR
) ExceptionPointer
->ContextRecord
,
562 (ULONG_PTR
) ExceptionPointer
->ExceptionRecord
->ExceptionAddress
);
566 return EXCEPTION_EXECUTE_HANDLER
;
572 IN PIRP_CONTEXT IrpContext OPTIONAL
,
574 IN NTSTATUS ExceptionCode
581 This routine processes an exception. It either completes the request
582 with the exception status in the IrpContext, sends this off to the Fsp
583 workque or causes it to be retried in the current thread if a verification
586 If the volume needs to be verified (STATUS_VERIFY_REQUIRED) and we can
587 do the work in the current thread we will translate the status code
588 to STATUS_CANT_WAIT to indicate that we need to retry the request.
592 Irp - Supplies the Irp being processed
594 ExceptionCode - Supplies the normalized exception status being handled
598 NTSTATUS - Returns the results of either posting the Irp or the
599 saved completion status.
604 PDEVICE_OBJECT Device
;
608 ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext
);
612 // If there is not an irp context, then complete the request with the
613 // current status code.
616 if (!ARGUMENT_PRESENT( IrpContext
)) {
618 CdCompleteRequest( NULL
, Irp
, ExceptionCode
);
619 return ExceptionCode
;
623 // Get the real exception status from the IrpContext.
626 ExceptionCode
= IrpContext
->ExceptionStatus
;
629 // If we are not a top level request then we just complete the request
630 // with the current status code.
633 if (!FlagOn( IrpContext
->Flags
, IRP_CONTEXT_FLAG_TOP_LEVEL
)) {
635 CdCompleteRequest( IrpContext
, Irp
, ExceptionCode
);
636 return ExceptionCode
;
640 // Check if we are posting this request. One of the following must be true
641 // if we are to post a request.
643 // - Status code is STATUS_CANT_WAIT and the request is asynchronous
644 // or we are forcing this to be posted.
646 // - Status code is STATUS_VERIFY_REQUIRED and we are at APC level
647 // or higher. Can't wait for IO in the verify path in this case.
649 // Set the MORE_PROCESSING flag in the IrpContext to keep if from being
650 // deleted if this is a retryable condition.
653 // Note that (children of) CdFsdPostRequest can raise (Mdl allocation).
658 if (ExceptionCode
== STATUS_CANT_WAIT
) {
660 if (FlagOn( IrpContext
->Flags
, IRP_CONTEXT_FLAG_FORCE_POST
)) {
662 ExceptionCode
= CdFsdPostRequest( IrpContext
, Irp
);
665 } else if (ExceptionCode
== STATUS_VERIFY_REQUIRED
) {
667 if (KeGetCurrentIrql() >= APC_LEVEL
) {
669 ExceptionCode
= CdFsdPostRequest( IrpContext
, Irp
);
673 except( CdExceptionFilter( IrpContext
, GetExceptionInformation() )) {
675 ExceptionCode
= GetExceptionCode();
679 // If we posted the request or our caller will retry then just return here.
682 if ((ExceptionCode
== STATUS_PENDING
) ||
683 (ExceptionCode
== STATUS_CANT_WAIT
)) {
685 return ExceptionCode
;
688 ClearFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_MORE_PROCESSING
);
691 // Store this error into the Irp for posting back to the Io system.
694 Irp
->IoStatus
.Status
= ExceptionCode
;
696 if (IoIsErrorUserInduced( ExceptionCode
)) {
699 // Check for the various error conditions that can be caused by,
700 // and possibly resolved my the user.
703 if (ExceptionCode
== STATUS_VERIFY_REQUIRED
) {
706 // Now we are at the top level file system entry point.
708 // If we have already posted this request then the device to
709 // verify is in the original thread. Find this via the Irp.
712 Device
= IoGetDeviceToVerify( Irp
->Tail
.Overlay
.Thread
);
713 IoSetDeviceToVerify( Irp
->Tail
.Overlay
.Thread
, NULL
);
716 // If there is no device in that location then check in the
720 if (Device
== NULL
) {
722 Device
= IoGetDeviceToVerify( PsGetCurrentThread() );
723 IoSetDeviceToVerify( PsGetCurrentThread(), NULL
);
725 ASSERT( Device
!= NULL
);
728 // Let's not BugCheck just because the driver messes up.
731 if (Device
== NULL
) {
733 ExceptionCode
= STATUS_DRIVER_INTERNAL_ERROR
;
735 CdCompleteRequest( IrpContext
, Irp
, ExceptionCode
);
737 return ExceptionCode
;
742 // CdPerformVerify() will do the right thing with the Irp.
743 // If we return STATUS_CANT_WAIT then the current thread
744 // can retry the request.
747 return CdPerformVerify( IrpContext
, Irp
, Device
);
751 // The other user induced conditions generate an error unless
752 // they have been disabled for this request.
755 if (FlagOn( IrpContext
->Flags
, IRP_CONTEXT_FLAG_DISABLE_POPUPS
)) {
757 CdCompleteRequest( IrpContext
, Irp
, ExceptionCode
);
759 return ExceptionCode
;
763 // Generate a pop-up.
767 if (IoGetCurrentIrpStackLocation( Irp
)->FileObject
!= NULL
) {
769 Vpb
= IoGetCurrentIrpStackLocation( Irp
)->FileObject
->Vpb
;
777 // The device to verify is either in my thread local storage
778 // or that of the thread that owns the Irp.
781 Thread
= Irp
->Tail
.Overlay
.Thread
;
782 Device
= IoGetDeviceToVerify( Thread
);
784 if (Device
== NULL
) {
786 Thread
= PsGetCurrentThread();
787 Device
= IoGetDeviceToVerify( Thread
);
789 ASSERT( Device
!= NULL
);
792 // Let's not BugCheck just because the driver messes up.
795 if (Device
== NULL
) {
797 CdCompleteRequest( IrpContext
, Irp
, ExceptionCode
);
799 return ExceptionCode
;
804 // This routine actually causes the pop-up. It usually
805 // does this by queuing an APC to the callers thread,
806 // but in some cases it will complete the request immediately,
807 // so it is very important to IoMarkIrpPending() first.
810 IoMarkIrpPending( Irp
);
811 IoRaiseHardError( Irp
, Vpb
, Device
);
814 // We will be handing control back to the caller here, so
815 // reset the saved device object.
818 IoSetDeviceToVerify( Thread
, NULL
);
821 // The Irp will be completed by Io or resubmitted. In either
822 // case we must clean up the IrpContext here.
825 CdCompleteRequest( IrpContext
, NULL
, STATUS_SUCCESS
);
826 return STATUS_PENDING
;
831 // This is just a run of the mill error.
834 CdCompleteRequest( IrpContext
, Irp
, ExceptionCode
);
836 return ExceptionCode
;
842 IN PIRP_CONTEXT IrpContext OPTIONAL
,
843 IN PIRP Irp OPTIONAL
,
851 This routine completes a Irp and cleans up the IrpContext. Either or
852 both of these may not be specified.
856 Irp - Supplies the Irp being processed.
858 Status - Supplies the status to complete the Irp with
867 ASSERT_OPTIONAL_IRP_CONTEXT( IrpContext
);
868 ASSERT_OPTIONAL_IRP( Irp
);
871 // Cleanup the IrpContext if passed in here.
874 if (ARGUMENT_PRESENT( IrpContext
)) {
876 CdCleanupIrpContext( IrpContext
, FALSE
);
880 // If we have an Irp then complete the irp.
883 if (ARGUMENT_PRESENT( Irp
)) {
886 // Clear the information field in case we have used this Irp
890 if (NT_ERROR( Status
) &&
891 FlagOn( Irp
->Flags
, IRP_INPUT_OPERATION
)) {
893 Irp
->IoStatus
.Information
= 0;
896 Irp
->IoStatus
.Status
= Status
;
898 AssertVerifyDeviceIrp( Irp
);
900 IoCompleteRequest( Irp
, IO_CD_ROM_INCREMENT
);
909 IN PIRP_CONTEXT IrpContext
,
910 IN PTHREAD_CONTEXT ThreadContext
917 This routine is called at each Fsd/Fsp entry point set up the IrpContext
918 and thread local storage to track top level requests. If there is
919 not a Cdfs context in the thread local storage then we use the input one.
920 Otherwise we use the one already there. This routine also updates the
921 IrpContext based on the state of the top-level context.
923 If the TOP_LEVEL flag in the IrpContext is already set when we are called
924 then we force this request to appear top level.
928 ThreadContext - Address on stack for local storage if not already present.
930 ForceTopLevel - We force this request to appear top level regardless of
931 any previous stack value.
940 PTHREAD_CONTEXT CurrentThreadContext
;
942 ULONG_PTR StackBottom
;
946 ASSERT_IRP_CONTEXT( IrpContext
);
949 // Get the current top-level irp out of the thread storage.
950 // If NULL then this is the top-level request.
953 CurrentThreadContext
= (PTHREAD_CONTEXT
) IoGetTopLevelIrp();
955 if (CurrentThreadContext
== NULL
) {
957 SetFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_TOP_LEVEL
);
961 // Initialize the input context unless we are using the current
962 // thread context block. We use the new block if our caller
963 // specified this or the existing block is invalid.
965 // The following must be true for the current to be a valid Cdfs context.
967 // Structure must lie within current stack.
968 // Address must be ULONG aligned.
969 // Cdfs signature must be present.
971 // If this is not a valid Cdfs context then use the input thread
972 // context and store it in the top level context.
975 IoGetStackLimits( &StackTop
, &StackBottom
);
977 if (FlagOn( IrpContext
->Flags
, IRP_CONTEXT_FLAG_TOP_LEVEL
) ||
978 (((ULONG_PTR
) CurrentThreadContext
> StackBottom
- sizeof( THREAD_CONTEXT
)) ||
979 ((ULONG_PTR
) CurrentThreadContext
<= StackTop
) ||
980 FlagOn( (ULONG_PTR
) CurrentThreadContext
, 0x3 ) ||
981 (CurrentThreadContext
->Cdfs
!= 0x53464443))) {
983 ThreadContext
->Cdfs
= 0x53464443;
984 ThreadContext
->SavedTopLevelIrp
= (PIRP
) CurrentThreadContext
;
985 ThreadContext
->TopLevelIrpContext
= IrpContext
;
986 IoSetTopLevelIrp( (PIRP
) ThreadContext
);
988 IrpContext
->TopLevel
= IrpContext
;
989 IrpContext
->ThreadContext
= ThreadContext
;
991 SetFlag( IrpContext
->Flags
, IRP_CONTEXT_FLAG_TOP_LEVEL_CDFS
);
994 // Otherwise use the IrpContext in the thread context.
999 IrpContext
->TopLevel
= CurrentThreadContext
->TopLevelIrpContext
;
1007 NTAPI
/* ReactOS Change: GCC Does not support STDCALL by default */
1008 CdFastIoCheckIfPossible (
1009 IN PFILE_OBJECT FileObject
,
1010 IN PLARGE_INTEGER FileOffset
,
1014 IN BOOLEAN CheckForReadOperation
,
1015 OUT PIO_STATUS_BLOCK IoStatus
,
1016 IN PDEVICE_OBJECT DeviceObject
1021 Routine Description:
1023 This routine checks if fast i/o is possible for a read/write operation
1027 FileObject - Supplies the file object used in the query
1029 FileOffset - Supplies the starting byte offset for the read/write operation
1031 Length - Supplies the length, in bytes, of the read/write operation
1033 Wait - Indicates if we can wait
1035 LockKey - Supplies the lock key
1037 CheckForReadOperation - Indicates if this is a check for a read or write
1040 IoStatus - Receives the status of the operation if our return value is
1045 BOOLEAN - TRUE if fast I/O is possible and FALSE if the caller needs
1046 to take the long route.
1052 TYPE_OF_OPEN TypeOfOpen
;
1053 LARGE_INTEGER LargeLength
;
1058 // Decode the type of file object we're being asked to process and
1059 // make sure that is is only a user file open.
1062 TypeOfOpen
= CdFastDecodeFileObject( FileObject
, &Fcb
);
1064 if ((TypeOfOpen
!= UserFileOpen
) || !CheckForReadOperation
) {
1066 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
1070 LargeLength
.QuadPart
= Length
;
1073 // Check whether the file locks will allow for fast io.
1076 if ((Fcb
->FileLock
== NULL
) ||
1077 FsRtlFastCheckLockForRead( Fcb
->FileLock
,
1082 PsGetCurrentProcess() )) {
1098 Routine Description:
1100 This routine is called to generate a 32 bit serial number. This is
1101 done by doing four separate checksums into an array of bytes and
1102 then treating the bytes as a ULONG.
1106 Buffer - Pointer to the buffer to generate the ID for.
1108 ByteCount - Number of bytes in the buffer.
1112 ULONG - The 32 bit serial number.
1125 // Initialize the serial number.
1128 Checksum
.SerialId
= 0;
1131 // Continue while there are more bytes to use.
1134 while (ByteCount
--) {
1137 // Increment this sub-checksum.
1140 Checksum
.Bytes
[ByteCount
& 0x3] += *(Buffer
++);
1144 // Return the checksums as a ULONG.
1147 return Checksum
.SerialId
;