ReactOS  0.4.13-dev-73-gcfe54aa
deviosup.c
Go to the documentation of this file.
1 /*++
2 
3 Copyright (c) 1989-2000 Microsoft Corporation
4 
5 Module Name:
6 
7  DevIoSup.c
8 
9 Abstract:
10 
11  This module implements the low lever disk read/write support for Cdfs.
12 
13 
14 --*/
15 
16 #include "cdprocs.h"
17 
18 //
19 // The Bug check file id for this module
20 //
21 
22 #define BugCheckFileId (CDFS_BUG_CHECK_DEVIOSUP)
23 
24 //
25 // Local structure definitions
26 //
27 
28 //
29 // An array of these structures is passed to CdMultipleAsync describing
30 // a set of runs to execute in parallel.
31 //
32 
33 typedef struct _IO_RUN {
34 
35  //
36  // Disk offset to read from and number of bytes to read. These
37  // must be a multiple of 2048 and the disk offset is also a
38  // multiple of 2048.
39  //
40 
43 
44  //
45  // Current position in user buffer. This is the final destination for
46  // this portion of the Io transfer.
47  //
48 
50 
51  //
52  // Buffer to perform the transfer to. If this is the same as the
53  // user buffer above then we are using the user's buffer. Otherwise
54  // we either allocated a temporary buffer or are using a different portion
55  // of the user's buffer.
56  //
57  // TransferBuffer - Read full sectors into this location. This can
58  // be a pointer into the user's buffer at the exact location the
59  // data should go. It can also be an earlier point in the user's
60  // buffer if the complete I/O doesn't start on a sector boundary.
61  // It may also be a pointer into an allocated buffer.
62  //
63  // TransferByteCount - Count of bytes to transfer to user's buffer. A
64  // value of zero indicates that we did do the transfer into the
65  // user's buffer directly.
66  //
67  // TransferBufferOffset - Offset in this buffer to begin the transfer
68  // to the user's buffer.
69  //
70 
74 
75  //
76  // This is the Mdl describing the locked pages in memory. It may
77  // be allocated to describe the allocated buffer. Or it may be
78  // the Mdl in the originating Irp. The MdlOffset is the offset of
79  // the current buffer from the beginning of the buffer described by
80  // the Mdl below. If the TransferMdl is not the same as the Mdl
81  // in the user's Irp then we know we have allocated it.
82  //
83 
86 
87  //
88  // Associated Irp used to perform the Io.
89  //
90 
92 
93 } IO_RUN;
94 typedef IO_RUN *PIO_RUN;
95 
96 #define MAX_PARALLEL_IOS 5
97 
98 //
99 // Local support routines
100 //
101 
102 _Requires_lock_held_(_Global_critical_region_)
103 BOOLEAN
104 CdPrepareBuffers (
105  _In_ PIRP_CONTEXT IrpContext,
106  _In_ PIRP Irp,
107  _In_ PFCB Fcb,
108  _In_reads_bytes_(ByteCount) PVOID UserBuffer,
109  _In_ ULONG UserBufferOffset,
112  _Out_ PIO_RUN IoRuns,
113  _Out_ PULONG RunCount,
114  _Out_ PULONG ThisByteCount
115  );
116 
117 _Requires_lock_held_(_Global_critical_region_)
118 VOID
119 CdPrepareXABuffers (
120  _In_ PIRP_CONTEXT IrpContext,
121  _In_ PIRP Irp,
122  _In_ PFCB Fcb,
123  _In_reads_bytes_(ByteCount) PVOID UserBuffer,
124  _In_ ULONG UserBufferOffset,
127  _Out_ PIO_RUN IoRuns,
128  _Out_ PULONG RunCount,
129  _Out_ PULONG ThisByteCount
130  );
131 
132 BOOLEAN
134  _In_ PIRP_CONTEXT IrpContext,
135  _Inout_ PIO_RUN IoRuns,
136  _In_ ULONG RunCount,
137  _In_ BOOLEAN FinalCleanup,
138  _In_ BOOLEAN SaveXABuffer
139  );
140 
141 _Requires_lock_held_(_Global_critical_region_)
142 VOID
143 CdMultipleAsync (
144  _In_ PIRP_CONTEXT IrpContext,
145  _In_ PFCB Fcb,
146  _In_ ULONG RunCount,
147  _Inout_ PIO_RUN IoRuns
148  );
149 
150 VOID
152  _In_ PIRP_CONTEXT IrpContext,
153  _In_ ULONG RunCount,
154  _Inout_ PIO_RUN IoRuns,
155  _In_ PRAW_READ_INFO RawReads,
156  _In_ TRACK_MODE_TYPE TrackMode
157  );
158 
159 _Requires_lock_held_(_Global_critical_region_)
160 VOID
161 CdSingleAsync (
162  _In_ PIRP_CONTEXT IrpContext,
163  _In_ PIO_RUN Run,
164  _In_ PFCB Fcb
165  );
166 
167 VOID
168 CdWaitSync (
169  _In_ PIRP_CONTEXT IrpContext
170  );
171 
172 // Tell prefast this is a completion routine.
173 IO_COMPLETION_ROUTINE CdMultiSyncCompletionRoutine;
174 
175 // Tell prefast this is a completion routine
176 IO_COMPLETION_ROUTINE CdMultiAsyncCompletionRoutine;
177 
178 // Tell prefast this is a completion routine
179 IO_COMPLETION_ROUTINE CdSingleSyncCompletionRoutine;
180 
181 // Tell prefast this is a completion routine
182 IO_COMPLETION_ROUTINE CdSingleAsyncCompletionRoutine;
183 
186 VOID
187 CdReadAudioSystemFile (
188  _In_ PIRP_CONTEXT IrpContext,
189  _In_ PFCB Fcb,
192  _Out_writes_bytes_(ByteCount) PVOID SystemBuffer
193  );
194 
195 _Requires_lock_held_(_Global_critical_region_)
196 BOOLEAN
197 CdReadDirDataThroughCache (
198  _In_ PIRP_CONTEXT IrpContext,
200  );
201 
202 #ifdef ALLOC_PRAGMA
203 #pragma alloc_text(PAGE, CdCreateUserMdl)
204 #pragma alloc_text(PAGE, CdMultipleAsync)
205 #pragma alloc_text(PAGE, CdMultipleXAAsync)
206 #pragma alloc_text(PAGE, CdNonCachedRead)
207 #pragma alloc_text(PAGE, CdNonCachedXARead)
208 #pragma alloc_text(PAGE, CdVolumeDasdWrite)
209 #pragma alloc_text(PAGE, CdFinishBuffers)
210 #pragma alloc_text(PAGE, CdPerformDevIoCtrl)
211 #pragma alloc_text(PAGE, CdPerformDevIoCtrlEx)
212 #pragma alloc_text(PAGE, CdPrepareBuffers)
213 #pragma alloc_text(PAGE, CdPrepareXABuffers)
214 #pragma alloc_text(PAGE, CdReadAudioSystemFile)
215 #pragma alloc_text(PAGE, CdReadSectors)
216 #pragma alloc_text(PAGE, CdSingleAsync)
217 #pragma alloc_text(PAGE, CdWaitSync)
218 #pragma alloc_text(PAGE, CdReadDirDataThroughCache)
219 #pragma alloc_text(PAGE, CdFreeDirCache)
220 #pragma alloc_text(PAGE, CdLbnToMmSsFf)
221 #pragma alloc_text(PAGE, CdHijackIrpAndFlushDevice)
222 #endif
223 
224 
225 VOID
227  _In_ ULONG Blocks,
228  _Out_writes_(3) PUCHAR Msf
229  )
230 
231 /*++
232 
233 Routine Description:
234 
235  Convert Lbn to MSF format.
236 
237 Arguments:
238 
239  Msf - on output, set to 0xMmSsFf representation of blocks.
240 
241 --*/
242 
243 {
244  PAGED_CODE();
245 
246  Blocks += 150; // Lbn 0 == 00:02:00, 1sec == 75 frames.
247 
248  Msf[0] = (UCHAR)(Blocks % 75); // Frames
249  Blocks /= 75; // -> Seconds
250  Msf[1] = (UCHAR)(Blocks % 60); // Seconds
251  Blocks /= 60; // -> Minutes
252  Msf[2] = (UCHAR)Blocks; // Minutes
253 }
254 
255 
256 __inline
259  _In_ PFCB Fcb
260  )
261 
262 /*++
263 
264 Routine Description:
265 
266  This routine converts FCB XA file type flags to the track mode
267  used by the device drivers.
268 
269 Arguments:
270 
271  Fcb - Fcb representing the file to read.
272 
273 Return Value:
274 
275  TrackMode of the file represented by the Fcb.
276 
277 --*/
278 {
282 
284 
285  return XAForm2;
286 
287  } else if (FlagOn( Fcb->FcbState, FCB_STATE_DA_FILE )) {
288 
289  return CDDA;
290 
291  }
292 
293  //
294  // FCB_STATE_MODE2_FILE
295  //
296 
297  return YellowMode2;
298 }
299 
300 
301 _Requires_lock_held_(_Global_critical_region_)
302 NTSTATUS
303 CdNonCachedRead (
304  _In_ PIRP_CONTEXT IrpContext,
305  _In_ PFCB Fcb,
308  )
309 
310 /*++
311 
312 Routine Description:
313 
314  This routine performs the non-cached reads to 'cooked' sectors (2048 bytes
315  per sector). This is done by performing the following in a loop.
316 
317  Fill in the IoRuns array for the next block of Io.
318  Send the Io to the device.
319  Perform any cleanup on the Io runs array.
320 
321  We will not do async Io to any request that generates non-aligned Io.
322  Also we will not perform async Io if it will exceed the size of our
323  IoRuns array. These should be the unusual cases but we will raise
324  or return CANT_WAIT in this routine if we detect this case.
325 
326 Arguments:
327 
328  Fcb - Fcb representing the file to read.
329 
330  StartingOffset - Logical offset in the file to read from.
331 
332  ByteCount - Number of bytes to read.
333 
334 Return Value:
335 
336  NTSTATUS - Status indicating the result of the operation.
337 
338 --*/
339 
340 {
342 
343  IO_RUN IoRuns[MAX_PARALLEL_IOS];
344  ULONG RunCount = 0;
345  ULONG CleanupRunCount = 0;
346 
347  PVOID UserBuffer;
348  ULONG UserBufferOffset = 0;
349  LONGLONG CurrentOffset = StartingOffset;
350  ULONG RemainingByteCount = ByteCount;
351  ULONG ThisByteCount;
352 
353  BOOLEAN Unaligned;
354  BOOLEAN FlushIoBuffers = FALSE;
355  BOOLEAN FirstPass = TRUE;
356 
357  PAGED_CODE();
358 
359  //
360  // We want to make sure the user's buffer is locked in all cases.
361  //
362 
363  if (IrpContext->Irp->MdlAddress == NULL) {
364 
365  CdCreateUserMdl( IrpContext, ByteCount, TRUE, IoWriteAccess );
366  }
367 
368  CdMapUserBuffer( IrpContext, &UserBuffer);
369 
370  //
371  // Special case the root directory and path table for a music volume.
372  //
373 
377 
378  CdReadAudioSystemFile( IrpContext,
379  Fcb,
381  ByteCount,
382  UserBuffer );
383 
384  return STATUS_SUCCESS;
385  }
386 
387  //
388  // If we're going to use the sector cache for this request, then
389  // mark the request waitable.
390  //
391 
392  if ((SafeNodeType( Fcb) == CDFS_NTC_FCB_INDEX) &&
393  (NULL != Fcb->Vcb->SectorCacheBuffer) &&
394  (VcbMounted == IrpContext->Vcb->VcbCondition)) {
395 
396  if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
397 
398  KeInitializeEvent( &IrpContext->IoContext->SyncEvent,
400  FALSE );
401 
402  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
403  }
404  }
405 
406  //
407  // Use a try-finally to perform the final cleanup.
408  //
409 
410  _SEH2_TRY {
411 
412  //
413  // Loop while there are more bytes to transfer.
414  //
415 
416  do {
417 
418  //
419  // Call prepare buffers to set up the next entries
420  // in the IoRuns array. Remember if there are any
421  // unaligned entries. This routine will raise CANT_WAIT
422  // if there are unaligned entries for an async request.
423  //
424 
425  RtlZeroMemory( IoRuns, sizeof( IoRuns ));
426 
427  Unaligned = CdPrepareBuffers( IrpContext,
428  IrpContext->Irp,
429  Fcb,
430  UserBuffer,
431  UserBufferOffset,
432  CurrentOffset,
433  RemainingByteCount,
434  IoRuns,
435  &CleanupRunCount,
436  &ThisByteCount );
437 
438 
439  RunCount = CleanupRunCount;
440 
441  //
442  // If this is an async request and there aren't enough entries
443  // in the Io array then post the request.
444  //
445 
446  if ((ThisByteCount < RemainingByteCount) &&
447  !FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
448 
449  CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
450  }
451 
452  //
453  // If the entire Io is contained in a single run then
454  // we can pass the Io down to the driver. Send the driver down
455  // and wait on the result if this is synchronous.
456  //
457 
458  if ((RunCount == 1) && !Unaligned && FirstPass) {
459 
460  CdSingleAsync( IrpContext,&IoRuns[0], Fcb );
461 
462  //
463  // No cleanup needed for the IoRuns array here.
464  //
465 
466  CleanupRunCount = 0;
467 
468  //
469  // Wait if we are synchronous, otherwise return
470  //
471 
472  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
473 
474  CdWaitSync( IrpContext );
475 
476  Status = IrpContext->Irp->IoStatus.Status;
477 
478  //
479  // Our completion routine will free the Io context but
480  // we do want to return STATUS_PENDING.
481  //
482 
483  } else {
484 
485  ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
487  }
488 
489  try_return( NOTHING );
490  }
491 
492  //
493  // Otherwise we will perform multiple Io to read in the data.
494  //
495 
496  CdMultipleAsync( IrpContext, Fcb, RunCount, IoRuns );
497 
498  //
499  // If this is a synchronous request then perform any necessary
500  // post-processing.
501  //
502 
503  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
504 
505  //
506  // Wait for the request to complete.
507  //
508 
509  CdWaitSync( IrpContext );
510 
511  Status = IrpContext->Irp->IoStatus.Status;
512 
513  //
514  // Exit this loop if there is an error.
515  //
516 
517  if (!NT_SUCCESS( Status )) {
518 
519  try_return( NOTHING );
520  }
521 
522  //
523  // Perform post read operations on the IoRuns if
524  // necessary.
525  //
526 
527  if (Unaligned &&
528  CdFinishBuffers( IrpContext, IoRuns, RunCount, FALSE, FALSE )) {
529 
530  FlushIoBuffers = TRUE;
531  }
532 
533  CleanupRunCount = 0;
534 
535  //
536  // Exit this loop if there are no more bytes to transfer
537  // or we have any error.
538  //
539 
540  RemainingByteCount -= ThisByteCount;
541  CurrentOffset += ThisByteCount;
542  UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
543  UserBufferOffset += ThisByteCount;
544 
545  //
546  // Otherwise this is an asynchronous request. Always return
547  // STATUS_PENDING.
548  //
549 
550  } else {
551 
552  ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
553  CleanupRunCount = 0;
555  break;
556  }
557 
558  FirstPass = FALSE;
559  } while (RemainingByteCount != 0);
560 
561  //
562  // Flush the hardware cache if we performed any copy operations.
563  //
564 
565  if (FlushIoBuffers) {
566 
567  KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE );
568  }
569 
570  try_exit: NOTHING;
571  } _SEH2_FINALLY {
572 
573  //
574  // Perform final cleanup on the IoRuns if necessary.
575  //
576 
577  if (CleanupRunCount != 0) {
578 
579  CdFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE, FALSE );
580  }
581  } _SEH2_END;
582 
583  return Status;
584 }
585 
586 
587 
588 _Requires_lock_held_(_Global_critical_region_)
589 NTSTATUS
590 CdNonCachedXARead (
591  _In_ PIRP_CONTEXT IrpContext,
592  _In_ PFCB Fcb,
595  )
596 
597 /*++
598 
599 Routine Description:
600 
601  This routine performs the non-cached reads for 'raw' sectors (2352 bytes
602  per sector). We also prepend a hard-coded RIFF header of 44 bytes to the file.
603  All of this is already reflected in the file size.
604 
605  We start by checking whether to prepend any portion of the RIFF header. Then we check
606  if the last raw sector read was from the beginning portion of this file, deallocating
607  that buffer if necessary. Finally we do the following in a loop.
608 
609  Fill the IoRuns array for the next block of Io.
610  Send the Io to the device driver.
611  Perform any cleanup necessary on the IoRuns array.
612 
613  We will not do any async request in this path. The request would have been
614  posted to a worker thread before getting to this point.
615 
616 Arguments:
617 
618  Fcb - Fcb representing the file to read.
619 
620  StartingOffset - Logical offset in the file to read from.
621 
622  ByteCount - Number of bytes to read.
623 
624 Return Value:
625 
626  NTSTATUS - Status indicating the result of the operation.
627 
628 --*/
629 
630 {
632 
633  RIFF_HEADER LocalRiffHeader;
634  PRIFF_HEADER RiffHeader;
635 
637  IO_RUN IoRuns[MAX_PARALLEL_IOS];
638  ULONG RunCount = 0;
639  ULONG CleanupRunCount = 0;
640 
641  PVOID UserBuffer;
642  ULONG UserBufferOffset = 0;
643  LONGLONG CurrentOffset = StartingOffset;
644  ULONG RemainingByteCount = ByteCount;
645  ULONG ThisByteCount = 0;
646  ULONG Address = 0;
647 
648  BOOLEAN TryingYellowbookMode2 = FALSE;
649 
650  TRACK_MODE_TYPE TrackMode;
651 
652  PAGED_CODE();
653 
654  //
655  // We want to make sure the user's buffer is locked in all cases.
656  //
657 
658  if (IrpContext->Irp->MdlAddress == NULL) {
659 
660  CdCreateUserMdl( IrpContext, ByteCount, TRUE, IoWriteAccess );
661  }
662 
663  //
664  // The byte count was rounded up to a logical sector boundary. It has
665  // nothing to do with the raw sectors on disk. Limit the remaining
666  // byte count to file size.
667  //
668 
669  if (CurrentOffset + RemainingByteCount > Fcb->FileSize.QuadPart) {
670 
671  RemainingByteCount = (ULONG) (Fcb->FileSize.QuadPart - CurrentOffset);
672  }
673 
674  CdMapUserBuffer( IrpContext, &UserBuffer);
675 
676  //
677  // Use a try-finally to perform the final cleanup.
678  //
679 
680  _SEH2_TRY {
681 
682  //
683  // If the initial offset lies within the RIFF header then copy the
684  // necessary bytes to the user's buffer.
685  //
686 
687  if (CurrentOffset < sizeof( RIFF_HEADER )) {
688 
689  //
690  // Copy the appropriate RIFF header.
691  //
692 
694 
695  //
696  // Create the pseudo entries for a music disk.
697  //
698 
700 
701  PAUDIO_PLAY_HEADER AudioPlayHeader;
702  PTRACK_DATA TrackData;
703 
704  AudioPlayHeader = (PAUDIO_PLAY_HEADER) &LocalRiffHeader;
705  TrackData = &Fcb->Vcb->CdromToc->TrackData[Fcb->XAFileNumber];
706 
707  //
708  // Copy the data header into our local buffer.
709  //
710 
711  RtlCopyMemory( AudioPlayHeader,
713  sizeof( AUDIO_PLAY_HEADER ));
714 
715  //
716  // Copy the serial number into the Id field. Also
717  // the track number in the TOC.
718  //
719 
720  AudioPlayHeader->DiskID = Fcb->Vcb->Vpb->SerialNumber;
721  AudioPlayHeader->TrackNumber = TrackData->TrackNumber;
722 
723  //
724  // One frame == One sector.
725  // One second == 75 frames (winds up being a 44.1khz sample)
726  //
727  // Note: LBN 0 == 0:2:0 (MSF)
728  //
729 
730  //
731  // Fill in the address (both MSF and Lbn format) and length fields.
732  //
733 
734  SwapCopyUchar4( &Address, TrackData->Address);
735  CdLbnToMmSsFf( Address, AudioPlayHeader->TrackAddress);
736 
737  SwapCopyUchar4( &AudioPlayHeader->StartingSector, TrackData->Address);
738 
739  //
740  // Go to the next track and find the starting point.
741  //
742 
743  TrackData = &Fcb->Vcb->CdromToc->TrackData[Fcb->XAFileNumber + 1];
744 
745  SwapCopyUchar4( &AudioPlayHeader->SectorCount, TrackData->Address);
746 
747  //
748  // Now compute the difference. If there is an error then use
749  // a length of zero.
750  //
751 
752  if (AudioPlayHeader->SectorCount < AudioPlayHeader->StartingSector) {
753 
754  AudioPlayHeader->SectorCount = 0;
755 
756  } else {
757 
758  AudioPlayHeader->SectorCount -= AudioPlayHeader->StartingSector;
759  }
760 
761  //
762  // Use the sector count to determine the MSF length. Bias by 150 to make
763  // it an "lbn" since the conversion routine corrects for Lbn 0 == 0:2:0;
764  //
765 
766  Address = AudioPlayHeader->SectorCount - 150;
767  CdLbnToMmSsFf( Address, AudioPlayHeader->TrackLength);
768 
769  ThisByteCount = sizeof( RIFF_HEADER ) - (ULONG) CurrentOffset;
770 
771  RtlCopyMemory( UserBuffer,
772  Add2Ptr( AudioPlayHeader,
773  sizeof( RIFF_HEADER ) - ThisByteCount,
774  PCHAR ),
775  ThisByteCount );
776 
777  //
778  // CD-XA CDDA
779  //
780 
781  } else {
782 
783  //
784  // The WAVE header format is actually much closer to an audio play
785  // header in format but we only need to modify the filesize fields.
786  //
787 
788  RiffHeader = &LocalRiffHeader;
789 
790  //
791  // Copy the data header into our local buffer and add the file size to it.
792  //
793 
794  RtlCopyMemory( RiffHeader,
796  sizeof( RIFF_HEADER ));
797 
798  RiffHeader->ChunkSize += Fcb->FileSize.LowPart;
799  RiffHeader->RawSectors += Fcb->FileSize.LowPart;
800 
801  ThisByteCount = sizeof( RIFF_HEADER ) - (ULONG) CurrentOffset;
802  RtlCopyMemory( UserBuffer,
803  Add2Ptr( RiffHeader,
804  sizeof( RIFF_HEADER ) - ThisByteCount,
805  PCHAR ),
806  ThisByteCount );
807  }
808 
809  //
810  // CD-XA non-audio
811  //
812 
813  } else {
814 
816 
817  RiffHeader = &LocalRiffHeader;
818 
819  //
820  // Copy the data header into our local buffer and add the file size to it.
821  //
822 
823  RtlCopyMemory( RiffHeader,
825  sizeof( RIFF_HEADER ));
826 
827  RiffHeader->ChunkSize += Fcb->FileSize.LowPart;
828  RiffHeader->RawSectors += Fcb->FileSize.LowPart;
829 
830  RiffHeader->Attributes = (USHORT) Fcb->XAAttributes;
831  RiffHeader->FileNumber = (UCHAR) Fcb->XAFileNumber;
832 
833  ThisByteCount = sizeof( RIFF_HEADER ) - (ULONG) CurrentOffset;
834  RtlCopyMemory( UserBuffer,
835  Add2Ptr( RiffHeader,
836  sizeof( RIFF_HEADER ) - ThisByteCount,
837  PCHAR ),
838  ThisByteCount );
839  }
840 
841  //
842  // Adjust the starting offset and byte count to reflect that
843  // we copied over the RIFF bytes.
844  //
845 
846  UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
847  UserBufferOffset += ThisByteCount;
848  CurrentOffset += ThisByteCount;
849  RemainingByteCount -= ThisByteCount;
850  }
851 
852  //
853  // Set up the appropriate trackmode
854  //
855 
856  TrackMode = CdFileTrackMode(Fcb);
857 
858  //
859  // Loop while there are more bytes to transfer.
860  //
861 
862  while (RemainingByteCount != 0) {
863 
864  //
865  // Call prepare buffers to set up the next entries
866  // in the IoRuns array. Remember if there are any
867  // unaligned entries. If we're just retrying the previous
868  // runs with a different track mode, then don't do anything here.
869  //
870 
871  if (!TryingYellowbookMode2) {
872 
873  RtlZeroMemory( IoRuns, sizeof( IoRuns ));
874  RtlZeroMemory( RawReads, sizeof( RawReads ));
875 
876  CdPrepareXABuffers( IrpContext,
877  IrpContext->Irp,
878  Fcb,
879  UserBuffer,
880  UserBufferOffset,
881  CurrentOffset,
882  RemainingByteCount,
883  IoRuns,
884  &CleanupRunCount,
885  &ThisByteCount );
886  }
887 
888  //
889  // Perform multiple Io to read in the data. Note that
890  // there may be no Io to do if we were able to use an
891  // existing buffer from the Vcb.
892  //
893 
894  if (CleanupRunCount != 0) {
895 
896  RunCount = CleanupRunCount;
897 
898  CdMultipleXAAsync( IrpContext,
899  RunCount,
900  IoRuns,
901  RawReads,
902  TrackMode );
903  //
904  // Wait for the request to complete.
905  //
906 
907  CdWaitSync( IrpContext );
908 
909  Status = IrpContext->Irp->IoStatus.Status;
910 
911  //
912  // Exit this loop if there is an error.
913  //
914 
915  if (!NT_SUCCESS( Status )) {
916 
917  if (!TryingYellowbookMode2 &&
919 
920  //
921  // There are wacky cases where someone has mastered as CD-XA
922  // but the sectors they claim are Mode2Form2 are really, according
923  // to ATAPI devices, Yellowbook Mode2. We will try once more
924  // with these. Kodak PHOTO-CD has been observed to do this.
925  //
926 
927  TryingYellowbookMode2 = TRUE;
928  TrackMode = YellowMode2;
929 
930  //
931  // Clear our 'cumulative' error status value
932  //
933 
934  IrpContext->IoContext->Status = STATUS_SUCCESS;
935 
936  continue;
937  }
938 
939  try_return( NOTHING );
940  }
941 
942  CleanupRunCount = 0;
943 
944  if (TryingYellowbookMode2) {
945 
946  //
947  // We succesfully got data when we tried switching the trackmode,
948  // so change the state of the FCB to remember that.
949  //
950 
953 
954  TryingYellowbookMode2 = FALSE;
955  }
956 
957  //
958  // Perform post read operations on the IoRuns if
959  // necessary.
960  //
961 
962  CdFinishBuffers( IrpContext, IoRuns, RunCount, FALSE, TRUE );
963  }
964 
965  //
966  // Adjust our loop variants.
967  //
968 
969  RemainingByteCount -= ThisByteCount;
970  CurrentOffset += ThisByteCount;
971  UserBuffer = Add2Ptr( UserBuffer, ThisByteCount, PVOID );
972  UserBufferOffset += ThisByteCount;
973  }
974 
975  //
976  // Always flush the hardware cache.
977  //
978 
979  KeFlushIoBuffers( IrpContext->Irp->MdlAddress, TRUE, FALSE );
980 
981  try_exit: NOTHING;
982  } _SEH2_FINALLY {
983 
984  //
985  // Perform final cleanup on the IoRuns if necessary.
986  //
987 
988  if (CleanupRunCount != 0) {
989 
990  CdFinishBuffers( IrpContext, IoRuns, CleanupRunCount, TRUE, FALSE );
991  }
992  } _SEH2_END;
993 
994  return Status;
995 }
996 
997 _Requires_lock_held_(_Global_critical_region_)
998 NTSTATUS
999 CdVolumeDasdWrite (
1000  _In_ PIRP_CONTEXT IrpContext,
1001  _In_ PFCB Fcb,
1004  )
1005 
1006 /*++
1007 
1008 Routine Description:
1009 
1010  This routine performs the non-cached writes to 'cooked' sectors (2048 bytes
1011  per sector). This is done by filling the IoRun for the desired request
1012  and send it down to the device.
1013 
1014 Arguments:
1015 
1016  Fcb - Fcb representing the file to read.
1017 
1018  StartingOffset - Logical offset in the file to read from.
1019 
1020  ByteCount - Number of bytes to read.
1021 
1022 Return Value:
1023 
1024  NTSTATUS - Status indicating the result of the operation.
1025 
1026 --*/
1027 
1028 {
1029  NTSTATUS Status;
1030  IO_RUN IoRun;
1031 
1032  PAGED_CODE();
1033 
1034  //
1035  // We want to make sure the user's buffer is locked in all cases.
1036  //
1037 
1038  CdLockUserBuffer( IrpContext, ByteCount, IoReadAccess );
1039 
1040  //
1041  // The entire Io can be contained in a single run, just pass
1042  // the Io down to the driver. Send the driver down
1043  // and wait on the result if this is synchronous.
1044  //
1045 
1046  RtlZeroMemory( &IoRun, sizeof( IoRun ) );
1047 
1048  IoRun.DiskOffset = StartingOffset;
1049  IoRun.DiskByteCount = ByteCount;
1050 
1051  CdSingleAsync( IrpContext, &IoRun, Fcb );
1052 
1053  //
1054  // Wait if we are synchronous, otherwise return
1055  //
1056 
1057  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
1058 
1059  CdWaitSync( IrpContext );
1060 
1061  Status = IrpContext->Irp->IoStatus.Status;
1062 
1063  //
1064  // Our completion routine will free the Io context but
1065  // we do want to return STATUS_PENDING.
1066  //
1067 
1068  } else {
1069 
1070  ClearFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_ALLOC_IO );
1072  }
1073 
1074  return Status;
1075 }
1076 
1077 
1078 
1079 BOOLEAN
1081  _In_ PIRP_CONTEXT IrpContext,
1084  _In_ BOOLEAN ReturnError,
1087  )
1088 
1089 /*++
1090 
1091 Routine Description:
1092 
1093  This routine is called to transfer sectors from the disk to a
1094  specified buffer. It is used for mount and volume verify operations.
1095 
1096  This routine is synchronous, it will not return until the operation
1097  is complete or until the operation fails.
1098 
1099  The routine allocates an IRP and then passes this IRP to a lower
1100  level driver. Errors may occur in the allocation of this IRP or
1101  in the operation of the lower driver.
1102 
1103 Arguments:
1104 
1105  StartingOffset - Logical offset on the disk to start the read. This
1106  must be on a sector boundary, no check is made here.
1107 
1108  ByteCount - Number of bytes to read. This is an integral number of
1109  2K sectors, no check is made here to confirm this.
1110 
1111  ReturnError - Indicates whether we should return TRUE or FALSE
1112  to indicate an error or raise an error condition. This only applies
1113  to the result of the IO. Any other error may cause a raise.
1114 
1115  Buffer - Buffer to transfer the disk data into.
1116 
1117  TargetDeviceObject - The device object for the volume to be read.
1118 
1119 Return Value:
1120 
1121  BOOLEAN - Depending on 'RaiseOnError' flag above. TRUE if operation
1122  succeeded, FALSE otherwise.
1123 
1124 --*/
1125 
1126 {
1127  NTSTATUS Status;
1128  KEVENT Event;
1129  PIRP Irp;
1130 
1131  PAGED_CODE();
1132 
1133  //
1134  // Initialize the event.
1135  //
1136 
1138 
1139  //
1140  // Attempt to allocate the IRP. If unsuccessful, raise
1141  // STATUS_INSUFFICIENT_RESOURCES.
1142  //
1143 
1146  Buffer,
1147  ByteCount,
1149  &Event,
1150  &IrpContext->Irp->IoStatus );
1151 
1152  if (Irp == NULL) {
1153 
1155  }
1156 
1157  //
1158  // Ignore the change line (verify) for mount and verify requests
1159  //
1160 
1162 
1163  //
1164  // Send the request down to the driver. If an error occurs return
1165  // it to the caller.
1166  //
1167 
1169 
1170  //
1171  // If the status was STATUS_PENDING then wait on the event.
1172  //
1173 
1174  if (Status == STATUS_PENDING) {
1175 
1177  Executive,
1178  KernelMode,
1179  FALSE,
1180  NULL );
1181 
1182  //
1183  // On a successful wait pull the status out of the IoStatus block.
1184  //
1185 
1186  if (NT_SUCCESS( Status )) {
1187 
1188  Status = IrpContext->Irp->IoStatus.Status;
1189  }
1190  }
1191 
1192  //
1193  // Check whether we should raise in the error case.
1194  //
1195 
1196  if (!NT_SUCCESS( Status )) {
1197 
1198  if (!ReturnError) {
1199 
1200  CdNormalizeAndRaiseStatus( IrpContext, Status );
1201  }
1202 
1203  //
1204  // We don't raise, but return FALSE to indicate an error.
1205  //
1206 
1207  return FALSE;
1208 
1209  //
1210  // The operation completed successfully.
1211  //
1212 
1213  } else {
1214 
1215  return TRUE;
1216  }
1217 }
1218 
1219 
1220 NTSTATUS
1222  _In_ PIRP_CONTEXT IrpContext,
1226  )
1227 
1228 /*++
1229 
1230 Routine Description:
1231 
1232  This routine locks the specified buffer for read access (we only write into
1233  the buffer). The file system requires this routine since it does not
1234  ask the I/O system to lock its buffers for direct I/O. This routine
1235  may only be called from the Fsd while still in the user context.
1236 
1237  This routine is only called if there is not already an Mdl.
1238 
1239 Arguments:
1240 
1241  BufferLength - Length of user buffer.
1242 
1243  RaiseOnError - Indicates if our caller wants this routine to raise on
1244  an error condition.
1245 
1246  Operation - IoWriteAccess or IoReadAccess
1247 
1248 Return Value:
1249 
1250  NTSTATUS - Status from this routine. Error status only returned if
1251  RaiseOnError is FALSE.
1252 
1253 --*/
1254 
1255 {
1257  PMDL Mdl;
1258 
1259  PAGED_CODE();
1260 
1262  UNREFERENCED_PARAMETER( IrpContext );
1263 
1264  ASSERT_IRP_CONTEXT( IrpContext );
1265  ASSERT_IRP( IrpContext->Irp );
1266  NT_ASSERT( IrpContext->Irp->MdlAddress == NULL );
1267 
1268  //
1269  // Allocate the Mdl, and Raise if we fail.
1270  //
1271 
1272  Mdl = IoAllocateMdl( IrpContext->Irp->UserBuffer,
1273  BufferLength,
1274  FALSE,
1275  FALSE,
1276  IrpContext->Irp );
1277 
1278  if (Mdl != NULL) {
1279 
1280  //
1281  // Now probe the buffer described by the Irp. If we get an exception,
1282  // deallocate the Mdl and return the appropriate "expected" status.
1283  //
1284 
1285  _SEH2_TRY {
1286 
1287  MmProbeAndLockPages( Mdl, IrpContext->Irp->RequestorMode, IoWriteAccess );
1288 
1290 
1291 #ifdef _MSC_VER
1292 #pragma warning(suppress: 6320)
1293 #endif
1295 
1297 
1298  IoFreeMdl( Mdl );
1299  IrpContext->Irp->MdlAddress = NULL;
1300 
1301  if (!FsRtlIsNtstatusExpected( Status )) {
1302 
1304  }
1305  } _SEH2_END;
1306  }
1307 
1308  //
1309  // Check if we are to raise or return
1310  //
1311 
1312  if (Status != STATUS_SUCCESS) {
1313 
1314  if (RaiseOnError) {
1315 
1316  CdRaiseStatus( IrpContext, Status );
1317  }
1318  }
1319 
1320  //
1321  // Return the status code.
1322  //
1323 
1324  return Status;
1325 }
1326 
1327 
1328 NTSTATUS
1330  _In_ PIRP_CONTEXT IrpContext,
1338  _In_ BOOLEAN OverrideVerify,
1340  )
1341 
1342 /*++
1343 
1344 Routine Description:
1345 
1346  This routine is called to perform DevIoCtrl functions internally within
1347  the filesystem. We take the status from the driver and return it to our
1348  caller.
1349 
1350 Arguments:
1351 
1352  IoControlCode - Code to send to driver.
1353 
1354  Device - This is the device to send the request to.
1355 
1356  OutPutBuffer - Pointer to output buffer.
1357 
1358  OutputBufferLength - Length of output buffer above.
1359 
1360  InternalDeviceIoControl - Indicates if this is an internal or external
1361  Io control code.
1362 
1363  OverrideVerify - Indicates if we should tell the driver not to return
1364  STATUS_VERIFY_REQUIRED for mount and verify.
1365 
1366  Iosb - If specified, we return the results of the operation here.
1367 
1368 Return Value:
1369 
1370  NTSTATUS - Status returned by next lower driver.
1371 
1372 --*/
1373 
1374 {
1375  NTSTATUS Status;
1376  PIRP Irp;
1377  KEVENT Event;
1378  IO_STATUS_BLOCK LocalIosb;
1379  PIO_STATUS_BLOCK IosbToUse = &LocalIosb;
1380 
1381  PAGED_CODE();
1382 
1383  UNREFERENCED_PARAMETER( IrpContext );
1384 
1385  //
1386  // Check if the user gave us an Iosb.
1387  //
1388 
1389  if (ARGUMENT_PRESENT( Iosb )) {
1390 
1391  IosbToUse = Iosb;
1392  }
1393 
1394  IosbToUse->Status = 0;
1395  IosbToUse->Information = 0;
1396 
1398 
1400  Device,
1401  InputBuffer,
1403  OutputBuffer,
1406  &Event,
1407  IosbToUse );
1408 
1409  if (Irp == NULL) {
1410 
1412  }
1413 
1414  if (OverrideVerify) {
1415 
1417  }
1418 
1419  Status = IoCallDriver( Device, Irp );
1420 
1421  //
1422  // We check for device not ready by first checking Status
1423  // and then if status pending was returned, the Iosb status
1424  // value.
1425  //
1426 
1427  if (Status == STATUS_PENDING) {
1428 
1430  Executive,
1431  KernelMode,
1432  FALSE,
1433  (PLARGE_INTEGER)NULL );
1434 
1435  Status = IosbToUse->Status;
1436  }
1437 
1438  NT_ASSERT( !(OverrideVerify && (STATUS_VERIFY_REQUIRED == Status)));
1439 
1440  return Status;
1441 }
1442 
1443 
1444 NTSTATUS
1445 FASTCALL
1447  _In_ PIRP_CONTEXT IrpContext,
1453  _In_ BOOLEAN OverrideVerify,
1455  )
1456 {
1457  PAGED_CODE();
1458 
1459  return CdPerformDevIoCtrlEx( IrpContext,
1460  IoControlCode,
1461  Device,
1462  NULL,
1463  0,
1464  OutputBuffer,
1467  OverrideVerify,
1468  Iosb);
1469 }
1470 
1471 
1472 
1473 //
1474 // Local support routine
1475 //
1476 
1477 _Requires_lock_held_(_Global_critical_region_)
1478 BOOLEAN
1479 CdPrepareBuffers (
1480  _In_ PIRP_CONTEXT IrpContext,
1481  _In_ PIRP Irp,
1482  _In_ PFCB Fcb,
1483  _In_reads_bytes_(ByteCount) PVOID UserBuffer,
1484  _In_ ULONG UserBufferOffset,
1487  _Out_ PIO_RUN IoRuns,
1488  _Out_ PULONG RunCount,
1489  _Out_ PULONG ThisByteCount
1490  )
1491 
1492 /*++
1493 
1494 Routine Description:
1495 
1496  This routine is the worker routine which looks up each run of an IO
1497  request and stores an entry for it in the IoRuns array. If the run
1498  begins on an unaligned disk boundary then we will allocate a buffer
1499  and Mdl for the unaligned portion and put it in the IoRuns entry.
1500 
1501  This routine will raise CANT_WAIT if an unaligned transfer is encountered
1502  and this request can't wait.
1503 
1504 Arguments:
1505 
1506  Irp - Originating Irp for this request.
1507 
1508  Fcb - This is the Fcb for this data stream. It may be a file, directory,
1509  path table or the volume file.
1510 
1511  UserBuffer - Current position in the user's buffer.
1512 
1513  UserBufferOffset - Offset from the start of the original user buffer.
1514 
1515  StartingOffset - Offset in the stream to begin the read.
1516 
1517  ByteCount - Number of bytes to read. We will fill the IoRuns array up
1518  to this point. We will stop early if we exceed the maximum number
1519  of parallel Ios we support.
1520 
1521  IoRuns - Pointer to the IoRuns array. The entire array is zeroes when
1522  this routine is called.
1523 
1524  RunCount - Number of entries in the IoRuns array filled here.
1525 
1526  ThisByteCount - Number of bytes described by the IoRun entries. Will
1527  not exceed the ByteCount passed in.
1528 
1529 Return Value:
1530 
1531  BOOLEAN - TRUE if one of the entries in an unaligned buffer (provided
1532  this is synchronous). FALSE otherwise.
1533 
1534 --*/
1535 
1536 {
1537  BOOLEAN FoundUnaligned = FALSE;
1538  PIO_RUN ThisIoRun = IoRuns;
1539 
1540  //
1541  // Following indicate where we are in the current transfer. Current
1542  // position in the file and number of bytes yet to transfer from
1543  // this position.
1544  //
1545 
1546  ULONG RemainingByteCount = ByteCount;
1547  LONGLONG CurrentFileOffset = StartingOffset;
1548 
1549  //
1550  // Following indicate the state of the user's buffer. We have
1551  // the destination of the next transfer and its offset in the
1552  // buffer. We also have the next available position in the buffer
1553  // available for a scratch buffer. We will align this up to a sector
1554  // boundary.
1555  //
1556 
1557  PVOID CurrentUserBuffer = UserBuffer;
1558  ULONG CurrentUserBufferOffset = UserBufferOffset;
1559 
1560  //
1561  // The following is the next contiguous bytes on the disk to
1562  // transfer. Read from the allocation package.
1563  //
1564 
1565  LONGLONG DiskOffset = 0;
1566  ULONG CurrentByteCount = RemainingByteCount;
1567 
1568  PAGED_CODE();
1569 
1570  //
1571  // Initialize the RunCount and ByteCount.
1572  //
1573 
1574  *RunCount = 0;
1575  *ThisByteCount = 0;
1576 
1577  //
1578  // Loop while there are more bytes to process or there are
1579  // available entries in the IoRun array.
1580  //
1581 
1582  while (TRUE) {
1583 
1584  *RunCount += 1;
1585 
1586  //
1587  // Initialize the current position in the IoRuns array.
1588  // Find the user's buffer for this portion of the transfer.
1589  //
1590 
1591  ThisIoRun->UserBuffer = CurrentUserBuffer;
1592 
1593  //
1594  // Find the allocation information for the current offset in the
1595  // stream.
1596  //
1597 
1598  CdLookupAllocation( IrpContext,
1599  Fcb,
1600  CurrentFileOffset,
1601  &DiskOffset,
1602  &CurrentByteCount );
1603 
1604  //
1605  // Limit ourselves to the data requested.
1606  //
1607 
1608  if (CurrentByteCount > RemainingByteCount) {
1609 
1610  CurrentByteCount = RemainingByteCount;
1611  }
1612 
1613  //
1614  // Handle the case where this is an unaligned transfer. The
1615  // following must all be true for this to be an aligned transfer.
1616  //
1617  // Disk offset on a 2048 byte boundary (Start of transfer)
1618  //
1619  // Byte count is a multiple of 2048 (Length of transfer)
1620  //
1621  // If the ByteCount is at least one sector then do the
1622  // unaligned transfer only for the tail. We can use the
1623  // user's buffer for the aligned portion.
1624  //
1625 
1626  if (FlagOn( (ULONG) DiskOffset, SECTOR_MASK ) ||
1627  (FlagOn( (ULONG) CurrentByteCount, SECTOR_MASK ) &&
1628  (CurrentByteCount < SECTOR_SIZE))) {
1629 
1631 
1632  //
1633  // If we can't wait then raise.
1634  //
1635 
1636  if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
1637 
1638  CdRaiseStatus( IrpContext, STATUS_CANT_WAIT );
1639  }
1640 
1641  //
1642  // Remember the offset and the number of bytes out of
1643  // the transfer buffer to copy into the user's buffer.
1644  // We will truncate the current read to end on a sector
1645  // boundary.
1646  //
1647 
1649 
1650  //
1651  // Make sure this transfer ends on a sector boundary.
1652  //
1653 
1654  ThisIoRun->DiskOffset = LlSectorTruncate( DiskOffset );
1655 
1656  //
1657  // We need to allocate an auxilary buffer for the next sector.
1658  // Read up to a page containing the partial data.
1659  //
1660 
1661  ThisIoRun->DiskByteCount = SectorAlign( ThisIoRun->TransferBufferOffset + CurrentByteCount );
1662 
1663  if (ThisIoRun->DiskByteCount > PAGE_SIZE) {
1664 
1665  ThisIoRun->DiskByteCount = PAGE_SIZE;
1666  }
1667 
1668  if (ThisIoRun->TransferBufferOffset + CurrentByteCount > ThisIoRun->DiskByteCount) {
1669 
1670  CurrentByteCount = ThisIoRun->DiskByteCount - ThisIoRun->TransferBufferOffset;
1671  }
1672 
1673  ThisIoRun->TransferByteCount = CurrentByteCount;
1674 
1675  //
1676  // Allocate a buffer for the non-aligned transfer.
1677  //
1678 
1680 
1681  //
1682  // Allocate and build the Mdl to describe this buffer.
1683  //
1684 
1685  ThisIoRun->TransferMdl = IoAllocateMdl( ThisIoRun->TransferBuffer,
1686  PAGE_SIZE,
1687  FALSE,
1688  FALSE,
1689  NULL );
1690 
1691  ThisIoRun->TransferVirtualAddress = ThisIoRun->TransferBuffer;
1692 
1693  if (ThisIoRun->TransferMdl == NULL) {
1694 
1695  IrpContext->Irp->IoStatus.Information = 0;
1697  }
1698 
1699  MmBuildMdlForNonPagedPool( ThisIoRun->TransferMdl );
1700 
1701  //
1702  // Remember we found an unaligned transfer.
1703  //
1704 
1705  FoundUnaligned = TRUE;
1706 
1707  //
1708  // Otherwise we use the buffer and Mdl from the original request.
1709  //
1710 
1711  } else {
1712 
1713  //
1714  // Truncate the read length to a sector-aligned value. We know
1715  // the length must be at least one sector or we wouldn't be
1716  // here now.
1717  //
1718 
1719  CurrentByteCount = SectorTruncate( CurrentByteCount );
1720 
1721  //
1722  // Read these sectors from the disk.
1723  //
1724 
1725  ThisIoRun->DiskOffset = DiskOffset;
1726  ThisIoRun->DiskByteCount = CurrentByteCount;
1727 
1728  //
1729  // Use the user's buffer and Mdl as our transfer buffer
1730  // and Mdl.
1731  //
1732 
1733  ThisIoRun->TransferBuffer = CurrentUserBuffer;
1734  ThisIoRun->TransferMdl = Irp->MdlAddress;
1735  ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
1736  CurrentUserBufferOffset,
1737  PVOID );
1738  }
1739 
1740  //
1741  // Update our position in the transfer and the RunCount and
1742  // ByteCount for the user.
1743  //
1744 
1745  RemainingByteCount -= CurrentByteCount;
1746 
1747  //
1748  // Break out if no more positions in the IoRuns array or
1749  // we have all of the bytes accounted for.
1750  //
1751 
1752  *ThisByteCount += CurrentByteCount;
1753 
1754  if ((RemainingByteCount == 0) || (*RunCount == MAX_PARALLEL_IOS)) {
1755 
1756  break;
1757  }
1758 
1759  //
1760  // Update our pointers for the user's buffer.
1761  //
1762 
1763  ThisIoRun += 1;
1764  CurrentUserBuffer = Add2Ptr( CurrentUserBuffer, CurrentByteCount, PVOID );
1765  CurrentUserBufferOffset += CurrentByteCount;
1766  CurrentFileOffset += CurrentByteCount;
1767  }
1768 
1769  return FoundUnaligned;
1770 }
1771 
1772 
1773 //
1774 // Local support routine
1775 //
1776 
1777 _Requires_lock_held_(_Global_critical_region_)
1778 VOID
1779 CdPrepareXABuffers (
1780  _In_ PIRP_CONTEXT IrpContext,
1781  _In_ PIRP Irp,
1782  _In_ PFCB Fcb,
1783  _In_reads_bytes_(ByteCount) PVOID UserBuffer,
1784  _In_ ULONG UserBufferOffset,
1787  _Out_ PIO_RUN IoRuns,
1788  _Out_ PULONG RunCount,
1789  _Out_ PULONG ThisByteCount
1790  )
1791 
1792 /*++
1793 
1794 Routine Description:
1795 
1796  This routine is the worker routine which looks up the individual runs
1797  of an IO request and stores an entry for it in the IoRuns array. The
1798  worker routine is for XA files where we need to convert the raw offset
1799  in the file to logical cooked sectors. We store one raw sector in
1800  the Vcb. If the current read is to that sector then we can simply copy
1801  whatever bytes are needed from that sector.
1802 
1803 Arguments:
1804 
1805  Irp - Originating Irp for this request.
1806 
1807  Fcb - This is the Fcb for this data stream. It must be a data stream.
1808 
1809  UserBuffer - Current position in the user's buffer.
1810 
1811  UserBufferOffset - Offset of this buffer from the beginning of the user's
1812  buffer for the original request.
1813 
1814  StartingOffset - Offset in the stream to begin the read.
1815 
1816  ByteCount - Number of bytes to read. We will fill the IoRuns array up
1817  to this point. We will stop early if we exceed the maximum number
1818  of parallel Ios we support.
1819 
1820  IoRuns - Pointer to the IoRuns array. The entire array is zeroes when
1821  this routine is called.
1822 
1823  RunCount - Number of entries in the IoRuns array filled here.
1824 
1825  ThisByteCount - Number of bytes described by the IoRun entries. Will
1826  not exceed the ByteCount passed in.
1827 
1828 Return Value:
1829 
1830  None
1831 
1832 --*/
1833 
1834 {
1835  PIO_RUN ThisIoRun = IoRuns;
1836  BOOLEAN PerformedCopy;
1837 
1838  //
1839  // The following deal with where we are in the range of raw sectors.
1840  // Note that we will bias the input file offset by the RIFF header
1841  // to deal directly with the raw sectors.
1842  //
1843 
1844  ULONG RawSectorOffset;
1845  ULONG RemainingRawByteCount = ByteCount;
1846  LONGLONG CurrentRawOffset = StartingOffset - sizeof( RIFF_HEADER );
1847 
1848  //
1849  // The following is the offset into the cooked sectors for the file.
1850  //
1851 
1852  LONGLONG CurrentCookedOffset;
1853  ULONG RemainingCookedByteCount;
1854 
1855  //
1856  // Following indicate the state of the user's buffer. We have
1857  // the destination of the next transfer and its offset in the
1858  // buffer. We also have the next available position in the buffer
1859  // available for a scratch buffer.
1860  //
1861 
1862  PVOID CurrentUserBuffer = UserBuffer;
1863  ULONG CurrentUserBufferOffset = UserBufferOffset;
1864 
1865  //
1866  // The following is the next contiguous bytes on the disk to
1867  // transfer. These are represented by cooked byte offset and length.
1868  // We also compute the number of raw bytes in the current transfer.
1869  //
1870 
1871  LONGLONG DiskOffset = 0;
1872  ULONG CurrentCookedByteCount = 0;
1873  ULONG CurrentRawByteCount;
1874 
1875  PAGED_CODE();
1876 
1877  //
1878  // We need to maintain our position as we walk through the sectors on the disk.
1879  // We keep separate values for the cooked offset as well as the raw offset.
1880  // These are initialized on sector boundaries and we move through these
1881  // the file sector-by-sector.
1882  //
1883  // Try to do 32-bit math.
1884  //
1885 
1886  if (((PLARGE_INTEGER) &CurrentRawOffset)->HighPart == 0) {
1887 
1888  //
1889  // Prefix/fast: Note that the following are safe since we only
1890  // take this path for 32bit offsets.
1891  //
1892 
1893  CurrentRawOffset = (LONGLONG) ((ULONG) CurrentRawOffset / RAW_SECTOR_SIZE);
1894 
1895 #ifdef _MSC_VER
1896 #pragma prefast( suppress: __WARNING_RESULTOFSHIFTCASTTOLARGERSIZE, "This is fine beacuse raw sector size > sector shift" )
1897 #endif
1898  CurrentCookedOffset = (LONGLONG) ((ULONG) CurrentRawOffset << SECTOR_SHIFT );
1899 
1900  CurrentRawOffset = (LONGLONG) ((ULONG) CurrentRawOffset * RAW_SECTOR_SIZE);
1901 
1902  //
1903  // Otherwise we need to do 64-bit math (sigh).
1904  //
1905 
1906  } else {
1907 
1908  CurrentRawOffset /= RAW_SECTOR_SIZE;
1909 
1910  CurrentCookedOffset = CurrentRawOffset << SECTOR_SHIFT;
1911 
1912  CurrentRawOffset *= RAW_SECTOR_SIZE;
1913  }
1914 
1915  //
1916  // Now compute the full number of sectors to be read. Count all of the raw
1917  // sectors that need to be read and convert to cooked bytes.
1918  //
1919 
1920  RawSectorOffset = (ULONG) ( StartingOffset - CurrentRawOffset) - sizeof( RIFF_HEADER );
1921  CurrentRawByteCount = (RawSectorOffset + RemainingRawByteCount + RAW_SECTOR_SIZE - 1) / RAW_SECTOR_SIZE;
1922 
1923  RemainingCookedByteCount = CurrentRawByteCount << SECTOR_SHIFT;
1924 
1925  //
1926  // Initialize the RunCount and ByteCount.
1927  //
1928 
1929  *RunCount = 0;
1930  *ThisByteCount = 0;
1931 
1932  //
1933  // Loop while there are more bytes to process or there are
1934  // available entries in the IoRun array.
1935  //
1936 
1937  while (TRUE) {
1938 
1939  PerformedCopy = FALSE;
1940  *RunCount += 1;
1941 
1942  //
1943  // Initialize the current position in the IoRuns array. Find the
1944  // eventual destination in the user's buffer for this portion of the transfer.
1945  //
1946 
1947  ThisIoRun->UserBuffer = CurrentUserBuffer;
1948 
1949  //
1950  // Find the allocation information for the current offset in the
1951  // stream.
1952  //
1953 
1954  CdLookupAllocation( IrpContext,
1955  Fcb,
1956  CurrentCookedOffset,
1957  &DiskOffset,
1958  &CurrentCookedByteCount );
1959  //
1960  // Maybe we got lucky and this is the same sector as in the
1961  // Vcb.
1962  //
1963 
1964  if (DiskOffset == Fcb->Vcb->XADiskOffset) {
1965 
1966  //
1967  // We will perform safe synchronization. Check again that
1968  // this is the correct sector.
1969  //
1970 
1971  CdLockVcb( IrpContext, Fcb->Vcb );
1972 
1973  if ((DiskOffset == Fcb->Vcb->XADiskOffset) &&
1974  (Fcb->Vcb->XASector != NULL)) {
1975 
1976  //
1977  // Copy any bytes we can from the current sector.
1978  //
1979 
1980  CurrentRawByteCount = RAW_SECTOR_SIZE - RawSectorOffset;
1981 
1982  //
1983  // Check whether we don't go to the end of the sector.
1984  //
1985 
1986  if (CurrentRawByteCount > RemainingRawByteCount) {
1987 
1988  CurrentRawByteCount = RemainingRawByteCount;
1989  }
1990 
1991  RtlCopyMemory( CurrentUserBuffer,
1992  Add2Ptr( Fcb->Vcb->XASector, RawSectorOffset, PCHAR ),
1993  CurrentRawByteCount );
1994 
1995  CdUnlockVcb( IrpContext, Fcb->Vcb );
1996 
1997  //
1998  // Adjust the run count and pointer in the IoRuns array
1999  // to show that we didn't use a position.
2000  //
2001 
2002  *RunCount -= 1;
2003  ThisIoRun -= 1;
2004 
2005  //
2006  // Remember that we performed a copy operation.
2007  //
2008 
2009  PerformedCopy = TRUE;
2010 
2011  CurrentCookedByteCount = SECTOR_SIZE;
2012 
2013  } else {
2014 
2015  //
2016  // The safe test showed no available buffer. Drop down to common code to
2017  // perform the Io.
2018  //
2019 
2020  CdUnlockVcb( IrpContext, Fcb->Vcb );
2021  }
2022  }
2023 
2024  //
2025  // No work in this pass if we did a copy operation.
2026  //
2027 
2028  if (!PerformedCopy) {
2029 
2030  //
2031  // Limit ourselves by the number of remaining cooked bytes.
2032  //
2033 
2034  if (CurrentCookedByteCount > RemainingCookedByteCount) {
2035 
2036  CurrentCookedByteCount = RemainingCookedByteCount;
2037  }
2038 
2039  ThisIoRun->DiskOffset = DiskOffset;
2040  ThisIoRun->TransferBufferOffset = RawSectorOffset;
2041 
2042  //
2043  // We will always need to perform copy operations for XA files.
2044  // We allocate an auxillary buffer to read the start of the
2045  // transfer. Then we can use a range of the user's buffer to
2046  // perform the next range of the transfer. Finally we may
2047  // need to allocate a buffer for the tail of the transfer.
2048  //
2049  // We can use the user's buffer (at the current scratch buffer) if the
2050  // following are true:
2051  //
2052  // If we are to store the beginning of the raw sector in the user's buffer.
2053  // The current scratch buffer precedes the destination in the user's buffer
2054  // (and hence also lies within it)
2055  // There are enough bytes remaining in the buffer for at least one
2056  // raw sector.
2057  //
2058 
2059  if ((RawSectorOffset == 0) &&
2060  (RemainingRawByteCount >= RAW_SECTOR_SIZE)) {
2061 
2062  //
2063  // We can use the scratch buffer. We must ensure we don't send down reads
2064  // greater than the device can handle, since the driver is unable to split
2065  // raw requests.
2066  //
2067 
2068  if (CurrentCookedByteCount <= Fcb->Vcb->MaximumTransferRawSectors * SECTOR_SIZE) {
2069 
2070  CurrentRawByteCount = (SectorAlign( CurrentCookedByteCount) >> SECTOR_SHIFT) * RAW_SECTOR_SIZE;
2071 
2072  } else {
2073 
2074  CurrentCookedByteCount = Fcb->Vcb->MaximumTransferRawSectors * SECTOR_SIZE;
2075  CurrentRawByteCount = Fcb->Vcb->MaximumTransferRawSectors * RAW_SECTOR_SIZE;
2076  }
2077 
2078  //
2079  // Now make sure we are within the page transfer limit.
2080  //
2081 
2082  while (ADDRESS_AND_SIZE_TO_SPAN_PAGES(CurrentUserBuffer, RawSectorAlign( CurrentRawByteCount)) >
2084 
2085  CurrentRawByteCount -= RAW_SECTOR_SIZE;
2086  CurrentCookedByteCount -= SECTOR_SIZE;
2087  }
2088 
2089  //
2090  // Trim the number of bytes to read if it won't fit into the current buffer. Take
2091  // account of the fact that we must read in whole raw sector multiples.
2092  //
2093 
2094  while (RawSectorAlign( CurrentRawByteCount) > RemainingRawByteCount) {
2095 
2096  CurrentRawByteCount -= RAW_SECTOR_SIZE;
2097  CurrentCookedByteCount -= SECTOR_SIZE;
2098  }
2099 
2100  //
2101  // Now trim the maximum number of raw bytes to the remaining bytes.
2102  //
2103 
2104  if (CurrentRawByteCount > RemainingRawByteCount) {
2105 
2106  CurrentRawByteCount = RemainingRawByteCount;
2107  }
2108 
2109  //
2110  // Update the IO run array. We point to the scratch buffer as
2111  // well as the buffer and Mdl in the original Irp.
2112  //
2113 
2114  ThisIoRun->DiskByteCount = SectorAlign( CurrentCookedByteCount);
2115 
2116  //
2117  // Point to the user's buffer and Mdl for this transfer.
2118  //
2119 
2120  ThisIoRun->TransferBuffer = CurrentUserBuffer;
2121  ThisIoRun->TransferMdl = Irp->MdlAddress;
2122  ThisIoRun->TransferVirtualAddress = Add2Ptr( Irp->UserBuffer,
2123  CurrentUserBufferOffset,
2124  PVOID);
2125 
2126  } else {
2127 
2128  //
2129  // We need to determine the number of bytes to transfer and the
2130  // offset into this page to begin the transfer.
2131  //
2132  // We will transfer only one raw sector.
2133  //
2134 
2135  ThisIoRun->DiskByteCount = SECTOR_SIZE;
2136 
2137  CurrentCookedByteCount = SECTOR_SIZE;
2138 
2139  ThisIoRun->TransferByteCount = RAW_SECTOR_SIZE - RawSectorOffset;
2140  ThisIoRun->TransferBufferOffset = RawSectorOffset;
2141 
2142  if (ThisIoRun->TransferByteCount > RemainingRawByteCount) {
2143 
2144  ThisIoRun->TransferByteCount = RemainingRawByteCount;
2145  }
2146 
2147  CurrentRawByteCount = ThisIoRun->TransferByteCount;
2148 
2149  //
2150  // We need to allocate an auxillary buffer. We will allocate
2151  // a single page. Then we will build an Mdl to describe the buffer.
2152  //
2153 
2155 
2156  //
2157  // Allocate and build the Mdl to describe this buffer.
2158  //
2159 
2160  ThisIoRun->TransferMdl = IoAllocateMdl( ThisIoRun->TransferBuffer,
2161  PAGE_SIZE,
2162  FALSE,
2163  FALSE,
2164  NULL );
2165 
2166  ThisIoRun->TransferVirtualAddress = ThisIoRun->TransferBuffer;
2167 
2168  if (ThisIoRun->TransferMdl == NULL) {
2169 
2170  IrpContext->Irp->IoStatus.Information = 0;
2172  }
2173 
2174  MmBuildMdlForNonPagedPool( ThisIoRun->TransferMdl );
2175  }
2176  }
2177 
2178  //
2179  // Update the byte count for our caller.
2180  //
2181 
2182  RemainingRawByteCount -= CurrentRawByteCount;
2183  *ThisByteCount += CurrentRawByteCount;
2184 
2185  //
2186  // Break out if no more positions in the IoRuns array or
2187  // we have all of the bytes accounted for.
2188  //
2189 
2190  if ((RemainingRawByteCount == 0) || (*RunCount == MAX_PARALLEL_IOS)) {
2191 
2192  break;
2193  }
2194 
2195  //
2196  // Update our local pointers to allow for the current range of bytes.
2197  //
2198 
2199  ThisIoRun += 1;
2200 
2201  CurrentUserBuffer = Add2Ptr( CurrentUserBuffer, CurrentRawByteCount, PVOID );
2202  CurrentUserBufferOffset += CurrentRawByteCount;
2203 
2204  RawSectorOffset = 0;
2205 
2206  CurrentCookedOffset += CurrentCookedByteCount;
2207  RemainingCookedByteCount -= CurrentCookedByteCount;
2208  }
2209 
2210  return;
2211 }
2212 
2213 
2214 //
2215 // Local support routine
2216 //
2217 
2218 BOOLEAN
2220  _In_ PIRP_CONTEXT IrpContext,
2221  _Inout_ PIO_RUN IoRuns,
2222  _In_ ULONG RunCount,
2223  _In_ BOOLEAN FinalCleanup,
2224  _In_ BOOLEAN SaveXABuffer
2225  )
2226 
2227 /*++
2228 
2229 Routine Description:
2230 
2231  This routine is called to perform any data transferred required for
2232  unaligned Io or to perform the final cleanup of the IoRuns array.
2233 
2234  In all cases this is where we will deallocate any buffer and mdl
2235  allocated to perform the unaligned transfer. If this is not the
2236  final cleanup then we also transfer the bytes to the user buffer
2237  and flush the hardware cache.
2238 
2239  We walk backwards through the run array because we may be shifting data
2240  in the user's buffer. Typical case is where we allocated a buffer for
2241  the first part of a read and then used the user's buffer for the
2242  next section (but stored it at the beginning of the buffer.
2243 
2244 Arguments:
2245 
2246  IoRuns - Pointer to the IoRuns array.
2247 
2248  RunCount - Number of entries in the IoRuns array filled here.
2249 
2250  FinalCleanup - Indicates if we should be deallocating temporary buffers
2251  (TRUE) or transferring bytes for a unaligned transfers and
2252  deallocating the buffers (FALSE). Flush the system cache if
2253  transferring data.
2254 
2255  SaveXABuffer - TRUE if we should try to save an XA buffer, FALSE otherwise
2256 
2257 Return Value:
2258 
2259  BOOLEAN - TRUE if this request needs the Io buffers to be flushed, FALSE otherwise.
2260 
2261 --*/
2262 
2263 {
2264  BOOLEAN FlushIoBuffers = FALSE;
2265 
2266  ULONG RemainingEntries = RunCount;
2267  PIO_RUN ThisIoRun = &IoRuns[RunCount - 1];
2268  PVCB Vcb;
2269 
2270  PAGED_CODE();
2271 
2272  //
2273  // Walk through each entry in the IoRun array.
2274  //
2275 
2276  while (RemainingEntries != 0) {
2277 
2278  //
2279  // We only need to deal with the case of an unaligned transfer.
2280  //
2281 
2282  if (ThisIoRun->TransferByteCount != 0) {
2283 
2284  //
2285  // If not the final cleanup then transfer the data to the
2286  // user's buffer and remember that we will need to flush
2287  // the user's buffer to memory.
2288  //
2289 
2290  if (!FinalCleanup) {
2291 
2292  RtlCopyMemory( ThisIoRun->UserBuffer,
2293  Add2Ptr( ThisIoRun->TransferBuffer,
2294  ThisIoRun->TransferBufferOffset,
2295  PVOID ),
2296  ThisIoRun->TransferByteCount );
2297 
2298  FlushIoBuffers = TRUE;
2299  }
2300 
2301  //
2302  // Free any Mdl we may have allocated. If the Mdl isn't
2303  // present then we must have failed during the allocation
2304  // phase.
2305  //
2306 
2307  if (ThisIoRun->TransferMdl != IrpContext->Irp->MdlAddress) {
2308 
2309  if (ThisIoRun->TransferMdl != NULL) {
2310 
2311  IoFreeMdl( ThisIoRun->TransferMdl );
2312  }
2313 
2314  //
2315  // Now free any buffer we may have allocated. If the Mdl
2316  // doesn't match the original Mdl then free the buffer.
2317  //
2318 
2319  if (ThisIoRun->TransferBuffer != NULL) {
2320 
2321  //
2322  // If this is the final buffer for an XA read then store this buffer
2323  // into the Vcb so that we will have it when reading any remaining
2324  // portion of this buffer.
2325  //
2326 
2327  if (SaveXABuffer) {
2328 
2329  Vcb = IrpContext->Vcb;
2330 
2331  CdLockVcb( IrpContext, Vcb );
2332 
2333  if (Vcb->XASector != NULL) {
2334 
2335  CdFreePool( &Vcb->XASector );
2336  }
2337 
2338  Vcb->XASector = ThisIoRun->TransferBuffer;
2339  Vcb->XADiskOffset = ThisIoRun->DiskOffset;
2340 
2341  SaveXABuffer = FALSE;
2342 
2343  CdUnlockVcb( IrpContext, Vcb );
2344 
2345  //
2346  // Otherwise just free the buffer.
2347  //
2348 
2349  } else {
2350 
2351  CdFreePool( &ThisIoRun->TransferBuffer );
2352  }
2353  }
2354  }
2355  }
2356 
2357  //
2358  // Now handle the case where we failed in the process
2359  // of allocating associated Irps and Mdls.
2360  //
2361 
2362  if (ThisIoRun->SavedIrp != NULL) {
2363 
2364  if (ThisIoRun->SavedIrp->MdlAddress != NULL) {
2365 
2366  IoFreeMdl( ThisIoRun->SavedIrp->MdlAddress );
2367  }
2368 
2369  IoFreeIrp( ThisIoRun->SavedIrp );
2370  }
2371 
2372  //
2373  // Move to the previous IoRun entry.
2374  //
2375 
2376  ThisIoRun -= 1;
2377  RemainingEntries -= 1;
2378  }
2379 
2380  //
2381  // If we copied any data then flush the Io buffers.
2382  //
2383 
2384  return FlushIoBuffers;
2385 }
2386 
2387 // Tell prefast this is a completion routine.
2388 IO_COMPLETION_ROUTINE CdSyncCompletionRoutine;
2389 
2390 NTSTATUS
2391 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
2394  PIRP Irp,
2395  PVOID Contxt
2396  )
2397 
2398 /*++
2399 
2400 Routine Description:
2401 
2402  Completion routine for synchronizing back to dispatch.
2403 
2404 Arguments:
2405 
2406  Contxt - pointer to KEVENT.
2407 
2408 Return Value:
2409 
2410  STATUS_MORE_PROCESSING_REQUIRED
2411 
2412 --*/
2413 
2414 {
2415  PKEVENT Event = (PKEVENT)Contxt;
2416  _Analysis_assume_(Contxt != NULL);
2417 
2420 
2421  KeSetEvent( Event, 0, FALSE );
2422 
2423  //
2424  // We don't want IO to get our IRP and free it.
2425  //
2426 
2428 }
2429 
2430 
2431 _Requires_lock_held_(_Global_critical_region_)
2432 VOID
2433 CdFreeDirCache (
2434  _In_ PIRP_CONTEXT IrpContext
2435  )
2436 
2437 /*++
2438 
2439 Routine Description:
2440 
2441  Safely frees the sector cache buffer.
2442 
2443 Arguments:
2444 
2445 Return Value:
2446 
2447  None.
2448 
2449 --*/
2450 
2451 {
2452  PAGED_CODE();
2453 
2454  if (NULL != IrpContext->Vcb->SectorCacheBuffer) {
2455 
2456  CdAcquireCacheForUpdate( IrpContext);
2457  CdFreePool( &IrpContext->Vcb->SectorCacheBuffer);
2458  CdReleaseCache( IrpContext);
2459  }
2460 }
2461 
2462 _Requires_lock_held_(_Global_critical_region_)
2463 BOOLEAN
2464 CdReadDirDataThroughCache (
2465  _In_ PIRP_CONTEXT IrpContext,
2466  _In_ PIO_RUN Run
2467  )
2468 
2469 /*++
2470 
2471 Routine Description:
2472 
2473  Reads blocks through the sector cache. If the data is present, then it
2474  is copied from memory. If not present, one of the cache chunks will be
2475  replaced with a chunk containing the requested region, and the data
2476  copied from there.
2477 
2478  Only intended for reading *directory* blocks, for the purpose of pre-caching
2479  directory information, by reading a chunk of blocks which hopefully contains
2480  other directory blocks, rather than just the (usually) single block requested.
2481 
2482 Arguments:
2483 
2484  Run - description of extent required, and buffer to read into.
2485 
2486 Return Value:
2487 
2488  None. Raises on error.
2489 
2490 --*/
2491 
2492 {
2493  PVCB Vcb = IrpContext->Vcb;
2494  ULONG Lbn = SectorsFromLlBytes( Run->DiskOffset);
2495  ULONG Remaining = SectorsFromBytes( Run->DiskByteCount);
2496  PUCHAR UserBuffer = Run->TransferBuffer;
2497 
2498  NTSTATUS Status;
2499  ULONG Found;
2500  ULONG BufferSectorOffset;
2501  ULONG StartBlock;
2502  ULONG EndBlock;
2503  ULONG Blocks;
2504 
2507 
2508  PTRACK_DATA TrackData;
2509 
2510 #if DBG
2511  BOOLEAN JustRead = FALSE;
2512 #endif
2513 
2514  ULONG Index;
2516  BOOLEAN Result = FALSE;
2517 
2518  PAGED_CODE();
2519 
2520  CdAcquireCacheForRead( IrpContext);
2521 
2522  _SEH2_TRY {
2523 
2524  //
2525  // Check the cache hasn't gone away due to volume verify failure (which
2526  // is the *only* reason it'll go away). If this is the case we raise
2527  // the same error any I/O would return if the cache weren't here.
2528  //
2529 
2530  if (NULL == Vcb->SectorCacheBuffer) {
2531 
2532  CdRaiseStatus( IrpContext, STATUS_VERIFY_REQUIRED);
2533  }
2534 
2535  while (Remaining) {
2536 
2537  Buffer = NULL;
2538 
2539  //
2540  // Look to see if any portion is currently cached.
2541  //
2542 
2543  for (Index = 0; Index < CD_SEC_CACHE_CHUNKS; Index++) {
2544 
2545  if ((Vcb->SecCacheChunks[ Index].BaseLbn != -1) &&
2546  (Vcb->SecCacheChunks[ Index].BaseLbn <= Lbn) &&
2547  ((Vcb->SecCacheChunks[ Index].BaseLbn + CD_SEC_CHUNK_BLOCKS) > Lbn)) {
2548 
2549  Buffer = &Vcb->SecCacheChunks[ Index];
2550  break;
2551  }
2552  }
2553 
2554  //
2555  // If we found any, copy it out and continue.
2556  //
2557 
2558  if (NULL != Buffer) {
2559 
2560  BufferSectorOffset = Lbn - Buffer->BaseLbn;
2561  Found = Min( CD_SEC_CHUNK_BLOCKS - BufferSectorOffset, Remaining);
2562 
2563  RtlCopyMemory( UserBuffer,
2564  Buffer->Buffer + BytesFromSectors( BufferSectorOffset),
2566 
2567  Remaining -= Found;
2568  UserBuffer += BytesFromSectors( Found);
2569  Lbn += Found;
2570 #if DBG
2571  //
2572  // Update stats. Don't count a hit if we've just read the data in.
2573  //
2574 
2575  if (!JustRead) {
2576 
2577  InterlockedIncrement( (LONG*)&Vcb->SecCacheHits);
2578  }
2579 
2580  JustRead = FALSE;
2581 #endif
2582  continue;
2583  }
2584 
2585  //
2586  // Missed the cache, so we need to read a new chunk. Take the cache
2587  // resource exclusive while we do so.
2588  //
2589 
2590  CdReleaseCache( IrpContext);
2591  CdAcquireCacheForUpdate( IrpContext);
2592 #if DBG
2593  Vcb->SecCacheMisses += 1;
2594 #endif
2595  //
2596  // Select the chunk to replace and calculate the start block of the
2597  // chunk to cache. We cache blocks which start on Lbns aligned on
2598  // multiples of chunk size, treating block 16 (VRS start) as block
2599  // zero.
2600  //
2601 
2602  Buffer = &Vcb->SecCacheChunks[ Vcb->SecCacheLRUChunkIndex];
2603 
2604  StartBlock = Lbn - ((Lbn - 16) % CD_SEC_CHUNK_BLOCKS);
2605 
2606  //
2607  // Make sure we don't try and read past end of the last track.
2608  //
2609 
2610 #ifdef __REACTOS__
2611  if (Vcb->CdromToc) {
2612 #endif
2613  TrackData = &Vcb->CdromToc->TrackData[(Vcb->CdromToc->LastTrack - Vcb->CdromToc->FirstTrack + 1)];
2614 
2615  SwapCopyUchar4( &EndBlock, &TrackData->Address );
2616 
2617  Blocks = EndBlock - StartBlock;
2618 
2619  if (Blocks > CD_SEC_CHUNK_BLOCKS) {
2620 
2621  Blocks = CD_SEC_CHUNK_BLOCKS;
2622  }
2623 #ifdef __REACTOS__
2624  } else {
2625  // HACK!!!!!!!! Might cause reads to overrun the end of the partition, no idea what consequences that can have.
2626  Blocks = CD_SEC_CHUNK_BLOCKS;
2627  }
2628 #endif
2629 
2630  if ((0 == Blocks) || (Lbn < 16)) {
2631 
2633  }
2634 
2635  //
2636  // Now build / send the read request.
2637  //
2638 
2639  IoReuseIrp( Vcb->SectorCacheIrp, STATUS_SUCCESS);
2640 
2641  KeClearEvent( &Vcb->SectorCacheEvent);
2642  Vcb->SectorCacheIrp->Tail.Overlay.Thread = PsGetCurrentThread();
2643 
2644  //
2645  // Get a pointer to the stack location of the first driver which will be
2646  // invoked. This is where the function codes and the parameters are set.
2647  //
2648 
2649  IrpSp = IoGetNextIrpStackLocation( Vcb->SectorCacheIrp);
2651 
2652  //
2653  // Build an MDL to describe the buffer.
2654  //
2655 
2656  IoAllocateMdl( Buffer->Buffer,
2657  BytesFromSectors( Blocks),
2658  FALSE,
2659  FALSE,
2660  Vcb->SectorCacheIrp);
2661 
2662  if (NULL == Vcb->SectorCacheIrp->MdlAddress) {
2663 
2664  IrpContext->Irp->IoStatus.Information = 0;
2666  }
2667 
2668  //
2669  // We're reading/writing into the block cache (paged pool). Lock the
2670  // pages and update the MDL with physical page information.
2671  //
2672 
2673  _SEH2_TRY {
2674 
2675  MmProbeAndLockPages( Vcb->SectorCacheIrp->MdlAddress,
2676  KernelMode,
2678  }
2679 #ifdef _MSC_VER
2680 #pragma warning(suppress: 6320)
2681 #endif
2683 
2684  IoFreeMdl( Vcb->SectorCacheIrp->MdlAddress );
2685  Vcb->SectorCacheIrp->MdlAddress = NULL;
2686  } _SEH2_END;
2687 
2688  if (NULL == Vcb->SectorCacheIrp->MdlAddress) {
2689 
2691  }
2692 
2693  //
2694  // Reset the BaseLbn as we can't trust this Buffer's data until the request
2695  // is successfully completed.
2696  //
2697 
2698  Buffer->BaseLbn = (ULONG)-1;
2699 
2700  IrpSp->Parameters.Read.Length = BytesFromSectors( Blocks);
2701  IrpSp->Parameters.Read.ByteOffset.QuadPart = LlBytesFromSectors( StartBlock);
2702 
2703  IoSetCompletionRoutine( Vcb->SectorCacheIrp,
2705  &Vcb->SectorCacheEvent,
2706  TRUE,
2707  TRUE,
2708  TRUE );
2709 
2710  Vcb->SectorCacheIrp->UserIosb = &Iosb;
2711 
2712  Status = IoCallDriver( Vcb->TargetDeviceObject, Vcb->SectorCacheIrp );
2713 
2714  if (STATUS_PENDING == Status) {
2715 
2716 
2717  (VOID)KeWaitForSingleObject( &Vcb->SectorCacheEvent,
2718  Executive,
2719  KernelMode,
2720  FALSE,
2721  NULL );
2722 
2723  Status = Vcb->SectorCacheIrp->IoStatus.Status;
2724  }
2725 
2726  Vcb->SectorCacheIrp->UserIosb = NULL;
2727 
2728  //
2729  // Unlock the pages and free the MDL.
2730  //
2731 
2732  MmUnlockPages( Vcb->SectorCacheIrp->MdlAddress );
2733  IoFreeMdl( Vcb->SectorCacheIrp->MdlAddress );
2734  Vcb->SectorCacheIrp->MdlAddress = NULL;
2735 
2736  if (!NT_SUCCESS( Status )) {
2737 
2738  try_leave( Status );
2739  }
2740 
2741  //
2742  // Update the buffer information, and drop the cache resource to shared
2743  // to allow in reads.
2744  //
2745 
2746  Buffer->BaseLbn = StartBlock;
2747  Vcb->SecCacheLRUChunkIndex = (Vcb->SecCacheLRUChunkIndex + 1) % CD_SEC_CACHE_CHUNKS;
2748 
2749  CdConvertCacheToShared( IrpContext);
2750 #if DBG
2751  JustRead = TRUE;
2752 #endif
2753  }
2754 
2755  Result = TRUE;
2756  }
2757  _SEH2_FINALLY {
2758 
2759  CdReleaseCache( IrpContext);
2760  } _SEH2_END;
2761 
2762  return Result;
2763 }
2764 
2765 
2766 //
2767 // Local support routine
2768 //
2769 
2770 _Requires_lock_held_(_Global_critical_region_)
2771 VOID
2772 CdMultipleAsync (
2773  _In_ PIRP_CONTEXT IrpContext,
2774  _In_ PFCB Fcb,
2775  _In_ ULONG RunCount,
2776  _Inout_ PIO_RUN IoRuns
2777  )
2778 
2779 /*++
2780 
2781 Routine Description:
2782 
2783  This routine first does the initial setup required of a Master IRP that is
2784  going to be completed using associated IRPs. This routine should not
2785  be used if only one async request is needed, instead the single read
2786  async routines should be called.
2787 
2788  A context parameter is initialized, to serve as a communications area
2789  between here and the common completion routine.
2790 
2791  Next this routine reads or writes one or more contiguous sectors from
2792  a device asynchronously, and is used if there are multiple reads for a
2793  master IRP. A completion routine is used to synchronize with the
2794  completion of all of the I/O requests started by calls to this routine.
2795 
2796  Also, prior to calling this routine the caller must initialize the
2797  IoStatus field in the Context, with the correct success status and byte
2798  count which are expected if all of the parallel transfers complete
2799  successfully. After return this status will be unchanged if all requests
2800  were, in fact, successful. However, if one or more errors occur, the
2801  IoStatus will be modified to reflect the error status and byte count
2802  from the first run (by Vbo) which encountered an error. I/O status
2803  from all subsequent runs will not be indicated.
2804 
2805 Arguments:
2806 
2807  RunCount - Supplies the number of multiple async requests
2808  that will be issued against the master irp.
2809 
2810  IoRuns - Supplies an array containing the Offset and ByteCount for the
2811  separate requests.
2812 
2813 Return Value:
2814 
2815  None.
2816 
2817 --*/
2818 
2819 {
2822  PMDL Mdl;
2823  PIRP Irp;
2824  PIRP MasterIrp;
2825  ULONG UnwindRunCount;
2826  BOOLEAN UseSectorCache;
2827 
2828  PAGED_CODE();
2829 
2830  //
2831  // Set up things according to whether this is truely async.
2832  //
2833 
2835 
2836  if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
2837 
2839  }
2840 
2841  //
2842  // For directories, use the sector cache.
2843  //
2844 
2845  if ((SafeNodeType( Fcb) == CDFS_NTC_FCB_INDEX) &&
2846  (NULL != Fcb->Vcb->SectorCacheBuffer) &&
2847  (VcbMounted == IrpContext->Vcb->VcbCondition)) {
2848 
2849  UseSectorCache = TRUE;
2850  }
2851  else {
2852 
2853  UseSectorCache = FALSE;
2854  }
2855 
2856  //
2857  // Initialize some local variables.
2858  //
2859 
2860  MasterIrp = IrpContext->Irp;
2861 
2862  //
2863  // Itterate through the runs, doing everything that can fail.
2864  // We let the cleanup in CdFinishBuffers clean up on error.
2865  //
2866 
2867  for (UnwindRunCount = 0;
2868  UnwindRunCount < RunCount;
2869  UnwindRunCount += 1) {
2870 
2871  if (UseSectorCache) {
2872 
2873  if (!CdReadDirDataThroughCache( IrpContext, &IoRuns[ UnwindRunCount])) {
2874 
2875  //
2876  // Turn off using directory cache and restart all over again.
2877  //
2878 
2879  UseSectorCache = FALSE;
2880  UnwindRunCount = 0;
2881  }
2882 
2883  continue;
2884  }
2885 
2886  //
2887  // Create an associated IRP, making sure there is one stack entry for
2888  // us, as well.
2889  //
2890 
2891  IoRuns[UnwindRunCount].SavedIrp =
2892  Irp = IoMakeAssociatedIrp( MasterIrp, (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1) );
2893 
2894  if (Irp == NULL) {
2895 
2896  IrpContext->Irp->IoStatus.Information = 0;
2898  }
2899 
2900  //
2901  // Allocate and build a partial Mdl for the request.
2902  //
2903 
2904  Mdl = IoAllocateMdl( IoRuns[UnwindRunCount].TransferVirtualAddress,
2905  IoRuns[UnwindRunCount].DiskByteCount,
2906  FALSE,
2907  FALSE,
2908  Irp );
2909 
2910  if (Mdl == NULL) {
2911 
2912  IrpContext->Irp->IoStatus.Information = 0;
2914  }
2915 
2916  IoBuildPartialMdl( IoRuns[UnwindRunCount].TransferMdl,
2917  Mdl,
2918  IoRuns[UnwindRunCount].TransferVirtualAddress,
2919  IoRuns[UnwindRunCount].DiskByteCount );
2920 
2921  //
2922  // Get the first IRP stack location in the associated Irp
2923  //
2924 
2927 
2928  //
2929  // Setup the Stack location to describe our read.
2930  //
2931 
2933  IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
2934  IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
2935 
2936  //
2937  // Set up the completion routine address in our stack frame.
2938  //
2939 
2942  IrpContext->IoContext,
2943  TRUE,
2944  TRUE,
2945  TRUE );
2946 
2947  //
2948  // Setup the next IRP stack location in the associated Irp for the disk
2949  // driver beneath us.
2950  //
2951 
2953 
2954  //
2955  // Setup the Stack location to do a read from the disk driver.
2956  //
2957 
2959  IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].DiskByteCount;
2960  IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].DiskOffset;
2961  }
2962 
2963  //
2964  // If we used the cache, we're done.
2965  //
2966 
2967  if (UseSectorCache) {
2968 
2969  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
2970 
2971  IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
2972  KeSetEvent( &IrpContext->IoContext->SyncEvent, 0, FALSE );
2973  }
2974 
2975  return;
2976  }
2977 
2978  //
2979  // We only need to set the associated IRP count in the master irp to
2980  // make it a master IRP. But we set the count to one more than our
2981  // caller requested, because we do not want the I/O system to complete
2982  // the I/O. We also set our own count.
2983  //
2984 
2985  IrpContext->IoContext->IrpCount = RunCount;
2986  IrpContext->IoContext->MasterIrp = MasterIrp;
2987 
2988  //
2989  // We set the count in the master Irp to 1 since typically we
2990  // will clean up the associated irps ourselves. Setting this to one
2991  // means completing the last associated Irp with SUCCESS (in the async
2992  // case) will complete the master irp.
2993  //
2994 
2995  MasterIrp->AssociatedIrp.IrpCount = 1;
2996 
2997  //
2998  // If we (FS) acquired locks, transition the lock owners to an object, since
2999  // when we return this thread could go away before request completion, and
3000  // the resource package may otherwise try to boost priority, etc.
3001  //
3002 
3003  if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ) &&
3004  FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL )) {
3005 
3006  NT_ASSERT( IrpContext->IoContext->ResourceThreadId == (ERESOURCE_THREAD)PsGetCurrentThread() );
3007 
3008  IrpContext->IoContext->ResourceThreadId = ((ULONG_PTR)IrpContext->IoContext) | 3;
3009 
3010  ExSetResourceOwnerPointer( IrpContext->IoContext->Resource,
3011  (PVOID)IrpContext->IoContext->ResourceThreadId );
3012  }
3013 
3014  //
3015  // Now that all the dangerous work is done, issue the Io requests
3016  //
3017 
3018  for (UnwindRunCount = 0;
3019  UnwindRunCount < RunCount;
3020  UnwindRunCount++) {
3021 
3022  Irp = IoRuns[UnwindRunCount].SavedIrp;
3023  IoRuns[UnwindRunCount].SavedIrp = NULL;
3024 
3025  if (NULL != Irp) {
3026 
3027  //
3028  // If IoCallDriver returns an error, it has completed the Irp
3029  // and the error will be caught by our completion routines
3030  // and dealt with as a normal IO error.
3031  //
3032 
3033  (VOID) IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
3034  }
3035  }
3036 }
3037 
3038 
3039 //
3040 // Local support routine
3041 //
3042 
3043 VOID
3045  _In_ PIRP_CONTEXT IrpContext,
3046  _In_ ULONG RunCount,
3047  _Inout_ PIO_RUN IoRuns,
3048  _In_ PRAW_READ_INFO RawReads,
3049  _In_ TRACK_MODE_TYPE TrackMode
3050  )
3051 
3052 /*++
3053 
3054 Routine Description:
3055 
3056  This routine first does the initial setup required of a Master IRP that is
3057  going to be completed using associated IRPs. This routine is used to generate
3058  the associated Irps used to read raw sectors from the disk.
3059 
3060  A context parameter is initialized, to serve as a communications area
3061  between here and the common completion routine.
3062 
3063  Next this routine reads or writes one or more contiguous sectors from
3064  a device asynchronously, and is used if there are multiple reads for a
3065  master IRP. A completion routine is used to synchronize with the
3066  completion of all of the I/O requests started by calls to this routine.
3067 
3068  Also, prior to calling this routine the caller must initialize the
3069  IoStatus field in the Context, with the correct success status and byte
3070  count which are expected if all of the parallel transfers complete
3071  successfully. After return this status will be unchanged if all requests
3072  were, in fact, successful. However, if one or more errors occur, the
3073  IoStatus will be modified to reflect the error status and byte count
3074  from the first run (by Vbo) which encountered an error. I/O status
3075  from all subsequent runs will not be indicated.
3076 
3077 Arguments:
3078 
3079  RunCount - Supplies the number of multiple async requests
3080  that will be issued against the master irp.
3081 
3082  IoRuns - Supplies an array containing the Offset and ByteCount for the
3083  separate requests.
3084 
3085  RawReads - Supplies an array of structures to store in the Irps passed to the
3086  device driver to perform the low-level Io.
3087 
3088  TrackMode - Supplies the recording mode of sectors in these IoRuns
3089 
3090 Return Value:
3091 
3092  None.
3093 
3094 --*/
3095 
3096 {
3098  PMDL Mdl;
3099  PIRP Irp;
3100  PIRP MasterIrp;
3101  ULONG UnwindRunCount;
3102  ULONG RawByteCount;
3103 
3104  PIO_RUN ThisIoRun = IoRuns;
3105  PRAW_READ_INFO ThisRawRead = RawReads;
3106 
3107  PAGED_CODE();
3108 
3109  //
3110  // Initialize some local variables.
3111  //
3112 
3113  MasterIrp = IrpContext->Irp;
3114 
3115  //
3116  // Itterate through the runs, doing everything that can fail.
3117  // We let the cleanup in CdFinishBuffers clean up on error.
3118  //
3119 
3120  for (UnwindRunCount = 0;
3121  UnwindRunCount < RunCount;
3122  UnwindRunCount += 1, ThisIoRun += 1, ThisRawRead += 1) {
3123 
3124  //
3125  // Create an associated IRP, making sure there is one stack entry for
3126  // us, as well.
3127  //
3128 
3129  ThisIoRun->SavedIrp =
3130  Irp = IoMakeAssociatedIrp( MasterIrp, (CCHAR)(IrpContext->Vcb->TargetDeviceObject->StackSize + 1) );
3131 
3132  if (Irp == NULL) {
3133 
3134  IrpContext->Irp->IoStatus.Information = 0;
3136  }
3137 
3138  //
3139  // Should have been passed a byte count of at least one sector, and
3140  // must be a multiple of sector size
3141  //
3142 
3143  NT_ASSERT( ThisIoRun->DiskByteCount && !SectorOffset(ThisIoRun->DiskByteCount));
3144 
3145  RawByteCount = SectorsFromBytes( ThisIoRun->DiskByteCount) * RAW_SECTOR_SIZE;
3146 
3147  //
3148  // Allocate and build a partial Mdl for the request.
3149  //
3150 
3151  Mdl = IoAllocateMdl( ThisIoRun->TransferVirtualAddress,
3152  RawByteCount,
3153  FALSE,
3154  FALSE,
3155  Irp );
3156 
3157  if (Mdl == NULL) {
3158 
3159  IrpContext->Irp->IoStatus.Information = 0;
3161  }
3162 
3163  IoBuildPartialMdl( ThisIoRun->TransferMdl,
3164  Mdl,
3165  ThisIoRun->TransferVirtualAddress,
3166  RawByteCount);
3167  //
3168  // Get the first IRP stack location in the associated Irp
3169  //
3170 
3173 
3174  //
3175  // Setup the Stack location to describe our read (using cooked values)
3176  // These values won't be used for the raw read in any case.
3177  //
3178 
3180  IrpSp->Parameters.Read.Length = ThisIoRun->DiskByteCount;
3181  IrpSp->Parameters.Read.ByteOffset.QuadPart = ThisIoRun->DiskOffset;
3182 
3183  //
3184  // Set up the completion routine address in our stack frame.
3185  //
3186 
3189  IrpContext->IoContext,
3190  TRUE,
3191  TRUE,
3192  TRUE );
3193 
3194  //
3195  // Setup the next IRP stack location in the associated Irp for the disk
3196  // driver beneath us.
3197  //
3198 
3200 
3201  //
3202  // Setup the stack location to do a read of raw sectors at this location.
3203  // Note that the storage stack always reads multiples of whole XA sectors.
3204  //
3205 
3206  ThisRawRead->DiskOffset.QuadPart = ThisIoRun->DiskOffset;
3207  ThisRawRead->SectorCount = ThisIoRun->DiskByteCount >> SECTOR_SHIFT;
3208  ThisRawRead->TrackMode = TrackMode;
3209 
3211 
3212  IrpSp->Parameters.DeviceIoControl.OutputBufferLength = ThisRawRead->SectorCount * RAW_SECTOR_SIZE;
3213  Irp->UserBuffer = ThisIoRun->TransferVirtualAddress;
3214 
3215  IrpSp->Parameters.DeviceIoControl.InputBufferLength = sizeof( RAW_READ_INFO );
3216  IrpSp->Parameters.DeviceIoControl.Type3InputBuffer = ThisRawRead;
3217 
3218  IrpSp->Parameters.DeviceIoControl.IoControlCode = IOCTL_CDROM_RAW_READ;
3219  }
3220 
3221  //
3222  // We only need to set the associated IRP count in the master irp to
3223  // make it a master IRP. But we set the count to one more than our
3224  // caller requested, because we do not want the I/O system to complete
3225  // the I/O. We also set our own count.
3226  //
3227 
3228  IrpContext->IoContext->IrpCount = RunCount;
3229  IrpContext->IoContext->MasterIrp = MasterIrp;
3230 
3231  //
3232  // We set the count in the master Irp to 1 since typically we
3233  // will clean up the associated irps ourselves. Setting this to one
3234  // means completing the last associated Irp with SUCCESS (in the async
3235  // case) will complete the master irp.
3236  //
3237 
3238  MasterIrp->AssociatedIrp.IrpCount = 1;
3239 
3240  //
3241  // Now that all the dangerous work is done, issue the Io requests
3242  //
3243 
3244  for (UnwindRunCount = 0;
3245  UnwindRunCount < RunCount;
3246  UnwindRunCount++) {
3247 
3248  Irp = IoRuns[UnwindRunCount].SavedIrp;
3249  IoRuns[UnwindRunCount].SavedIrp = NULL;
3250 
3251  //
3252  //
3253  // If IoCallDriver returns an error, it has completed the Irp
3254  // and the error will be caught by our completion routines
3255  // and dealt with as a normal IO error.
3256  //
3257 
3258  (VOID) IoCallDriver( IrpContext->Vcb->TargetDeviceObject, Irp );
3259  }
3260 
3261  return;
3262 }
3263 
3264 
3265 //
3266 // Local support routine
3267 //
3268 
3269 _Requires_lock_held_(_Global_critical_region_)
3270 VOID
3271 CdSingleAsync (
3272  _In_ PIRP_CONTEXT IrpContext,
3273  _In_ PIO_RUN Run,
3274  _In_ PFCB Fcb
3275  )
3276 
3277 /*++
3278 
3279 Routine Description:
3280 
3281  This routine reads one or more contiguous sectors from a device
3282  asynchronously, and is used if there is only one read necessary to
3283  complete the IRP. It implements the read by simply filling
3284  in the next stack frame in the Irp, and passing it on. The transfer
3285  occurs to the single buffer originally specified in the user request.
3286 
3287 Arguments:
3288 
3289  ByteOffset - Supplies the starting Logical Byte Offset to begin reading from
3290 
3291  ByteCount - Supplies the number of bytes to read from the device
3292 
3293 Return Value:
3294 
3295  None.
3296 
3297 --*/
3298 
3299 {
3302 
3303  PAGED_CODE();
3304 
3305  //
3306  // For directories, look in the sector cache,
3307  //
3308 
3309  if ((SafeNodeType( Fcb) == CDFS_NTC_FCB_INDEX) &&
3310  (NULL != Fcb->Vcb->SectorCacheBuffer) &&
3311  (VcbMounted == IrpContext->Vcb->VcbCondition)) {
3312 
3313  if (CdReadDirDataThroughCache( IrpContext, Run )) {
3314 
3315  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT)) {
3316 
3317  IrpContext->Irp->IoStatus.Status = STATUS_SUCCESS;
3318  KeSetEvent( &IrpContext->IoContext->SyncEvent, 0, FALSE );
3319  }
3320 
3321  return;
3322  }
3323  }
3324 
3325  //
3326  // Set up things according to whether this is truely async.
3327  //
3328 
3329  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT )) {
3330 
3332 
3333  } else {
3334 
3336 
3337  //
3338  // If we (FS) acquired locks, transition the lock owners to an object, since
3339  // when we return this thread could go away before request completion, and
3340  // the resource package may otherwise try to boost priority, etc.
3341  //
3342 
3343  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_TOP_LEVEL )) {
3344 
3345  NT_ASSERT( IrpContext->IoContext->ResourceThreadId == (ERESOURCE_THREAD)PsGetCurrentThread() );
3346 
3347  IrpContext->IoContext->ResourceThreadId = ((ULONG_PTR)IrpContext->IoContext) | 3;
3348 
3349  ExSetResourceOwnerPointer( IrpContext->IoContext->Resource,
3350  (PVOID)IrpContext->IoContext->ResourceThreadId );
3351  }
3352  }
3353 
3354  //
3355  // Set up the completion routine address in our stack frame.
3356  //
3357 
3358  IoSetCompletionRoutine( IrpContext->Irp,
3360  IrpContext->IoContext,
3361  TRUE,
3362  TRUE,
3363  TRUE );
3364 
3365  //
3366  // Setup the next IRP stack location in the associated Irp for the disk
3367  // driver beneath us.
3368  //
3369 
3370  IrpSp = IoGetNextIrpStackLocation( IrpContext->Irp );
3371 
3372  //
3373  // Setup the Stack location to do a read from the disk driver.
3374  //
3375 
3376  IrpSp->MajorFunction = IrpContext->MajorFunction;
3377  IrpSp->Parameters.Read.Length = Run->DiskByteCount;
3378  IrpSp->Parameters.Read.ByteOffset.QuadPart = Run->DiskOffset;
3379 
3380  //
3381  // Issue the Io request
3382  //
3383 
3384  //
3385  // If IoCallDriver returns an error, it has completed the Irp
3386  // and the error will be caught by our completion routines
3387  // and dealt with as a normal IO error.
3388  //
3389 
3390  (VOID)IoCallDriver( IrpContext->Vcb->TargetDeviceObject, IrpContext->Irp );
3391 }
3392 
3393 
3394 //
3395 // Local support routine
3396 //
3397 
3398 VOID
3400  _In_ PIRP_CONTEXT IrpContext
3401  )
3402 
3403 /*++
3404 
3405 Routine Description:
3406 
3407  This routine waits for one or more previously started I/O requests
3408  from the above routines, by simply waiting on the event.
3409 
3410 Arguments:
3411 
3412 Return Value:
3413 
3414  None
3415 
3416 --*/
3417 
3418 {
3419  PAGED_CODE();
3420 
3421 
3422  (VOID)KeWaitForSingleObject( &IrpContext->IoContext->SyncEvent,
3423  Executive,
3424  KernelMode,
3425  FALSE,
3426  NULL );
3427 
3428  KeClearEvent( &IrpContext->IoContext->SyncEvent );
3429 }
3430 
3431 
3432 //
3433 // Local support routine
3434 //
3435 
3436 NTSTATUS
3437 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3440  PIRP Irp,
3441  PVOID Context
3442  )
3443 
3444 /*++
3445 
3446 Routine Description:
3447 
3448  This is the completion routine for all synchronous reads
3449  started via CdMultipleAsynch.
3450 
3451  The completion routine has has the following responsibilities:
3452 
3453  If the individual request was completed with an error, then
3454  this completion routine must see if this is the first error
3455  and remember the error status in the Context.
3456 
3457  If the IrpCount goes to 1, then it sets the event in the Context
3458  parameter to signal the caller that all of the asynch requests
3459  are done.
3460 
3461 Arguments:
3462 
3463  DeviceObject - Pointer to the file system device object.
3464 
3465  Irp - Pointer to the associated Irp which is being completed. (This
3466  Irp will no longer be accessible after this routine returns.)
3467 
3468  Context - The context parameter which was specified for all of
3469  the multiple asynch I/O requests for this MasterIrp.
3470 
3471 Return Value:
3472 
3473  The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
3474  immediately complete the Master Irp without being in a race condition
3475  with the IoCompleteRequest thread trying to decrement the IrpCount in
3476  the Master Irp.
3477 
3478 --*/
3479 
3480 {
3481  PCD_IO_CONTEXT IoContext = Context;
3483 
3485 
3486  //
3487  // If we got an error (or verify required), remember it in the Irp
3488  //
3489 
3490  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
3491 
3492  InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status );
3493  IoContext->MasterIrp->IoStatus.Information = 0;
3494  }
3495 
3496  //
3497  // We must do this here since IoCompleteRequest won't get a chance
3498  // on this associated Irp.
3499  //
3500 
3501  IoFreeMdl( Irp->MdlAddress );
3502  IoFreeIrp( Irp );
3503 
3504  if (InterlockedDecrement( &IoContext->IrpCount ) == 0) {
3505 
3506  //
3507  // Update the Master Irp with any error status from the associated Irps.
3508  //
3509 
3510  IoContext->MasterIrp->IoStatus.Status = IoContext->Status;
3511  KeSetEvent( &IoContext->SyncEvent, 0, FALSE );
3512  }
3513 
3515 
3517 }
3518 
3519 
3520 //
3521 // Local support routine
3522 //
3523 
3524 NTSTATUS
3525 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3528  PIRP Irp,
3529  PVOID Context
3530  )
3531 
3532 /*++
3533 
3534 Routine Description:
3535 
3536  This is the completion routine for all asynchronous reads
3537  started via CdMultipleAsynch.
3538 
3539  The completion routine has has the following responsibilities:
3540 
3541  If the individual request was completed with an error, then
3542  this completion routine must see if this is the first error
3543  and remember the error status in the Context.
3544 
3545 Arguments:
3546 
3547  DeviceObject - Pointer to the file system device object.
3548 
3549  Irp - Pointer to the associated Irp which is being completed. (This
3550  Irp will no longer be accessible after this routine returns.)
3551 
3552  Context - The context parameter which was specified for all of
3553  the multiple asynch I/O requests for this MasterIrp.
3554 
3555 Return Value:
3556 
3557  Currently always returns STATUS_SUCCESS.
3558 
3559 --*/
3560 
3561 {
3562  PCD_IO_CONTEXT IoContext = Context;
3565 
3567 
3568  //
3569  // If we got an error (or verify required), remember it in the Irp
3570  //
3571 
3572  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
3573 
3574  InterlockedExchange( &IoContext->Status, Irp->IoStatus.Status );
3575  }
3576 
3577  //
3578  // Decrement IrpCount and see if it goes to zero.
3579  //
3580 
3581  if (InterlockedDecrement( &IoContext->IrpCount ) == 0) {
3582 
3583  //
3584  // Mark the master Irp pending
3585  //
3586 
3587  IoMarkIrpPending( IoContext->MasterIrp );
3588 
3589  //
3590  // Update the Master Irp with any error status from the associated Irps.
3591  //
3592 
3593  IoContext->MasterIrp->IoStatus.Status = IoContext->Status;
3594 
3595  //
3596  // Update the information field with the correct value.
3597  //
3598 
3599  IoContext->MasterIrp->IoStatus.Information = 0;
3600 
3601  if (NT_SUCCESS( IoContext->MasterIrp->IoStatus.Status )) {
3602 
3603  IoContext->MasterIrp->IoStatus.Information = IoContext->RequestedByteCount;
3604  }
3605 
3606  //
3607  // Now release the resource
3608  //
3609 
3611  ExReleaseResourceForThreadLite( IoContext->Resource, IoContext->ResourceThreadId );
3612 
3613  //
3614  // and finally, free the context record.
3615  //
3616 
3617  CdFreeIoContext( IoContext );
3618 
3619  //
3620  // Return success in this case.
3621  //
3622 
3623  return STATUS_SUCCESS;
3624 
3625  } else {
3626 
3627  //
3628  // We need to cleanup the associated Irp and its Mdl.
3629  //
3630 
3631  IoFreeMdl( Irp->MdlAddress );
3632  IoFreeIrp( Irp );
3633 
3635  }
3636 
3637 }
3638 
3639 
3640 //
3641 // Local support routine
3642 //
3643 
3644 NTSTATUS
3645 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3648  PIRP Irp,
3649  PVOID Context
3650  )
3651 
3652 /*++
3653 
3654 Routine Description:
3655 
3656  This is the completion routine for all reads started via CdSingleAsynch.
3657 
3658  The completion routine has has the following responsibilities:
3659 
3660  It sets the event in the Context parameter to signal the caller
3661  that all of the asynch requests are done.
3662 
3663 Arguments:
3664 
3665  DeviceObject - Pointer to the file system device object.
3666 
3667  Irp - Pointer to the Irp for this request. (This Irp will no longer
3668  be accessible after this routine returns.)
3669 
3670  Context - The context parameter which was specified in the call to
3671  CdSingleAsynch.
3672 
3673 Return Value:
3674 
3675  The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
3676  immediately complete the Master Irp without being in a race condition
3677  with the IoCompleteRequest thread trying to decrement the IrpCount in
3678  the Master Irp.
3679 
3680 --*/
3681 
3682 {
3684 
3686 
3688 
3689  //
3690  // Store the correct information field into the Irp.
3691  //
3692 
3693  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
3694 
3695  Irp->IoStatus.Information = 0;
3696  }
3697 
3698  KeSetEvent( &((PCD_IO_CONTEXT)Context)->SyncEvent, 0, FALSE );
3699 
3701 }
3702 
3703 
3704 //
3705 // Local support routine
3706 //
3707 
3708 NTSTATUS
3709 NTAPI /* ReactOS Change: GCC Does not support STDCALL by default */
3712  PIRP Irp,
3713  PVOID Context
3714  )
3715 
3716 /*++
3717 
3718 Routine Description:
3719 
3720  This is the completion routine for all asynchronous reads
3721  started via CdSingleAsynch.
3722 
3723 Arguments:
3724 
3725  DeviceObject - Pointer to the file system device object.
3726 
3727  Irp - Pointer to the Irp for this request. (This Irp will no longer
3728  be accessible after this routine returns.)
3729 
3730  Context - The context parameter which was specified in the call to
3731  CdSingleAsynch.
3732 
3733 Return Value:
3734 
3735  Currently always returns STATUS_SUCCESS.
3736 
3737 --*/
3738 
3739 {
3740  PCD_IO_CONTEXT IoContext = Context;
3741 
3743 
3744  _Analysis_assume_(IoContext != NULL);
3746 
3747  //
3748  // Update the information field with the correct value for bytes read.
3749  //
3750 
3751  Irp->IoStatus.Information = 0;
3752 
3753  if (NT_SUCCESS( Irp->IoStatus.Status )) {
3754 
3755  Irp->IoStatus.Information = IoContext->RequestedByteCount;
3756  }
3757 
3758  //
3759  // Mark the Irp pending
3760  //
3761 
3762  IoMarkIrpPending( Irp );
3763 
3764  //
3765  // Now release the resource
3766  //
3767 
3769  ExReleaseResourceForThreadLite( IoContext->Resource, IoContext->ResourceThreadId );
3770 
3771  //
3772  // and finally, free the context record.
3773  //
3774 
3775  CdFreeIoContext( IoContext );
3776  return STATUS_SUCCESS;
3777 
3778 }
3779 
3780 
3781 //
3782 // Local support routine
3783 //
3784 
3787 VOID
3788 CdReadAudioSystemFile (
3789  _In_ PIRP_CONTEXT IrpContext,
3790  _In_ PFCB Fcb,
3793  _Out_writes_bytes_(ByteCount) PVOID SystemBuffer
3794  )
3795 
3796 /*++
3797 
3798 Routine Description:
3799 
3800  This routine is called to read the pseudo root directory and path
3801  table for a music disk. We build the individual elements on the
3802  stack and copy into the cache buffer.
3803 
3804 Arguments:
3805 
3806  Fcb - Fcb representing the file to read.
3807 
3808  StartingOffset - Logical offset in the file to read from.
3809 
3810  ByteCount - Number of bytes to read.
3811 
3812  SystemBuffer - Pointer to buffer to fill in. This will always be page
3813  aligned.
3814 
3815 Return Value:
3816 
3817  None.
3818 
3819 --*/
3820 
3821 {
3822  PRAW_PATH_ISO RawPath;
3823  PRAW_DIRENT RawDirent;
3824 
3825  ULONG CurrentTrack;
3827  ULONG EntryCount;
3828  UCHAR TrackOnes;
3829  UCHAR TrackTens;
3830  PTRACK_DATA ThisTrack;
3831 
3832  LONGLONG CurrentOffset;
3833 
3834  PVOID CurrentSector;
3835 
3836  PSYSTEM_USE_XA SystemUse;
3837 
3839 
3840  UCHAR LocalBuffer[FIELD_OFFSET( RAW_DIRENT, FileId ) + 12];
3841 
3842  PAGED_CODE();
3843 
3844  //
3845  // If this is the path table then we just need a single entry.
3846  //
3847 
3849 
3850  //
3851  // Sanity check that the offset is zero.
3852  //
3853 
3854  NT_ASSERT( StartingOffset == 0 );
3855 
3856  //
3857  // Store a pseudo path entry in our local buffer.
3858  //
3859 
3860  RawPath = (PRAW_PATH_ISO) LocalBuffer;
3861 
3862  RtlZeroMemory( RawPath, sizeof( LocalBuffer ));
3863 
3864  RawPath->DirIdLen = 1;
3865  RawPath->ParentNum = 1;
3866  RawPath->DirId[0] = '\0';
3867 
3868  //
3869  // Now copy to the user's buffer.
3870  //
3871 
3872  BytesToCopy = FIELD_OFFSET( RAW_PATH_ISO, DirId ) + 2;
3873 
3874  if (BytesToCopy > ByteCount) {
3875 
3877  }
3878 
3879  RtlCopyMemory( SystemBuffer,
3880  RawPath,
3881  BytesToCopy );
3882 
3883  //
3884  // We need to deal with the multiple sector case for the root directory.
3885  //
3886 
3887  } else {
3888 
3889  //
3890  // Initialize the first track to return to our caller.
3891  //
3892 
3893  CurrentTrack = 0;
3894 
3895  //
3896  // If the offset is zero then store the entries for the self and parent
3897  // entries.
3898  //
3899 
3900  if (StartingOffset == 0) {
3901 
3902  RawDirent = SystemBuffer;
3903 
3904  //
3905  // Clear all of the fields initially.
3906  //
3907 
3908  RtlZeroMemory( RawDirent, FIELD_OFFSET( RAW_DIRENT, FileId ));
3909 
3910  //
3911  // Now fill in the interesting fields.
3912  //
3913 
3914  RawDirent->DirLen = FIELD_OFFSET( RAW_DIRENT, FileId ) + 1;
3915  RawDirent->FileIdLen = 1;
3916  RawDirent->FileId[0] = '\0';
3917  SetFlag( RawDirent->FlagsISO, CD_ATTRIBUTE_DIRECTORY );
3918 
3919  //
3920  // Set the time stamp to be Jan 1, 1995
3921  //
3922 
3923  RawDirent->RecordTime[0] = 95;
3924  RawDirent->RecordTime[1] = 1;
3925  RawDirent->RecordTime[2] = 1;
3926 
3927  SectorOffset = RawDirent->DirLen;
3928 
3929  RawDirent = Add2Ptr( RawDirent, SectorOffset, PRAW_DIRENT );
3930 
3931  //
3932  // Clear all of the fields initially.
3933  //
3934 
3935  RtlZeroMemory( RawDirent, FIELD_OFFSET( RAW_DIRENT, FileId ));
3936 
3937  //
3938  // Now fill in the interesting fields.
3939  //
3940 
3941  RawDirent->DirLen = FIELD_OFFSET( RAW_DIRENT, FileId ) + 1;
3942  RawDirent->FileIdLen = 1;
3943  RawDirent->FileId[0] = '\1';
3944  SetFlag( RawDirent->FlagsISO, CD_ATTRIBUTE_DIRECTORY );
3945 
3946  //
3947  // Set the time stamp to be Jan 1, 1995
3948  //
3949 
3950  RawDirent->RecordTime[0] = 95;
3951  RawDirent->RecordTime[1] = 1;
3952  RawDirent->RecordTime[2] = 1;
3953 
3954  SectorOffset += RawDirent->DirLen;
3955  EntryCount = 2;
3956 
3957  //
3958  // Otherwise compute the starting track to write to the buffer.
3959  //
3960 
3961  } else {
3962 
3963  //
3964  // Count the tracks in each preceding sector.
3965  //
3966 
3967  CurrentOffset = 0;
3968 
3969  do {
3970 
3971  CurrentTrack += CdAudioDirentsPerSector;
3972  CurrentOffset += SECTOR_SIZE;
3973 
3974  } while (CurrentOffset < StartingOffset);
3975 
3976  //
3977  // Bias the track count to reflect the two default entries.
3978  //
3979 
3980  CurrentTrack -= 2;
3981 
3982  SectorOffset = 0;
3983  EntryCount = 0;
3984  }
3985 
3986  //
3987  // We now know the first track to return as well as where we are in
3988  // the current sector. We will walk through sector by sector adding
3989  // the entries for the separate tracks in the TOC. We will zero
3990  // any sectors or partial sectors without data.
3991  //
3992 
3993  CurrentSector = SystemBuffer;
3995 
3996  //
3997  // Loop for each sector.
3998  //
3999 
4000  do {
4001 
4002  //
4003  // Add entries until we reach our threshold for each sector.
4004  //
4005 
4006  do {
4007 
4008  //
4009  // If we are beyond the entries in the TOC then exit.
4010  //
4011 
4012  if (CurrentTrack >= IrpContext->Vcb->TrackCount) {
4013 
4014  break;
4015  }
4016 
4017  ThisTrack = &IrpContext->Vcb->CdromToc->TrackData[CurrentTrack];
4018 
4019  //
4020  // Point to the current position in the buffer.
4021  //
4022 
4023  RawDirent = Add2Ptr( CurrentSector, SectorOffset, PRAW_DIRENT );
4024 
4025  //
4026  // Clear all of the fields initially.
4027  //
4028 
4029  RtlZeroMemory( RawDirent, CdAudioDirentSize );
4030 
4031  //
4032  // Now fill in the interesting fields.
4033  //
4034 
4035  RawDirent->DirLen = (UCHAR) CdAudioDirentSize;
4036  RawDirent->FileIdLen = CdAudioFileNameLength;
4037 
4038  RtlCopyMemory( RawDirent->FileId,
4041 
4042  //
4043  // Set the time stamp to be Jan 1, 1995 00:00
4044  //
4045 
4046  RawDirent->RecordTime[0] = 95;
4047  RawDirent->RecordTime[1] = 1;
4048  RawDirent->RecordTime[2] = 1;
4049 
4050  //
4051  // Put the track number into the file name.
4052  //
4053 
4054  TrackTens = TrackOnes = ThisTrack->TrackNumber;
4055 
4056  TrackOnes = (TrackOnes % 10) + '0';
4057 
4058  TrackTens /= 10;
4059  TrackTens = (TrackTens % 10) + '0';
4060 
4061  RawDirent->FileId[AUDIO_NAME_TENS_OFFSET] = TrackTens;
4062  RawDirent->FileId[AUDIO_NAME_ONES_OFFSET] = TrackOnes;
4063 
4064  SystemUse = Add2Ptr( RawDirent, CdAudioSystemUseOffset, PSYSTEM_USE_XA );
4065 
4066  SystemUse->Attributes = SYSTEM_USE_XA_DA;
4067  SystemUse->Signature = SYSTEM_XA_SIGNATURE;
4068 
4069  //
4070  // Store the track number as the file number.
4071  //
4072 
4073  SystemUse->FileNumber = (UCHAR) CurrentTrack;
4074 
4075  EntryCount += 1;
4077  CurrentTrack += 1;
4078 
4079  } while (EntryCount < CdAudioDirentsPerSector);
4080 
4081  //
4082  // Zero the remaining portion of this buffer.
4083  //
4084 
4085  RtlZeroMemory( Add2Ptr( CurrentSector, SectorOffset, PVOID ),
4087 
4088  //
4089  // Prepare for the next sector.
4090  //
4091 
4092  EntryCount = 0;
4094  SectorOffset = 0;
4095  CurrentSector = Add2Ptr( CurrentSector, SECTOR_SIZE, PVOID );
4096 
4097  } while (BytesToCopy <= ByteCount);
4098  }
4099 
4100  return;
4101 }
4102 
4103 
4104 NTSTATUS
4106  _In_ PIRP_CONTEXT IrpContext,
4107  _Inout_ PIRP Irp,
4109  )
4110 
4111 /*++
4112 
4113 Routine Description:
4114 
4115  This routine is called when we need to send a flush to a device but
4116  we don't have a flush Irp. What this routine does is make a copy
4117  of its current Irp stack location, but changes the Irp Major code
4118  to a IRP_MJ_FLUSH_BUFFERS amd then send it down, but cut it off at
4119  the knees in the completion routine, fix it up and return to the
4120  user as if nothing had happened.
4121 
4122 Arguments:
4123 
4124  Irp - The Irp to hijack
4125 
4126  TargetDeviceObject - The device to send the request to.
4127 
4128 Return Value:
4129 
4130  NTSTATUS - The Status from the flush in case anybody cares.
4131 
4132 --*/
4133 
4134 {
4135  KEVENT Event;
4136  NTSTATUS Status;
4137  PIO_STACK_LOCATION NextIrpSp;
4138 
4139  PAGED_CODE();
4140 
4141  UNREFERENCED_PARAMETER( IrpContext );
4142 
4143  //
4144  // Get the next stack location, and copy over the stack location
4145  //
4146 
4147  NextIrpSp = IoGetNextIrpStackLocation( Irp );
4148 
4149  *NextIrpSp = *IoGetCurrentIrpStackLocation( Irp );
4150 
4151  NextIrpSp->MajorFunction = IRP_MJ_FLUSH_BUFFERS;
4152  NextIrpSp->MinorFunction = 0;
4153 
4154  //
4155  // Set up the completion routine
4156  //
4157 
4159 
4162  &Event,
4163  TRUE,
4164  TRUE,
4165  TRUE );
4166 
4167  //
4168  // Send the request.
4169  //
4170 
4172 
4173  if (Status == STATUS_PENDING) {
4174 
4176 
4177  Status = Irp->IoStatus.Status;
4178  }
4179 
4180  //
4181  // If the driver doesn't support flushes, return SUCCESS.
4182  //
4183 
4185 
4187  }
4188 
4189  Irp->IoStatus.Status = 0;
4190  Irp->IoStatus.Information = 0;
4191 
4192  return Status;
4193 }
4194 
4195 
_Requires_lock_held_(_Global_critical_region_)
Definition: deviosup.c:102
signed char * PCHAR
Definition: retypes.h:7
ULONG RawSectors
Definition: cdstruc.h:1769
UCHAR TrackAddress[4]
Definition: cdstruc.h:1790
#define CdConvertCacheToShared(IC)
Definition: cdprocs.h:975
Definition: bidi.c:477
NTSTATUS NTAPI CdMultiAsyncCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: deviosup.c:3526
ULONG_PTR ERESOURCE_THREAD
Definition: extypes.h:208
#define VCB_STATE_AUDIO_DISK
Definition: cdstruc.h:718
PCDROM_TOC_LARGE CdromToc
Definition: cdstruc.h:643
_In_ PFCB _In_ LONGLONG _Out_ PLONGLONG DiskOffset
Definition: cdprocs.h:151
#define AssertVerifyDeviceIrp(I)
Definition: cdprocs.h:1821
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define MAX_PARALLEL_IOS
Definition: deviosup.c:96
#define SectorAlign(L)
Definition: cdprocs.h:1590
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
UCHAR DirLen
Definition: cd.h:332
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
NTSTATUS FASTCALL CdPerformDevIoCtrl(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT Device, _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _In_ BOOLEAN OverrideVerify, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: deviosup.c:1446
struct _KEVENT * PKEVENT
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
USHORT Attributes
Definition: cd.h:493
#define Add2Ptr(PTR, INC)
#define SECTOR_MASK
Definition: cd.h:28
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG IoControlCode
Definition: fltkernel.h:1383
struct _IO_RUN IO_RUN
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2020
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
_In_ PFCB _In_ LONGLONG StartingOffset
Definition: cdprocs.h:282
#define IRP_MJ_FLUSH_BUFFERS
VOID NTAPI IoReuseIrp(IN OUT PIRP Irp, IN NTSTATUS Status)
Definition: irp.c:1971
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define IRP_CONTEXT_FLAG_ALLOC_IO
Definition: cdstruc.h:1227
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:63
PIRP NTAPI IoBuildSynchronousFsdRequest(IN ULONG MajorFunction, IN PDEVICE_OBJECT DeviceObject, IN PVOID Buffer, IN ULONG Length, IN PLARGE_INTEGER StartingOffset, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:1069
NTSTATUS NTAPI CdSingleAsyncCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: deviosup.c:3710
TRACK_DATA TrackData[MAXIMUM_NUMBER_TRACKS_LARGE]
Definition: cdstruc.h:455
NTSTATUS CdCreateUserMdl(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG BufferLength, _In_ BOOLEAN RaiseOnError, _In_ LOCK_OPERATION Operation)
Definition: deviosup.c:1221
_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
NTSTATUS CdHijackIrpAndFlushDevice(_In_ PIRP_CONTEXT IrpContext, _Inout_ PIRP Irp, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: deviosup.c:4105
#define SafeNodeType(Ptr)
Definition: nodetype.h:54
unsigned char * PUCHAR
Definition: retypes.h:3
AUDIO_PLAY_HEADER * PAUDIO_PLAY_HEADER
Definition: cdstruc.h:1794
#define SECTOR_SHIFT
Definition: cd.h:32
#define _In_reads_bytes_opt_(size)
Definition: no_sal2.h:230
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:428
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID _In_ ULONG _In_ BOOLEAN InternalDeviceIoControl
Definition: iofuncs.h:713
LONG CdAudioPlayHeader[]
Definition: cddata.c:102
#define CdMapUserBuffer(IC, UB)
Definition: cdprocs.h:376
LONG NTSTATUS
Definition: precomp.h:26
#define SwapCopyUchar4(Dst, Src)
Definition: cdprocs.h:1729
#define AUDIO_NAME_TENS_OFFSET
Definition: cddata.h:81
LONG CdXAAudioPhileHeader[]
Definition: cddata.c:136
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Lbn
Definition: fsrtlfuncs.h:479
ULONG SectorCount
Definition: ntddcdrm.h:353
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG _In_ ULONG OutputBufferLength
Definition: fltkernel.h:1374
#define STATUS_INVALID_DEVICE_REQUEST
Definition: udferr_usr.h:138
KEVENT SyncEvent
Definition: cdstruc.h:1353
Definition: cdstruc.h:504
VOID CdMultipleXAAsync(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG RunCount, _Inout_ PIO_RUN IoRuns, _In_ PRAW_READ_INFO RawReads, _In_ TRACK_MODE_TYPE TrackMode)
Definition: deviosup.c:3044
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
PVPB Vpb
Definition: cdstruc.h:517
#define SYSTEM_USE_XA_DA
Definition: cd.h:518
UCHAR Address[4]
Definition: ntddcdrm.h:108
ULONG VcbState
Definition: cdstruc.h:546
ULONG CdAudioDirentSize
Definition: cddata.c:78
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define CDFS_NTC_FCB_PATH_TABLE
Definition: nodetype.h:29
LONG NTAPI KeSetEvent(IN PKEVENT Event, IN KPRIORITY Increment, IN BOOLEAN Wait)
Definition: eventobj.c:159
NTSTATUS NTAPI KeWaitForSingleObject(IN PVOID Object, IN KWAIT_REASON WaitReason, IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Timeout OPTIONAL)
Definition: wait.c:416
__inline TRACK_MODE_TYPE CdFileTrackMode(_In_ PFCB Fcb)
Definition: deviosup.c:258
#define FASTCALL
Definition: nt_native.h:50
VOID CdLbnToMmSsFf(_In_ ULONG Blocks, _Out_writes_(3) PUCHAR Msf)
#define CDFS_NTC_FCB_INDEX
Definition: nodetype.h:30
#define PAGED_CODE()
Definition: video.h:57
CHAR InputBuffer[80]
Definition: conmgr.c:33
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3149
NTSTATUS CdPerformDevIoCtrlEx(_In_ PIRP_CONTEXT IrpContext, _In_ ULONG IoControlCode, _In_ PDEVICE_OBJECT Device, _In_reads_bytes_opt_(InputBufferLength) PVOID InputBuffer, _In_ ULONG InputBufferLength, _Out_writes_bytes_opt_(OutputBufferLength) PVOID OutputBuffer, _In_ ULONG OutputBufferLength, _In_ BOOLEAN InternalDeviceIoControl, _In_ BOOLEAN OverrideVerify, _Out_opt_ PIO_STATUS_BLOCK Iosb)
Definition: deviosup.c:1329
_SEH2_TRY
Definition: create.c:4250
RAW_PATH_ISO * PRAW_PATH_ISO
Definition: cd.h:428
#define IOCTL_CDROM_RAW_READ
Definition: ntddcdrm.h:64
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:515
#define _Out_writes_(size)
Definition: no_sal2.h:367
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
UCHAR FileIdLen
Definition: cd.h:345
#define _Analysis_assume_lock_held_(lock)
Definition: no_sal2.h:682
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
#define ASSERT_IRP_CONTEXT(IC)
Definition: cddata.h:249
VOID CdWaitSync(_In_ PIRP_CONTEXT IrpContext)
Definition: deviosup.c:3399
#define SECTOR_SIZE
Definition: winldr.h:34
ULONG TransferByteCount
Definition: deviosup.c:72
long LONG
Definition: pedump.c:60
_In_ ULONG BufferLength
Definition: usbdlib.h:225
USHORT ParentNum
Definition: cd.h:424
#define CD_ATTRIBUTE_DIRECTORY
Definition: cd.h:354
__volatile LONG IrpCount
Definition: cdstruc.h:1331
#define RawSectorAlign(B)
Definition: cdprocs.h:1664
#define CdReleaseCache(IC)
Definition: cdprocs.h:972
USHORT Signature
Definition: cd.h:499
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:434
ULONG CdAudioSystemUseOffset
Definition: cddata.c:80
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
ULONG RequestedByteCount
Definition: cdstruc.h:1346
#define SectorOffset(L)
Definition: cdprocs.h:1632
unsigned char BOOLEAN
enum _TRACK_MODE_TYPE TRACK_MODE_TYPE
#define _Out_writes_bytes_opt_(a)
Definition: btrfs_drv.h:171
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define _Out_writes_bytes_(size)
Definition: no_sal2.h:370
_At_(*)(_In_ PWSK_CLIENT Client, _In_opt_ PUNICODE_STRING NodeName, _In_opt_ PUNICODE_STRING ServiceName, _In_opt_ ULONG NameSpace, _In_opt_ GUID *Provider, _In_opt_ PADDRINFOEXW Hints, _Outptr_ PADDRINFOEXW *Result, _In_opt_ PEPROCESS OwningProcess, _In_opt_ PETHREAD OwningThread, _Inout_ PIRP Irp Result)(Mem)) NTSTATUS(WSKAPI *PFN_WSK_GET_ADDRESS_INFO
Definition: wsk.h:426
#define _Out_
Definition: no_sal2.h:323
#define _At_(target, annos)
Definition: no_sal2.h:11
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1779
#define FCB_STATE_MODE2FORM2_FILE
Definition: cdstruc.h:1050
struct __RAW_READ_INFO RAW_READ_INFO
Definition: bufpool.h:45
ULONG StartingSector
Definition: cdstruc.h:1788
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
return Found
Definition: dirsup.c:1270
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
Definition: irp.c:1925
LONG ChunkSize
Definition: cdstruc.h:1759
LONGLONG DiskOffset
Definition: deviosup.c:41
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
PUCHAR SectorCacheBuffer
Definition: cdstruc.h:687
#define CdAcquireCacheForUpdate(IC)
Definition: cdprocs.h:969
#define try_leave(S)
Definition: cdprocs.h:2190
CHAR CdAudioFileName[]
Definition: cddata.c:76
UCHAR FileId[MAX_FILE_ID_LENGTH]
Definition: cd.h:346
int64_t LONGLONG
Definition: typedefs.h:66
#define _Out_opt_
Definition: no_sal2.h:339
TRACK_MODE_TYPE TrackMode
Definition: ntddcdrm.h:354
return Iosb
Definition: create.c:4426
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
ULONG CdAudioDirentsPerSector
Definition: cddata.c:79
#define LlBytesFromSectors(L)
Definition: cdprocs.h:1624
#define try_return(S)
Definition: cdprocs.h:2189
#define CdNonPagedPool
Definition: cdprocs.h:1387
char CCHAR
Definition: typedefs.h:50
#define CdUnlockVcb(IC, V)
Definition: cdprocs.h:1033
#define ARGUMENT_PRESENT(ArgumentPointer)
__volatile NTSTATUS Status
Definition: cdstruc.h:1333
PERESOURCE Resource
Definition: cdstruc.h:1344
#define Vcb
Definition: cdprocs.h:1425
#define FCB_STATE_DA_FILE
Definition: cdstruc.h:1052
PMDL TransferMdl
Definition: deviosup.c:84
static const UCHAR Index[8]
Definition: usbohci.c:18
ULONG MaximumPhysicalPages
Definition: cdstruc.h:666
#define Min(a, b)
Definition: cdprocs.h:66
#define _Inout_
Definition: no_sal2.h:244
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
#define CdLockVcb(IC, V)
Definition: cdprocs.h:1028
#define SYSTEM_XA_SIGNATURE
Definition: cd.h:520
#define CdFreeIoContext(IO)
Definition: cdprocs.h:1354
unsigned char UCHAR
Definition: xmlstorage.h:181
PIRP MasterIrp
Definition: cdstruc.h:1332
#define SectorTruncate(L)
Definition: cdprocs.h:1598
#define InterlockedDecrement
Definition: armddk.h:52
Definition: ntddcdrm.h:348
PVOID UserBuffer
Definition: deviosup.c:49
struct _RIFF_HEADER RIFF_HEADER
#define VOID
Definition: acefi.h:82
ULONG TransferBufferOffset
Definition: deviosup.c:73
NTSTATUS NTAPI CdMultiSyncCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: deviosup.c:3438
ERESOURCE_THREAD ResourceThreadId
Definition: cdstruc.h:1345
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
VOID NTAPI ExSetResourceOwnerPointer(IN PERESOURCE Resource, IN PVOID OwnerPointer)
Definition: resource.c:2045
UCHAR RecordTime[6]
Definition: cd.h:338
UCHAR CdAudioFileNameLength
Definition: cddata.c:77
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
#define _In_reads_bytes_(size)
Definition: no_sal2.h:229
PVOID XASector
Definition: cdstruc.h:582
#define InterlockedExchange
Definition: armddk.h:54
_When_(SafeNodeType(Fcb) !=CDFS_NTC_FCB_PATH_TABLE &&StartingOffset==0, _At_(ByteCount, _In_range_(>=, CdAudioDirentSize+sizeof(RAW_DIRENT))))
Definition: deviosup.c:3785
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1060
UCHAR XAFileNumber
Definition: cdstruc.h:995
Status
Definition: gdiplustypes.h:24
#define ASSERT_IRP(I)
Definition: cddata.h:251
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
LONGLONG XADiskOffset
Definition: cdstruc.h:583
static INLINE ULONG SectorsFromLlBytes(ULONGLONG Bytes)
Definition: cdprocs.h:1617
#define _In_
Definition: no_sal2.h:204
#define AUDIO_NAME_ONES_OFFSET
Definition: cddata.h:80
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1560
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define CD_SEC_CACHE_CHUNKS
Definition: cdstruc.h:466
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4424
PIRP SavedIrp
Definition: deviosup.c:91
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:161
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define InterlockedIncrement
Definition: armddk.h:53
#define CdFreePool(x)
Definition: cdprocs.h:2200
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
enum _LOCK_OPERATION LOCK_OPERATION
unsigned short USHORT
Definition: pedump.c:61
USHORT TrackNumber
Definition: cdstruc.h:1786
#define FCB_STATE_MODE2_FILE
Definition: cdstruc.h:1051
PVOID TransferBuffer
Definition: deviosup.c:71
#define CdRaiseStatus(IC, S)
Definition: cdprocs.h:1869
UCHAR TrackNumber
Definition: ntddcdrm.h:106
ULONG MaximumTransferRawSectors
Definition: cdstruc.h:665
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4157
#define IRP_CONTEXT_FLAG_TOP_LEVEL
Definition: cdstruc.h:1223
#define CD_SEC_CHUNK_BLOCKS
Definition: cdstruc.h:467
#define BytesFromSectors(L)
Definition: cdprocs.h:1606
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
USHORT Attributes
Definition: cdstruc.h:1764
_SEH2_FINALLY
Definition: create.c:4395
unsigned int * PULONG
Definition: retypes.h:1
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define CdAcquireCacheForRead(IC)
Definition: cdprocs.h:966
IO_COMPLETION_ROUTINE * PIO_COMPLETION_ROUTINE
Definition: iotypes.h:2479
#define TAG_IO_BUFFER
Definition: cdprocs.h:87
PIRP NTAPI IoBuildDeviceIoControlRequest(IN ULONG IoControlCode, IN PDEVICE_OBJECT DeviceObject, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PVOID OutputBuffer, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN PKEVENT Event, IN PIO_STATUS_BLOCK IoStatusBlock)
Definition: irp.c:881
#define IRP_MJ_READ
Definition: rdpdr.c:46
NTSTATUS NTAPI CdSingleSyncCompletionRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID Context)
Definition: deviosup.c:3646
#define SectorsFromBytes(L)
Definition: cdprocs.h:1610
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
IO_RUN * PIO_RUN
Definition: deviosup.c:94
IO_COMPLETION_ROUTINE CdSyncCompletionRoutine
Definition: deviosup.c:2388
UCHAR FileNumber
Definition: cdstruc.h:1766
UCHAR TrackLength[4]
Definition: cdstruc.h:1791
struct tagContext Context
Definition: acpixf.h:1012
_In_ PIRP _In_opt_ PVOID _In_opt_ POPLOCK_WAIT_COMPLETE_ROUTINE CompletionRoutine
Definition: fsrtlfuncs.h:673
_Inout_ PFCB _In_ BOOLEAN RaiseOnError
Definition: cdprocs.h:1214
unsigned int ULONG
Definition: retypes.h:1
#define RAW_SECTOR_SIZE
Definition: mcicda.c:50
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define CdLockUserBuffer(IC, BL, OP)
Definition: cdprocs.h:398
#define ULONG_PTR
Definition: config.h:101
_In_ FLT_SET_CONTEXT_OPERATION Operation
Definition: fltkernel.h:1468
PVCB Vcb
Definition: cdstruc.h:939
#define CdNormalizeAndRaiseStatus(IC, S)
Definition: cdprocs.h:1870
LONG CdXAFileHeader[]
Definition: cddata.c:165
VOID NTAPI ExReleaseResourceForThreadLite(IN PERESOURCE Resource, IN ERESOURCE_THREAD Thread)
Definition: resource.c:1844
LARGE_INTEGER DiskOffset
Definition: ntddcdrm.h:352
ULONG SerialNumber
Definition: iotypes.h:173
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
#define LlSectorTruncate(L)
Definition: cdprocs.h:1602
UCHAR FlagsISO
Definition: cd.h:340
BOOLEAN CdReadSectors(_In_ PIRP_CONTEXT IrpContext, _In_ LONGLONG StartingOffset, _In_ ULONG ByteCount, _In_ BOOLEAN ReturnError, _Out_writes_bytes_(ByteCount) PVOID Buffer, _In_ PDEVICE_OBJECT TargetDeviceObject)
Definition: deviosup.c:1080
#define _In_range_(lb, ub)
Definition: no_sal2.h:227
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2771
_In_ PFCB Fcb
Definition: cdprocs.h:151
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
IN OUT PVCB IN PDEVICE_OBJECT TargetDeviceObject
Definition: fatprocs.h:1664
return STATUS_SUCCESS
Definition: btrfs.c:2725
PVOID TransferVirtualAddress
Definition: deviosup.c:85
IoMarkIrpPending(Irp)
UCHAR DirIdLen
Definition: cd.h:421
UCHAR FileNumber
Definition: cd.h:505
ULONG FcbState
Definition: cdstruc.h:977
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2632
BOOLEAN CdFinishBuffers(_In_ PIRP_CONTEXT IrpContext, _Inout_ PIO_RUN IoRuns, _In_ ULONG RunCount, _In_ BOOLEAN FinalCleanup, _In_ BOOLEAN SaveXABuffer)
Definition: deviosup.c:2219
LONGLONG QuadPart
Definition: typedefs.h:112
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define STATUS_CANT_WAIT
Definition: ntstatus.h:438
UCHAR DirId[MAX_FILE_ID_LENGTH]
Definition: cd.h:425
#define NT_ASSERT
Definition: rtlfuncs.h:3312
USHORT XAAttributes
Definition: cdstruc.h:989
ULONG DiskByteCount
Definition: deviosup.c:42