ReactOS  0.4.15-dev-439-g292f67a
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 Fat.
12 
13 
14 --*/
15 
16 #include "fatprocs.h"
17 
18 //
19 // The Bug check file id for this module
20 //
21 
22 #define BugCheckFileId (FAT_BUG_CHECK_DEVIOSUP)
23 
24 //
25 // Local debug trace level
26 //
27 
28 #define Dbg (DEBUG_TRACE_DEVIOSUP)
29 
30 #define CollectDiskIoStats(VCB,FUNCTION,IS_USER_IO,COUNT) { \
31  PFILESYSTEM_STATISTICS Stats = &(VCB)->Statistics[KeGetCurrentProcessorNumber() % FatData.NumberProcessors].Common; \
32  if (IS_USER_IO) { \
33  if ((FUNCTION) == IRP_MJ_WRITE) { \
34  Stats->UserDiskWrites += (COUNT); \
35  } else { \
36  Stats->UserDiskReads += (COUNT); \
37  } \
38  } else { \
39  if ((FUNCTION) == IRP_MJ_WRITE) { \
40  Stats->MetaDataDiskWrites += (COUNT); \
41  } else { \
42  Stats->MetaDataDiskReads += (COUNT); \
43  } \
44  } \
45 }
46 
47 typedef struct _FAT_SYNC_CONTEXT {
48 
49  //
50  // Io status block for the request
51  //
52 
54 
55  //
56  // Event to be signaled when the request completes
57  //
58 
60 
62 
63 
64 //
65 // Completion Routine declarations
66 //
67 
68 IO_COMPLETION_ROUTINE FatMultiSyncCompletionRoutine;
69 
71 NTAPI
74  _In_ PIRP Irp,
75  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
76  );
77 
78 IO_COMPLETION_ROUTINE FatMultiAsyncCompletionRoutine;
79 
81 NTAPI
84  _In_ PIRP Irp,
85  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
86  );
87 
88 IO_COMPLETION_ROUTINE FatSpecialSyncCompletionRoutine;
89 
91 NTAPI
94  _In_ PIRP Irp,
95  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
96  );
97 
98 IO_COMPLETION_ROUTINE FatSingleSyncCompletionRoutine;
99 
100 NTSTATUS
101 NTAPI
104  _In_ PIRP Irp,
105  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
106  );
107 
108 IO_COMPLETION_ROUTINE FatSingleAsyncCompletionRoutine;
109 
110 NTSTATUS
111 NTAPI
114  _In_ PIRP Irp,
115  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
116  );
117 
118 IO_COMPLETION_ROUTINE FatPagingFileCompletionRoutine;
119 
120 NTSTATUS
121 NTAPI
124  _In_ PIRP Irp,
125  _In_reads_opt_(_Inexpressible_("varies")) PVOID MasterIrp
126  );
127 
129 
130 NTSTATUS
131 NTAPI
134  _In_ PIRP Irp,
135  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
136  );
137 
138 VOID
140  IN PIRP_CONTEXT IrpContext,
141  IN PVCB Vcb,
142  IN PUCHAR Buffer,
143  IN LBO Lbo,
145  IN PIRP Irp
146  );
147 
148 //
149 // The following macro decides whether to send a request directly to
150 // the device driver, or to other routines. It was meant to
151 // replace IoCallDriver as transparently as possible. It must only be
152 // called with a read or write Irp.
153 //
154 // NTSTATUS
155 // FatLowLevelReadWrite (
156 // PIRP_CONTEXT IrpContext,
157 // PDEVICE_OBJECT DeviceObject,
158 // PIRP Irp,
159 // PVCB Vcb
160 // );
161 //
162 
163 #define FatLowLevelReadWrite(IRPCONTEXT,DO,IRP,VCB) ( \
164  IoCallDriver((DO),(IRP)) \
165 )
166 
167 //
168 // The following macro handles completion-time zeroing of buffers.
169 //
170 
171 #define FatDoCompletionZero( I, C ) \
172  if ((C)->ZeroMdl) { \
173  NT_ASSERT( (C)->ZeroMdl->MdlFlags & (MDL_MAPPED_TO_SYSTEM_VA | \
174  MDL_SOURCE_IS_NONPAGED_POOL));\
175  if (NT_SUCCESS((I)->IoStatus.Status)) { \
176  RtlZeroMemory( (C)->ZeroMdl->MappedSystemVa, \
177  (C)->ZeroMdl->ByteCount ); \
178  } \
179  IoFreeMdl((C)->ZeroMdl); \
180  (C)->ZeroMdl = NULL; \
181  }
182 
183 #if (NTDDI_VERSION >= NTDDI_WIN8)
184 #define FatUpdateIOCountersPCW(IsAWrite,Count) \
185  FsRtlUpdateDiskCounters( ((IsAWrite) ? 0 : (Count) ), \
186  ((IsAWrite) ? (Count) : 0) )
187 #else
188 #define FatUpdateIOCountersPCW(IsAWrite,Count)
189 #endif
190 
191 #ifdef ALLOC_PRAGMA
192 #pragma alloc_text(PAGE, FatMultipleAsync)
193 #pragma alloc_text(PAGE, FatSingleAsync)
194 #pragma alloc_text(PAGE, FatSingleNonAlignedSync)
195 #pragma alloc_text(PAGE, FatWaitSync)
196 #pragma alloc_text(PAGE, FatLockUserBuffer)
197 #pragma alloc_text(PAGE, FatBufferUserBuffer)
198 #pragma alloc_text(PAGE, FatMapUserBuffer)
199 #pragma alloc_text(PAGE, FatNonCachedIo)
200 #pragma alloc_text(PAGE, FatNonCachedNonAlignedRead)
201 #pragma alloc_text(PAGE, FatPerformDevIoCtrl)
202 #endif
203 
204 typedef struct FAT_PAGING_FILE_CONTEXT {
208 
209 
210 VOID
212  IN PIRP Irp,
213  IN PFCB Fcb
214  )
215 
216 /*++
217 
218 Routine Description:
219 
220  This routine performs the non-cached disk io described in its parameters.
221  This routine nevers blocks, and should only be used with the paging
222  file since no completion processing is performed.
223 
224 Arguments:
225 
226  Irp - Supplies the requesting Irp.
227 
228  Fcb - Supplies the file to act on.
229 
230 Return Value:
231 
232  None.
233 
234 --*/
235 
236 {
237  //
238  // Declare some local variables for enumeration through the
239  // runs of the file.
240  //
241 
242  VBO Vbo;
244 
245  PMDL Mdl;
246  LBO NextLbo;
247  VBO NextVbo = 0;
248  ULONG NextByteCount;
249  ULONG RemainingByteCount;
250  BOOLEAN MustSucceed;
251 
252  ULONG FirstIndex;
253  ULONG CurrentIndex;
254  ULONG LastIndex;
255 
256  LBO LastLbo;
257  ULONG LastByteCount;
258 
259  BOOLEAN MdlIsReserve = FALSE;
260  BOOLEAN IrpIsMaster = FALSE;
262  LONG IrpCount;
263 
264  PIRP AssocIrp;
266  PIO_STACK_LOCATION NextIrpSp;
267  ULONG BufferOffset;
269 
270 #ifndef __REACTOS__
271  BOOLEAN IsAWrite = FALSE;
272 #endif
273 
274  DebugTrace(+1, Dbg, "FatPagingFileIo\n", 0);
275  DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
276  DebugTrace( 0, Dbg, "Fcb = %p\n", Fcb );
277 
279 
280  //
281  // Initialize some locals.
282  //
283 
284  BufferOffset = 0;
287 
288  Vbo = IrpSp->Parameters.Read.ByteOffset.LowPart;
289  ByteCount = IrpSp->Parameters.Read.Length;
290 #ifndef __REACTOS__
291  IsAWrite = (IrpSp->MajorFunction == IRP_MJ_WRITE);
292 #endif
293 
294  MustSucceed = FatLookupMcbEntry( Fcb->Vcb, &Fcb->Mcb,
295  Vbo,
296  &NextLbo,
297  &NextByteCount,
298  &FirstIndex);
299 
300  //
301  // If this run isn't present, something is very wrong.
302  //
303 
304  if (!MustSucceed) {
305 
306 #ifdef _MSC_VER
307 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
308 #endif
309  FatBugCheck( Vbo, ByteCount, 0 );
310  }
311 
312 #if (NTDDI_VERSION >= NTDDI_WIN8)
313 
314  //
315  // Charge the IO to paging file to current thread
316  //
317 
319 
320  PETHREAD ThreadIssuingIo = PsGetCurrentThread();
321  BOOLEAN IsWriteOperation = FALSE;
322 
323  if (IrpSp->MajorFunction == IRP_MJ_WRITE) {
324  IsWriteOperation = TRUE;
325  }
326 
327  PsUpdateDiskCounters( PsGetThreadProcess( ThreadIssuingIo ),
328  (IsWriteOperation ? 0 : ByteCount ), // bytes to read
329  (IsWriteOperation ? ByteCount : 0), // bytes to write
330  (IsWriteOperation ? 0 : 1), // # of reads
331  (IsWriteOperation ? 1 : 0), // # of writes
332  0 );
333  }
334 #endif
335 
336  // See if the write covers a single valid run, and if so pass
337  // it on.
338  //
339 
340  if ( NextByteCount >= ByteCount ) {
341 
342  DebugTrace( 0, Dbg, "Passing Irp on to Disk Driver\n", 0 );
343 
344  //
345  // Setup the next IRP stack location for the disk driver beneath us.
346  //
347 
348  NextIrpSp = IoGetNextIrpStackLocation( Irp );
349 
350  NextIrpSp->MajorFunction = IrpSp->MajorFunction;
351  NextIrpSp->Parameters.Read.Length = ByteCount;
352  NextIrpSp->Parameters.Read.ByteOffset.QuadPart = NextLbo;
353 
354  //
355  // Since this is Paging file IO, we'll just ignore the verify bit.
356  //
357 
358  SetFlag( NextIrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
359 
360  //
361  // Set up the completion routine address in our stack frame.
362  // This is only invoked on error or cancel, and just copies
363  // the error Status into master irp's iosb.
364  //
365  // If the error implies a media problem, it also enqueues a
366  // worker item to write out the dirty bit so that the next
367  // time we run we will do a autochk /r
368  //
369 
372  Irp,
373  FALSE,
374  TRUE,
375  TRUE );
376 
377  //
378  // Issue the read/write request
379  //
380  // If IoCallDriver returns an error, it has completed the Irp
381  // and the error will be dealt with as a normal IO error.
382  //
383 
385 
386  //
387  // We just issued an IO to the storage stack, update the counters indicating so.
388  //
389 
391 
392  FatUpdateIOCountersPCW( IsAWrite, ByteCount );
393  }
394 
395  DebugTrace(-1, Dbg, "FatPagingFileIo -> VOID\n", 0);
396  return;
397  }
398 
399  //
400  // Find out how may runs there are.
401  //
402 
403  MustSucceed = FatLookupMcbEntry( Fcb->Vcb, &Fcb->Mcb,
404  Vbo + ByteCount - 1,
405  &LastLbo,
406  &LastByteCount,
407  &LastIndex);
408 
409  //
410  // If this run isn't present, something is very wrong.
411  //
412 
413  if (!MustSucceed) {
414 
415 #ifdef _MSC_VER
416 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
417 #endif
418  FatBugCheck( Vbo + ByteCount - 1, 1, 0 );
419  }
420 
421  CurrentIndex = FirstIndex;
422 
423  //
424  // Now set up the Irp->IoStatus. It will be modified by the
425  // multi-completion routine in case of error or verify required.
426  //
427 
428  Irp->IoStatus.Status = STATUS_SUCCESS;
429  Irp->IoStatus.Information = ByteCount;
430 
431  //
432  // Loop while there are still byte writes to satisfy. The way we'll work this
433  // is to hope for the best - one associated IRP per run, which will let us be
434  // completely async after launching all the IO.
435  //
436  // IrpCount will indicate the remaining number of associated Irps to launch.
437  //
438  // All we have to do is make sure IrpCount doesn't hit zero before we're building
439  // the very last Irp. If it is positive when we're done, it means we have to
440  // wait for the rest of the associated Irps to come back before we complete the
441  // master by hand.
442  //
443  // This will keep the master from completing early.
444  //
445 
446  Irp->AssociatedIrp.IrpCount = IrpCount = LastIndex - FirstIndex + 1;
447 
448  while (CurrentIndex <= LastIndex) {
449 
450  //
451  // Reset this for unwinding purposes
452  //
453 
454  AssocIrp = NULL;
455 
456  //
457  // If next run is larger than we need, "ya get what ya need".
458  //
459 
460  if (NextByteCount > ByteCount) {
461  NextByteCount = ByteCount;
462  }
463 
464  RemainingByteCount = 0;
465 
466  //
467  // Allocate and build a partial Mdl for the request.
468  //
469 
470  Mdl = IoAllocateMdl( (PCHAR)Irp->UserBuffer + BufferOffset,
471  NextByteCount,
472  FALSE,
473  FALSE,
474  AssocIrp );
475 
476  if (Mdl == NULL) {
477 
478  //
479  // Pick up the reserve MDL
480  //
481 
483 
484  Mdl = FatReserveMdl;
485  MdlIsReserve = TRUE;
486 
487  //
488  // Trim to fit the size of the reserve MDL.
489  //
490 
491  if (NextByteCount > FAT_RESERVE_MDL_SIZE * PAGE_SIZE) {
492 
493  RemainingByteCount = NextByteCount - FAT_RESERVE_MDL_SIZE * PAGE_SIZE;
494  NextByteCount = FAT_RESERVE_MDL_SIZE * PAGE_SIZE;
495  }
496  }
497 
498  IoBuildPartialMdl( Irp->MdlAddress,
499  Mdl,
500  (PCHAR)Irp->UserBuffer + BufferOffset,
501  NextByteCount );
502 
503  //
504  // Now that we have properly bounded this piece of the transfer, it is
505  // time to read/write it. We can simplify life slightly by always
506  // re-using the master IRP for cases where we use the reserve MDL,
507  // since we'll always be synchronous for those and can use a single
508  // completion context on our local stack.
509  //
510  // We also must prevent ourselves from issuing an associated IRP that would
511  // complete the master UNLESS this is the very last IRP we'll issue.
512  //
513  // This logic looks a bit complicated, but is hopefully understandable.
514  //
515 
516  if (!MdlIsReserve &&
517  (IrpCount != 1 ||
518  (CurrentIndex == LastIndex &&
519  RemainingByteCount == 0))) {
520 
521  AssocIrp = IoMakeAssociatedIrp( Irp, (CCHAR)(DeviceObject->StackSize + 1) );
522  }
523 
524  if (AssocIrp == NULL) {
525 
526  AssocIrp = Irp;
527  IrpIsMaster = TRUE;
528 
529  //
530  // We need to drain the associated Irps so we can reliably figure out if
531  // the master Irp is showing a failed status, in which case we bail out
532  // immediately - as opposed to putting the value in the status field in
533  // jeopardy due to our re-use of the master Irp.
534  //
535 
536  while (Irp->AssociatedIrp.IrpCount != IrpCount) {
537 
539  }
540 
541  //
542  // Note that since we failed to launch this associated Irp, that the completion
543  // code at the bottom will take care of completing the master Irp.
544  //
545 
546  if (!NT_SUCCESS(Irp->IoStatus.Status)) {
547 
548  NT_ASSERT( IrpCount );
549  break;
550  }
551 
552  } else {
553 
554  //
555  // Indicate we used an associated Irp.
556  //
557 
558  IrpCount -= 1;
559  }
560 
561  //
562  // With an associated IRP, we must take over the first stack location so
563  // we can have one to put the completion routine on. When re-using the
564  // master IRP, its already there.
565  //
566 
567  if (!IrpIsMaster) {
568 
569  //
570  // Get the first IRP stack location in the associated Irp
571  //
572 
573  IoSetNextIrpStackLocation( AssocIrp );
574  NextIrpSp = IoGetCurrentIrpStackLocation( AssocIrp );
575 
576  //
577  // Setup the Stack location to describe our read.
578  //
579 
580  NextIrpSp->MajorFunction = IrpSp->MajorFunction;
581  NextIrpSp->Parameters.Read.Length = NextByteCount;
582  NextIrpSp->Parameters.Read.ByteOffset.QuadPart = Vbo;
583 
584  //
585  // We also need the VolumeDeviceObject in the Irp stack in case
586  // we take the failure path.
587  //
588 
589  NextIrpSp->DeviceObject = IrpSp->DeviceObject;
590 
591  } else {
592 
593  //
594  // Save the MDL in the IRP and prepare the stack
595  // context for the completion routine.
596  //
597 
599  Context.RestoreMdl = Irp->MdlAddress;
600  }
601 
602  //
603  // And drop our Mdl into the Irp.
604  //
605 
606  AssocIrp->MdlAddress = Mdl;
607 
608  //
609  // Set up the completion routine address in our stack frame.
610  // For true associated IRPs, this is only invoked on error or
611  // cancel, and just copies the error Status into master irp's
612  // iosb.
613  //
614  // If the error implies a media problem, it also enqueues a
615  // worker item to write out the dirty bit so that the next
616  // time we run we will do a autochk /r
617  //
618 
619  if (IrpIsMaster) {
620 
621  IoSetCompletionRoutine( AssocIrp,
623  &Context,
624  TRUE,
625  TRUE,
626  TRUE );
627 
628  } else {
629 
630  IoSetCompletionRoutine( AssocIrp,
632  Irp,
633  FALSE,
634  TRUE,
635  TRUE );
636  }
637 
638  //
639  // Setup the next IRP stack location for the disk driver beneath us.
640  //
641 
642  NextIrpSp = IoGetNextIrpStackLocation( AssocIrp );
643 
644  //
645  // Since this is paging file IO, we'll just ignore the verify bit.
646  //
647 
648  SetFlag( NextIrpSp->Flags, SL_OVERRIDE_VERIFY_VOLUME );
649 
650  //
651  // Setup the Stack location to do a read from the disk driver.
652  //
653 
654  NextIrpSp->MajorFunction = IrpSp->MajorFunction;
655  NextIrpSp->Parameters.Read.Length = NextByteCount;
656  NextIrpSp->Parameters.Read.ByteOffset.QuadPart = NextLbo;
657 
658  (VOID)IoCallDriver( DeviceObject, AssocIrp );
659 
660  //
661  // We just issued an IO to the storage stack, update the counters indicating so.
662  //
663 
665 
666  FatUpdateIOCountersPCW( IsAWrite, (ULONG64)NextByteCount );
667  }
668 
669  //
670  // Wait for the Irp in the catch case and drop the flags.
671  //
672 
673  if (IrpIsMaster) {
674 
676  IrpIsMaster = MdlIsReserve = FALSE;
677 
678  //
679  // If the Irp is showing a failed status, there is no point in continuing.
680  // In doing so, we get to avoid squirreling away the failed status in case
681  // we were to re-use the master irp again.
682  //
683  // Note that since we re-used the master, we must not have issued the "last"
684  // associated Irp, and thus the completion code at the bottom will take care
685  // of that for us.
686  //
687 
688  if (!NT_SUCCESS(Irp->IoStatus.Status)) {
689 
690  NT_ASSERT( IrpCount );
691  break;
692  }
693  }
694 
695  //
696  // Now adjust everything for the next pass through the loop.
697  //
698 
699  Vbo += NextByteCount;
700  BufferOffset += NextByteCount;
701  ByteCount -= NextByteCount;
702 
703  //
704  // Try to lookup the next run, if we are not done and we got
705  // all the way through the current run.
706  //
707 
708  if (RemainingByteCount) {
709 
710  //
711  // Advance the Lbo/Vbo if we have more to do in the current run.
712  //
713 
714  NextLbo += NextByteCount;
715  NextVbo += NextByteCount;
716 
717  NextByteCount = RemainingByteCount;
718 
719  } else {
720 
721  CurrentIndex += 1;
722 
723  if ( CurrentIndex <= LastIndex ) {
724 
725  NT_ASSERT( ByteCount != 0 );
726 
728  CurrentIndex,
729  &NextVbo,
730  &NextLbo,
731  &NextByteCount );
732 
733  NT_ASSERT( NextVbo == Vbo );
734  }
735  }
736  } // while ( CurrentIndex <= LastIndex )
737 
738  //
739  // If we didn't get enough associated Irps going to make this asynchronous, we
740  // twiddle our thumbs and wait for those we did launch to complete.
741  //
742 
743  if (IrpCount) {
744 
745  while (Irp->AssociatedIrp.IrpCount != IrpCount) {
746 
748  }
749 
751  }
752 
753  DebugTrace(-1, Dbg, "FatPagingFileIo -> VOID\n", 0);
754  return;
755 }
756 
757 #if (NTDDI_VERSION >= NTDDI_WIN8)
758 
759 VOID
761  IN PIRP_CONTEXT IrpContext,
762  IN PIRP Irp,
764  )
765 /*++
766 
767 Routine Description:
768 
769  Charge appropriate process for the IO this IRP will cause.
770 
771 Arguments:
772 
773  IrpContext- The Irp Context
774 
775  Irp - Supplies the requesting Irp.
776 
777  ByteCount - The lengh of the operation.
778 
779 Return Value:
780 
781  None.
782 
783 --*/
784 
785 {
786  PETHREAD OriginatingThread = NULL;
787  ULONG NumReads = 0;
788  ULONG NumWrites = 0;
789  ULONGLONG BytesToRead = 0;
790  ULONGLONG BytesToWrite = 0;
791 
792  //
793  // Here we attempt to charge the IO back to the originating process.
794  // - These checks are intended to cover following cases:
795  // o Buffered sync reads
796  // o Unbuffered sync read
797  // o Inline metadata reads
798  // o memory mapped reads (in-line faulting of data)
799  //
800 
801  if (IrpContext->MajorFunction == IRP_MJ_READ) {
802 
803  NumReads++;
804  BytesToRead = ByteCount;
805 
806  if ((Irp->Tail.Overlay.Thread != NULL) &&
807  !IoIsSystemThread( Irp->Tail.Overlay.Thread )) {
808 
809  OriginatingThread = Irp->Tail.Overlay.Thread;
810 
811  } else if (!IoIsSystemThread( PsGetCurrentThread() )) {
812 
813  OriginatingThread = PsGetCurrentThread();
814 
815  //
816  // We couldn't find a non-system entity, so this should be charged to system.
817  // Do so only if we are top level.
818  // If we are not top-level then the read was initiated by someone like Cc (read ahead)
819  // who should have already accounted for this IO.
820  //
821 
822  } else if (IoIsSystemThread( PsGetCurrentThread() ) &&
823  (IoGetTopLevelIrp() == Irp)) {
824 
825  OriginatingThread = PsGetCurrentThread();
826  }
827 
828  //
829  // Charge the write to Originating process.
830  // Intended to cover the following writes:
831  // - Unbuffered sync write
832  // - unbuffered async write
833  //
834  // If we re not top-level, then it should already have been accounted for
835  // somewhere else (Cc).
836  //
837 
838  } else if (IrpContext->MajorFunction == IRP_MJ_WRITE) {
839 
840  NumWrites++;
841  BytesToWrite = ByteCount;
842 
843  if (IoGetTopLevelIrp() == Irp) {
844 
845  if ((Irp->Tail.Overlay.Thread != NULL) &&
846  !IoIsSystemThread( Irp->Tail.Overlay.Thread )) {
847 
848  OriginatingThread = Irp->Tail.Overlay.Thread;
849 
850  } else {
851 
852  OriginatingThread = PsGetCurrentThread();
853  }
854 
855  //
856  // For mapped page writes
857  //
858 
860 
861  OriginatingThread = PsGetCurrentThread();
862  }
863  }
864 
865  if (OriginatingThread != NULL) {
866 
867  PsUpdateDiskCounters( PsGetThreadProcess( OriginatingThread ),
868  BytesToRead,
869  BytesToWrite,
870  NumReads,
871  NumWrites,
872  0 );
873  }
874 }
875 
876 #endif
877 
878 
879 
880 _Requires_lock_held_(_Global_critical_region_)
881 NTSTATUS
882 FatNonCachedIo (
883  IN PIRP_CONTEXT IrpContext,
884  IN PIRP Irp,
885  IN PFCB FcbOrDcb,
890  )
891 /*++
892 
893 Routine Description:
894 
895  This routine performs the non-cached disk io described in its parameters.
896  The choice of a single run is made if possible, otherwise multiple runs
897  are executed.
898 
899 Arguments:
900 
901  IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
902 
903  Irp - Supplies the requesting Irp.
904 
905  FcbOrDcb - Supplies the file to act on.
906 
907  StartingVbo - The starting point for the operation.
908 
909  ByteCount - The lengh of the operation.
910 
911  UserByteCount - The last byte the user can see, rest to be zeroed.
912 
913  StreamFlags - flag to indicate special attributes for a NonCachedIo.
914 
915 Return Value:
916 
917  None.
918 
919 --*/
920 
921 {
922 
923  //
924  // Declare some local variables for enumeration through the
925  // runs of the file, and an array to store parameters for
926  // parallel I/Os
927  //
928 
929  BOOLEAN Wait;
930 
931  LBO NextLbo;
932  VBO NextVbo;
933  ULONG NextByteCount;
934  BOOLEAN NextIsAllocated;
935 
936  LBO LastLbo;
937  ULONG LastByteCount;
938  BOOLEAN LastIsAllocated;
939 
941 
942  ULONG FirstIndex;
943  ULONG CurrentIndex;
944  ULONG LastIndex;
945 
946  ULONG NextRun;
947  ULONG BufferOffset;
948  ULONG OriginalByteCount;
949 
950 
951 
952  IO_RUN StackIoRuns[FAT_MAX_IO_RUNS_ON_STACK];
953  PIO_RUN IoRuns;
954 
955 
956  PAGED_CODE();
957 
959 
960  DebugTrace(+1, Dbg, "FatNonCachedIo\n", 0);
961  DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
962  DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
963  DebugTrace( 0, Dbg, "FcbOrDcb = %p\n", FcbOrDcb );
964  DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo );
965  DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount );
966 
967  if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
968 
971 
972  if (IrpContext->MajorFunction == IRP_MJ_READ) {
973  Stats->Fat.NonCachedReads += 1;
974  Stats->Fat.NonCachedReadBytes += ByteCount;
975  } else {
976  Stats->Fat.NonCachedWrites += 1;
978  }
979  }
980 
981  //
982  // Initialize some locals.
983  //
984 
985  NextRun = 0;
986  BufferOffset = 0;
987  OriginalByteCount = ByteCount;
988 
989  Wait = BooleanFlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT);
990 
991 #if (NTDDI_VERSION >= NTDDI_WIN8)
992 
993  //
994  // Disk IO accounting
995  //
996 
998 
999  FatUpdateDiskStats( IrpContext,
1000  Irp,
1001  ByteCount );
1002  }
1003 #endif
1004 
1005  //
1006  // For nonbuffered I/O, we need the buffer locked in all
1007  // cases.
1008  //
1009  // This call may raise. If this call succeeds and a subsequent
1010  // condition is raised, the buffers are unlocked automatically
1011  // by the I/O system when the request is completed, via the
1012  // Irp->MdlAddress field.
1013  //
1014 
1015  FatLockUserBuffer( IrpContext,
1016  Irp,
1017  (IrpContext->MajorFunction == IRP_MJ_READ) ?
1019  ByteCount );
1020 
1021 
1022 
1023  //
1024  // No zeroing for trailing sectors if requested.
1025  // Otherwise setup the required zeroing for read requests.
1026  //
1027 
1028 
1029  if (UserByteCount != ByteCount) {
1030 
1031 
1032  PMDL Mdl;
1033 
1036 
1037  Mdl = IoAllocateMdl( (PUCHAR) Irp->UserBuffer + UserByteCount,
1039  FALSE,
1040  FALSE,
1041  NULL );
1042 
1043  if (Mdl == NULL) {
1044 
1046  }
1047 
1048  IoBuildPartialMdl( Irp->MdlAddress,
1049  Mdl,
1050  (PUCHAR) Irp->UserBuffer + UserByteCount,
1052 
1053  IrpContext->FatIoContext->ZeroMdl = Mdl;
1054 
1055  //
1056  // Map the MDL now so we can't fail at IO completion time. Note
1057  // that this will be only a single page.
1058  //
1059 
1060  if (MmGetSystemAddressForMdlSafe( Mdl, NormalPagePriority | MdlMappingNoExecute ) == NULL) {
1061 
1063  }
1064  }
1065 
1066 
1067  //
1068  // Try to lookup the first run. If there is just a single run,
1069  // we may just be able to pass it on.
1070  //
1071 
1072  FatLookupFileAllocation( IrpContext,
1073  FcbOrDcb,
1074  StartingVbo,
1075  &NextLbo,
1076  &NextByteCount,
1077  &NextIsAllocated,
1078  &EndOnMax,
1079  &FirstIndex );
1080 
1081  //
1082  // We just added the allocation, thus there must be at least
1083  // one entry in the mcb corresponding to our write, ie.
1084  // NextIsAllocated must be true. If not, the pre-existing file
1085  // must have an allocation error.
1086  //
1087 
1088  if ( !NextIsAllocated ) {
1089 
1090  FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
1091 
1093  }
1094 
1095  NT_ASSERT( NextByteCount != 0 );
1096 
1097  //
1098  // If the request was not aligned correctly, read in the first
1099  // part first.
1100  //
1101 
1102 
1103  //
1104  // See if the write covers a single valid run, and if so pass
1105  // it on. We must bias this by the byte that is lost at the
1106  // end of the maximal file.
1107  //
1108 
1109  if ( NextByteCount >= ByteCount - (EndOnMax ? 1 : 0)) {
1110 
1111  if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
1112  CollectDiskIoStats(FcbOrDcb->Vcb, IrpContext->MajorFunction,
1113  FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO), 1);
1114  } else {
1115 
1116  PFILE_SYSTEM_STATISTICS Stats =
1118 
1119  if (IrpContext->MajorFunction == IRP_MJ_READ) {
1120  Stats->Fat.NonCachedDiskReads += 1;
1121  } else {
1122  Stats->Fat.NonCachedDiskWrites += 1;
1123  }
1124  }
1125 
1126  DebugTrace( 0, Dbg, "Passing 1 Irp on to Disk Driver\n", 0 );
1127 
1128  FatSingleAsync( IrpContext,
1129  FcbOrDcb->Vcb,
1130  NextLbo,
1131  ByteCount,
1132  Irp );
1133 
1134  } else {
1135 
1136  //
1137  // If there we can't wait, and there are more runs than we can handle,
1138  // we will have to post this request.
1139  //
1140 
1141  FatLookupFileAllocation( IrpContext,
1142  FcbOrDcb,
1143  StartingVbo + ByteCount - 1,
1144  &LastLbo,
1145  &LastByteCount,
1146  &LastIsAllocated,
1147  &EndOnMax,
1148  &LastIndex );
1149 
1150  //
1151  // Since we already added the allocation for the whole
1152  // write, assert that we find runs until ByteCount == 0
1153  // Otherwise this file is corrupt.
1154  //
1155 
1156  if ( !LastIsAllocated ) {
1157 
1158  FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
1159 
1161  }
1162 
1163  if (LastIndex - FirstIndex + 1 > FAT_MAX_IO_RUNS_ON_STACK) {
1164 
1166  (LastIndex - FirstIndex + 1) * sizeof(IO_RUN),
1167  TAG_IO_RUNS );
1168 
1169  } else {
1170 
1171  IoRuns = StackIoRuns;
1172  }
1173 
1174  NT_ASSERT( LastIndex != FirstIndex );
1175 
1176  CurrentIndex = FirstIndex;
1177 
1178  //
1179  // Loop while there are still byte writes to satisfy.
1180  //
1181 
1182  while (CurrentIndex <= LastIndex) {
1183 
1184 
1185  NT_ASSERT( NextByteCount != 0);
1186  NT_ASSERT( ByteCount != 0);
1187 
1188  //
1189  // If next run is larger than we need, "ya get what you need".
1190  //
1191 
1192  if (NextByteCount > ByteCount) {
1193  NextByteCount = ByteCount;
1194  }
1195 
1196  //
1197  // Now that we have properly bounded this piece of the
1198  // transfer, it is time to write it.
1199  //
1200  // We remember each piece of a parallel run by saving the
1201  // essential information in the IoRuns array. The tranfers
1202  // are started up in parallel below.
1203  //
1204 
1205  IoRuns[NextRun].Vbo = StartingVbo;
1206  IoRuns[NextRun].Lbo = NextLbo;
1207  IoRuns[NextRun].Offset = BufferOffset;
1208  IoRuns[NextRun].ByteCount = NextByteCount;
1209  NextRun += 1;
1210 
1211  //
1212  // Now adjust everything for the next pass through the loop.
1213  //
1214 
1215  StartingVbo += NextByteCount;
1216  BufferOffset += NextByteCount;
1217  ByteCount -= NextByteCount;
1218 
1219  //
1220  // Try to lookup the next run (if we are not done).
1221  //
1222 
1223  CurrentIndex += 1;
1224 
1225  if ( CurrentIndex <= LastIndex ) {
1226 
1227  NT_ASSERT( ByteCount != 0 );
1228 
1230  CurrentIndex,
1231  &NextVbo,
1232  &NextLbo,
1233  &NextByteCount );
1234 
1235 
1236  NT_ASSERT(NextVbo == StartingVbo);
1237 
1238 
1239  }
1240 
1241  } // while ( CurrentIndex <= LastIndex )
1242 
1243  //
1244  // Now set up the Irp->IoStatus. It will be modified by the
1245  // multi-completion routine in case of error or verify required.
1246  //
1247 
1248  Irp->IoStatus.Status = STATUS_SUCCESS;
1249  Irp->IoStatus.Information = OriginalByteCount;
1250 
1251  if (FlagOn(Irp->Flags, IRP_PAGING_IO)) {
1252  CollectDiskIoStats(FcbOrDcb->Vcb, IrpContext->MajorFunction,
1253  FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_USER_IO), NextRun);
1254  }
1255 
1256  //
1257  // OK, now do the I/O.
1258  //
1259 
1260  _SEH2_TRY {
1261 
1262  DebugTrace( 0, Dbg, "Passing Multiple Irps on to Disk Driver\n", 0 );
1263 
1264  FatMultipleAsync( IrpContext,
1265  FcbOrDcb->Vcb,
1266  Irp,
1267  NextRun,
1268  IoRuns );
1269 
1270  } _SEH2_FINALLY {
1271 
1272  if (IoRuns != StackIoRuns) {
1273 
1274  ExFreePool( IoRuns );
1275  }
1276  } _SEH2_END;
1277  }
1278 
1279  if (!Wait) {
1280 
1281  DebugTrace(-1, Dbg, "FatNonCachedIo -> STATUS_PENDING\n", 0);
1282  return STATUS_PENDING;
1283  }
1284 
1285  FatWaitSync( IrpContext );
1286 
1287 
1288  DebugTrace(-1, Dbg, "FatNonCachedIo -> 0x%08lx\n", Irp->IoStatus.Status);
1289  return Irp->IoStatus.Status;
1290 }
1291 
1292 
1293 _Requires_lock_held_(_Global_critical_region_)
1294 VOID
1295 FatNonCachedNonAlignedRead (
1296  IN PIRP_CONTEXT IrpContext,
1297  IN PIRP Irp,
1298  IN PFCB FcbOrDcb,
1301  )
1302 
1303 /*++
1304 
1305 Routine Description:
1306 
1307  This routine performs the non-cached disk io described in its parameters.
1308  This routine differs from the above in that the range does not have to be
1309  sector aligned. This accomplished with the use of intermediate buffers.
1310 
1311 Arguments:
1312 
1313  IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
1314 
1315  Irp - Supplies the requesting Irp.
1316 
1317  FcbOrDcb - Supplies the file to act on.
1318 
1319  StartingVbo - The starting point for the operation.
1320 
1321  ByteCount - The lengh of the operation.
1322 
1323 Return Value:
1324 
1325  None.
1326 
1327 --*/
1328 
1329 {
1330  //
1331  // Declare some local variables for enumeration through the
1332  // runs of the file, and an array to store parameters for
1333  // parallel I/Os
1334  //
1335 
1336  LBO NextLbo;
1337  ULONG NextByteCount;
1338  BOOLEAN NextIsAllocated;
1339 
1340  ULONG SectorSize;
1342  ULONG OriginalByteCount;
1343  ULONG OriginalStartingVbo;
1344 
1345  BOOLEAN EndOnMax;
1346 
1347  PUCHAR UserBuffer;
1348  PUCHAR DiskBuffer = NULL;
1349 
1350  PMDL Mdl;
1351  PMDL SavedMdl;
1352  PVOID SavedUserBuffer;
1353 
1354  PAGED_CODE();
1355 
1356  DebugTrace(+1, Dbg, "FatNonCachedNonAlignedRead\n", 0);
1357  DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
1358  DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
1359  DebugTrace( 0, Dbg, "FcbOrDcb = %p\n", FcbOrDcb );
1360  DebugTrace( 0, Dbg, "StartingVbo = %08lx\n", StartingVbo );
1361  DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount );
1362 
1363  //
1364  // Initialize some locals.
1365  //
1366 
1367  OriginalByteCount = ByteCount;
1368  OriginalStartingVbo = StartingVbo;
1370 
1371  NT_ASSERT( FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) );
1372 
1373  //
1374  // For nonbuffered I/O, we need the buffer locked in all
1375  // cases.
1376  //
1377  // This call may raise. If this call succeeds and a subsequent
1378  // condition is raised, the buffers are unlocked automatically
1379  // by the I/O system when the request is completed, via the
1380  // Irp->MdlAddress field.
1381  //
1382 
1383  FatLockUserBuffer( IrpContext,
1384  Irp,
1385  IoWriteAccess,
1386  ByteCount );
1387 
1388  UserBuffer = FatMapUserBuffer( IrpContext, Irp );
1389 
1390  //
1391  // Allocate the local buffer
1392  //
1393 
1394  DiskBuffer = FsRtlAllocatePoolWithTag( NonPagedPoolNxCacheAligned,
1396  TAG_IO_BUFFER );
1397 
1398  //
1399  // We use a try block here to ensure the buffer is freed, and to
1400  // fill in the correct byte count in the Iosb.Information field.
1401  //
1402 
1403  _SEH2_TRY {
1404 
1405  //
1406  // If the beginning of the request was not aligned correctly, read in
1407  // the first part first.
1408  //
1409 
1410  if ( StartingVbo & (SectorSize - 1) ) {
1411 
1412  VBO Hole;
1413 
1414  //
1415  // Try to lookup the first run.
1416  //
1417 
1418  FatLookupFileAllocation( IrpContext,
1419  FcbOrDcb,
1420  StartingVbo,
1421  &NextLbo,
1422  &NextByteCount,
1423  &NextIsAllocated,
1424  &EndOnMax,
1425  NULL );
1426 
1427  //
1428  // We just added the allocation, thus there must be at least
1429  // one entry in the mcb corresponding to our write, ie.
1430  // NextIsAllocated must be true. If not, the pre-existing file
1431  // must have an allocation error.
1432  //
1433 
1434  if ( !NextIsAllocated ) {
1435 
1436  FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
1437 
1439  }
1440 
1441  FatSingleNonAlignedSync( IrpContext,
1442  FcbOrDcb->Vcb,
1443  DiskBuffer,
1444  NextLbo & ~((LONG)SectorSize - 1),
1445  SectorSize,
1446  Irp );
1447 
1448  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
1449 
1450  try_return( NOTHING );
1451  }
1452 
1453  //
1454  // Now copy the part of the first sector that we want to the user
1455  // buffer.
1456  //
1457 
1458  Hole = StartingVbo & (SectorSize - 1);
1459 
1460  BytesToCopy = ByteCount >= SectorSize - Hole ?
1461  SectorSize - Hole : ByteCount;
1462 
1463  RtlCopyMemory( UserBuffer, DiskBuffer + Hole, BytesToCopy );
1464 
1467 
1468  if ( ByteCount == 0 ) {
1469 
1470  try_return( NOTHING );
1471  }
1472  }
1473 
1474  NT_ASSERT( (StartingVbo & (SectorSize - 1)) == 0 );
1475 
1476  //
1477  // If there is a tail part that is not sector aligned, read it.
1478  //
1479 
1480  if ( ByteCount & (SectorSize - 1) ) {
1481 
1482  VBO LastSectorVbo;
1483 
1484  LastSectorVbo = StartingVbo + (ByteCount & ~(SectorSize - 1));
1485 
1486  //
1487  // Try to lookup the last part of the requested range.
1488  //
1489 
1490  FatLookupFileAllocation( IrpContext,
1491  FcbOrDcb,
1492  LastSectorVbo,
1493  &NextLbo,
1494  &NextByteCount,
1495  &NextIsAllocated,
1496  &EndOnMax,
1497  NULL );
1498 
1499  //
1500  // We just added the allocation, thus there must be at least
1501  // one entry in the mcb corresponding to our write, ie.
1502  // NextIsAllocated must be true. If not, the pre-existing file
1503  // must have an allocation error.
1504  //
1505 
1506  if ( !NextIsAllocated ) {
1507 
1508  FatPopUpFileCorrupt( IrpContext, FcbOrDcb );
1509 
1511  }
1512 
1513  FatSingleNonAlignedSync( IrpContext,
1514  FcbOrDcb->Vcb,
1515  DiskBuffer,
1516  NextLbo,
1517  SectorSize,
1518  Irp );
1519 
1520  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
1521 
1522  try_return( NOTHING );
1523  }
1524 
1525  //
1526  // Now copy over the part of this last sector that we need.
1527  //
1528 
1529  BytesToCopy = ByteCount & (SectorSize - 1);
1530 
1531  UserBuffer += LastSectorVbo - OriginalStartingVbo;
1532 
1533  RtlCopyMemory( UserBuffer, DiskBuffer, BytesToCopy );
1534 
1536 
1537  if ( ByteCount == 0 ) {
1538 
1539  try_return( NOTHING );
1540  }
1541  }
1542 
1543  NT_ASSERT( ((StartingVbo | ByteCount) & (SectorSize - 1)) == 0 );
1544 
1545  //
1546  // Now build a Mdl describing the sector aligned balance of the transfer,
1547  // and put it in the Irp, and read that part.
1548  //
1549 
1550  SavedMdl = Irp->MdlAddress;
1551  Irp->MdlAddress = NULL;
1552 
1553  SavedUserBuffer = Irp->UserBuffer;
1554 
1555  Irp->UserBuffer = (PUCHAR)MmGetMdlVirtualAddress( SavedMdl ) +
1556  (StartingVbo - OriginalStartingVbo);
1557 
1558  Mdl = IoAllocateMdl( Irp->UserBuffer,
1559  ByteCount,
1560  FALSE,
1561  FALSE,
1562  Irp );
1563 
1564  if (Mdl == NULL) {
1565 
1566  Irp->MdlAddress = SavedMdl;
1567  Irp->UserBuffer = SavedUserBuffer;
1569  }
1570 
1571  IoBuildPartialMdl( SavedMdl,
1572  Mdl,
1573  Irp->UserBuffer,
1574  ByteCount );
1575 
1576  //
1577  // Try to read in the pages.
1578  //
1579 
1580  _SEH2_TRY {
1581 
1582  FatNonCachedIo( IrpContext,
1583  Irp,
1584  FcbOrDcb,
1585  StartingVbo,
1586  ByteCount,
1587  ByteCount,
1588  0 );
1589 
1590  } _SEH2_FINALLY {
1591 
1592  IoFreeMdl( Irp->MdlAddress );
1593 
1594  Irp->MdlAddress = SavedMdl;
1595  Irp->UserBuffer = SavedUserBuffer;
1596  } _SEH2_END;
1597 
1598  try_exit: NOTHING;
1599 
1600  } _SEH2_FINALLY {
1601 
1602  ExFreePool( DiskBuffer );
1603 
1604  if ( !_SEH2_AbnormalTermination() && NT_SUCCESS(Irp->IoStatus.Status) ) {
1605 
1606  Irp->IoStatus.Information = OriginalByteCount;
1607 
1608  //
1609  // We now flush the user's buffer to memory.
1610  //
1611 
1612  KeFlushIoBuffers( Irp->MdlAddress, TRUE, FALSE );
1613  }
1614  } _SEH2_END;
1615 
1616  DebugTrace(-1, Dbg, "FatNonCachedNonAlignedRead -> VOID\n", 0);
1617  return;
1618 }
1619 
1620 
1621 VOID
1623  IN PIRP_CONTEXT IrpContext,
1624  IN PVCB Vcb,
1625  IN PIRP MasterIrp,
1626  IN ULONG MultipleIrpCount,
1627  IN PIO_RUN IoRuns
1628  )
1629 
1630 /*++
1631 
1632 Routine Description:
1633 
1634  This routine first does the initial setup required of a Master IRP that is
1635  going to be completed using associated IRPs. This routine should not
1636  be used if only one async request is needed, instead the single read/write
1637  async routines should be called.
1638 
1639  A context parameter is initialized, to serve as a communications area
1640  between here and the common completion routine. This initialization
1641  includes allocation of a spinlock. The spinlock is deallocated in the
1642  FatWaitSync routine, so it is essential that the caller insure that
1643  this routine is always called under all circumstances following a call
1644  to this routine.
1645 
1646  Next this routine reads or writes one or more contiguous sectors from
1647  a device asynchronously, and is used if there are multiple reads for a
1648  master IRP. A completion routine is used to synchronize with the
1649  completion of all of the I/O requests started by calls to this routine.
1650 
1651  Also, prior to calling this routine the caller must initialize the
1652  IoStatus field in the Context, with the correct success status and byte
1653  count which are expected if all of the parallel transfers complete
1654  successfully. After return this status will be unchanged if all requests
1655  were, in fact, successful. However, if one or more errors occur, the
1656  IoStatus will be modified to reflect the error status and byte count
1657  from the first run (by Vbo) which encountered an error. I/O status
1658  from all subsequent runs will not be indicated.
1659 
1660 Arguments:
1661 
1662  IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
1663 
1664  Vcb - Supplies the device to be read
1665 
1666  MasterIrp - Supplies the master Irp.
1667 
1668  MulitpleIrpCount - Supplies the number of multiple async requests
1669  that will be issued against the master irp.
1670 
1671  IoRuns - Supplies an array containing the Vbo, Lbo, BufferOffset, and
1672  ByteCount for all the runs to executed in parallel.
1673 
1674 Return Value:
1675 
1676  None.
1677 
1678 --*/
1679 
1680 {
1681  PIRP Irp;
1683  PMDL Mdl;
1684  BOOLEAN Wait;
1686 #ifndef __REACTOS__
1687  BOOLEAN IsAWrite = FALSE;
1688  ULONG Length = 0;
1689 #endif
1690 
1691  ULONG UnwindRunCount = 0;
1692 
1693  BOOLEAN ExceptionExpected = TRUE;
1694 
1695  PAGED_CODE();
1696 
1697  DebugTrace(+1, Dbg, "FatMultipleAsync\n", 0);
1698  DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
1699  DebugTrace( 0, Dbg, "Vcb = %p\n", Vcb );
1700  DebugTrace( 0, Dbg, "MasterIrp = %p\n", MasterIrp );
1701  DebugTrace( 0, Dbg, "MultipleIrpCount = %08lx\n", MultipleIrpCount );
1702  DebugTrace( 0, Dbg, "IoRuns = %08lx\n", IoRuns );
1703 
1704  //
1705  // If this I/O originating during FatVerifyVolume, bypass the
1706  // verify logic.
1707  //
1708 
1709  if (Vcb->VerifyThread == KeGetCurrentThread()) {
1710 
1711  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY );
1712  }
1713 
1714  //
1715  // Set up things according to whether this is truely async.
1716  //
1717 
1718  Wait = BooleanFlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT );
1719 
1720  Context = IrpContext->FatIoContext;
1721 
1722  //
1723  // Finish initializing Context, for use in Read/Write Multiple Asynch.
1724  //
1725 
1726  Context->MasterIrp = MasterIrp;
1727 
1728  IrpSp = IoGetCurrentIrpStackLocation( MasterIrp );
1729 #ifndef __REACTOS__
1730  IsAWrite = (IrpSp->MajorFunction == IRP_MJ_WRITE);
1731  Length = IrpSp->Parameters.Read.Length;
1732 #endif
1733 
1734  _SEH2_TRY {
1735 
1736  //
1737  // Itterate through the runs, doing everything that can fail
1738  //
1739 
1740  for ( UnwindRunCount = 0;
1741  UnwindRunCount < MultipleIrpCount;
1742  UnwindRunCount++ ) {
1743 
1744  //
1745  // Create an associated IRP, making sure there is one stack entry for
1746  // us, as well.
1747  //
1748 
1749  IoRuns[UnwindRunCount].SavedIrp = 0;
1750 
1751  Irp = IoMakeAssociatedIrp( MasterIrp,
1752  (CCHAR)(Vcb->TargetDeviceObject->StackSize + 1) );
1753 
1754  if (Irp == NULL) {
1755 
1757  }
1758 
1759  IoRuns[UnwindRunCount].SavedIrp = Irp;
1760 
1761  //
1762  // Allocate and build a partial Mdl for the request.
1763  //
1764 
1765  Mdl = IoAllocateMdl( (PCHAR)MasterIrp->UserBuffer +
1766  IoRuns[UnwindRunCount].Offset,
1767  IoRuns[UnwindRunCount].ByteCount,
1768  FALSE,
1769  FALSE,
1770  Irp );
1771 
1772  if (Mdl == NULL) {
1773 
1775  }
1776 
1777  //
1778  // Sanity Check
1779  //
1780 
1781  NT_ASSERT( Mdl == Irp->MdlAddress );
1782 
1783  IoBuildPartialMdl( MasterIrp->MdlAddress,
1784  Mdl,
1785  (PCHAR)MasterIrp->UserBuffer +
1786  IoRuns[UnwindRunCount].Offset,
1787  IoRuns[UnwindRunCount].ByteCount );
1788 
1789  //
1790  // Get the first IRP stack location in the associated Irp
1791  //
1792 
1795 
1796  //
1797  // Setup the Stack location to describe our read.
1798  //
1799 
1800  IrpSp->MajorFunction = IrpContext->MajorFunction;
1801  IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].ByteCount;
1802  IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].Vbo;
1803 
1804  //
1805  // Set up the completion routine address in our stack frame.
1806  //
1807 
1809  Wait ?
1812  Context,
1813  TRUE,
1814  TRUE,
1815  TRUE );
1816 
1817  //
1818  // Setup the next IRP stack location in the associated Irp for the disk
1819  // driver beneath us.
1820  //
1821 
1823 
1824  //
1825  // Setup the Stack location to do a read from the disk driver.
1826  //
1827 
1828  IrpSp->MajorFunction = IrpContext->MajorFunction;
1829  IrpSp->Parameters.Read.Length = IoRuns[UnwindRunCount].ByteCount;
1830  IrpSp->Parameters.Read.ByteOffset.QuadPart = IoRuns[UnwindRunCount].Lbo;
1831 
1832  //
1833  // If this Irp is the result of a WriteThough operation,
1834  // tell the device to write it through.
1835  //
1836 
1837  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH )) {
1838 
1840  }
1841 
1842  //
1843  // If this I/O requires override verify, bypass the verify logic.
1844  //
1845 
1846  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY )) {
1847 
1849  }
1850  }
1851 
1852  //
1853  // Now we no longer expect an exception. If the driver raises, we
1854  // must bugcheck, because we do not know how to recover from that
1855  // case.
1856  //
1857 
1858  ExceptionExpected = FALSE;
1859 
1860  //
1861  // We only need to set the associated IRP count in the master irp to
1862  // make it a master IRP. But we set the count to one more than our
1863  // caller requested, because we do not want the I/O system to complete
1864  // the I/O. We also set our own count.
1865  //
1866 
1867  Context->IrpCount = MultipleIrpCount;
1868  MasterIrp->AssociatedIrp.IrpCount = MultipleIrpCount;
1869 
1870  if (Wait) {
1871 
1872  MasterIrp->AssociatedIrp.IrpCount += 1;
1873  }
1874  else if (FlagOn( Context->Wait.Async.ResourceThreadId, 3 )) {
1875 
1876  //
1877  // For async requests if we acquired locks, transition the lock owners to an
1878  // object, since when we return this thread could go away before request
1879  // completion, and the resource package may try to boost priority.
1880  //
1881 
1882  if (Context->Wait.Async.Resource != NULL) {
1883 
1884  ExSetResourceOwnerPointer( Context->Wait.Async.Resource,
1885  (PVOID)Context->Wait.Async.ResourceThreadId );
1886  }
1887 
1888  if (Context->Wait.Async.Resource2 != NULL) {
1889 
1890  ExSetResourceOwnerPointer( Context->Wait.Async.Resource2,
1891  (PVOID)Context->Wait.Async.ResourceThreadId );
1892  }
1893  }
1894 
1895  //
1896  // Back up a copy of the IrpContext flags for later use in async completion.
1897  //
1898 
1899  Context->IrpContextFlags = IrpContext->Flags;
1900 
1901  //
1902  // Now that all the dangerous work is done, issue the read requests
1903  //
1904 
1905  for (UnwindRunCount = 0;
1906  UnwindRunCount < MultipleIrpCount;
1907  UnwindRunCount++) {
1908 
1909  Irp = IoRuns[UnwindRunCount].SavedIrp;
1910 
1911  DebugDoit( FatIoCallDriverCount += 1);
1912 
1913  //
1914  // If IoCallDriver returns an error, it has completed the Irp
1915  // and the error will be caught by our completion routines
1916  // and dealt with as a normal IO error.
1917  //
1918 
1919  (VOID)FatLowLevelReadWrite( IrpContext,
1920  Vcb->TargetDeviceObject,
1921  Irp,
1922  Vcb );
1923  }
1924 
1925  //
1926  // We just issued an IO to the storage stack, update the counters indicating so.
1927  //
1928 
1930 
1931  FatUpdateIOCountersPCW( IsAWrite, Length );
1932  }
1933 
1934  } _SEH2_FINALLY {
1935 
1936  ULONG i;
1937 
1939 
1940  //
1941  // Only allocating the spinlock, making the associated Irps
1942  // and allocating the Mdls can fail.
1943  //
1944 
1945  if ( _SEH2_AbnormalTermination() ) {
1946 
1947  //
1948  // If the driver raised, we are hosed. He is not supposed to raise,
1949  // and it is impossible for us to figure out how to clean up.
1950  //
1951 
1952  if (!ExceptionExpected) {
1953  NT_ASSERT( ExceptionExpected );
1954 #ifdef _MSC_VER
1955 #pragma prefast( suppress:28159, "things are seriously wrong if we get here" )
1956 #endif
1957  FatBugCheck( 0, 0, 0 );
1958  }
1959 
1960  //
1961  // Unwind
1962  //
1963 
1964  for (i = 0; i <= UnwindRunCount; i++) {
1965 
1966  if ( (Irp = IoRuns[i].SavedIrp) != NULL ) {
1967 
1968  if ( Irp->MdlAddress != NULL ) {
1969 
1970  IoFreeMdl( Irp->MdlAddress );
1971  }
1972 
1973  IoFreeIrp( Irp );
1974  }
1975  }
1976  }
1977 
1978  //
1979  // And return to our caller
1980  //
1981 
1982  DebugTrace(-1, Dbg, "FatMultipleAsync -> VOID\n", 0);
1983  } _SEH2_END;
1984 
1985  return;
1986 }
1987 
1988 
1989 VOID
1991  IN PIRP_CONTEXT IrpContext,
1992  IN PVCB Vcb,
1993  IN LBO Lbo,
1994  IN ULONG ByteCount,
1995  IN PIRP Irp
1996  )
1997 
1998 /*++
1999 
2000 Routine Description:
2001 
2002  This routine reads or writes one or more contiguous sectors from a device
2003  asynchronously, and is used if there is only one read necessary to
2004  complete the IRP. It implements the read by simply filling
2005  in the next stack frame in the Irp, and passing it on. The transfer
2006  occurs to the single buffer originally specified in the user request.
2007 
2008 Arguments:
2009 
2010  IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
2011 
2012  Vcb - Supplies the device to read
2013 
2014  Lbo - Supplies the starting Logical Byte Offset to begin reading from
2015 
2016  ByteCount - Supplies the number of bytes to read from the device
2017 
2018  Irp - Supplies the master Irp to associated with the async
2019  request.
2020 
2021 Return Value:
2022 
2023  None.
2024 
2025 --*/
2026 
2027 {
2030 #ifndef __REACTOS__
2031  BOOLEAN IsAWrite = FALSE;
2032 #endif
2033 
2034  PAGED_CODE();
2035 
2036  DebugTrace(+1, Dbg, "FatSingleAsync\n", 0);
2037  DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
2038  DebugTrace( 0, Dbg, "Vcb = %p\n", Vcb );
2039  DebugTrace( 0, Dbg, "Lbo = %08lx\n", Lbo);
2040  DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
2041  DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
2042 
2043  //
2044  // If this I/O originating during FatVerifyVolume, bypass the
2045  // verify logic.
2046  //
2047 
2048  if (Vcb->VerifyThread == KeGetCurrentThread()) {
2049 
2050  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY );
2051  }
2052 
2053  //
2054  // Set up the completion routine address in our stack frame.
2055  //
2056 
2058  FlagOn(IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT) ?
2061  IrpContext->FatIoContext,
2062  TRUE,
2063  TRUE,
2064  TRUE );
2065 
2066  //
2067  // Setup the next IRP stack location in the associated Irp for the disk
2068  // driver beneath us.
2069  //
2070 
2072 
2073  //
2074  // Setup the Stack location to do a read from the disk driver.
2075  //
2076 
2077  IrpSp->MajorFunction = IrpContext->MajorFunction;
2078  IrpSp->Parameters.Read.Length = ByteCount;
2079  IrpSp->Parameters.Read.ByteOffset.QuadPart = Lbo;
2080 
2081 #ifndef __REACTOS__
2082  IsAWrite = (IrpSp->MajorFunction == IRP_MJ_WRITE);
2083 #endif
2084 
2085  //
2086  // If this Irp is the result of a WriteThough operation,
2087  // tell the device to write it through.
2088  //
2089 
2090  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WRITE_THROUGH )) {
2091 
2093  }
2094 
2095  //
2096  // If this I/O requires override verify, bypass the verify logic.
2097  //
2098 
2099  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY )) {
2100 
2102  }
2103 
2104  //
2105  // For async requests if we acquired locks, transition the lock owners to an
2106  // object, since when we return this thread could go away before request
2107  // completion, and the resource package may try to boost priority.
2108  //
2109 
2110  if (!FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_WAIT ) &&
2111  FlagOn( IrpContext->FatIoContext->Wait.Async.ResourceThreadId, 3 )) {
2112 
2113  Context = IrpContext->FatIoContext;
2114 
2115  if (Context->Wait.Async.Resource != NULL) {
2116 
2117  ExSetResourceOwnerPointer( Context->Wait.Async.Resource,
2118  (PVOID)Context->Wait.Async.ResourceThreadId );
2119  }
2120 
2121  if (Context->Wait.Async.Resource2 != NULL) {
2122 
2123  ExSetResourceOwnerPointer( Context->Wait.Async.Resource2,
2124  (PVOID)Context->Wait.Async.ResourceThreadId );
2125  }
2126  }
2127 
2128  //
2129  // Back up a copy of the IrpContext flags for later use in async completion.
2130  //
2131 
2132  IrpContext->FatIoContext->IrpContextFlags = IrpContext->Flags;
2133 
2134  //
2135  // Issue the read request
2136  //
2137 
2138  DebugDoit( FatIoCallDriverCount += 1);
2139 
2140  //
2141  // If IoCallDriver returns an error, it has completed the Irp
2142  // and the error will be caught by our completion routines
2143  // and dealt with as a normal IO error.
2144  //
2145 
2146  (VOID)FatLowLevelReadWrite( IrpContext,
2147  Vcb->TargetDeviceObject,
2148  Irp,
2149  Vcb );
2150 
2151  //
2152  // We just issued an IO to the storage stack, update the counters indicating so.
2153  //
2154 
2156 
2157  FatUpdateIOCountersPCW( IsAWrite, ByteCount );
2158  }
2159 
2160  //
2161  // And return to our caller
2162  //
2163 
2164  DebugTrace(-1, Dbg, "FatSingleAsync -> VOID\n", 0);
2165 
2166  return;
2167 }
2168 
2169 
2170 VOID
2172  IN PIRP_CONTEXT IrpContext,
2173  IN PVCB Vcb,
2174  IN PUCHAR Buffer,
2175  IN LBO Lbo,
2176  IN ULONG ByteCount,
2177  IN PIRP Irp
2178  )
2179 
2180 /*++
2181 
2182 Routine Description:
2183 
2184  This routine reads or writes one or more contiguous sectors from a device
2185  Synchronously, and does so to a buffer that must come from non paged
2186  pool. It saves a pointer to the Irp's original Mdl, and creates a new
2187  one describing the given buffer. It implements the read by simply filling
2188  in the next stack frame in the Irp, and passing it on. The transfer
2189  occurs to the single buffer originally specified in the user request.
2190 
2191 Arguments:
2192 
2193  IrpContext->MajorFunction - Supplies either IRP_MJ_READ or IRP_MJ_WRITE.
2194 
2195  Vcb - Supplies the device to read
2196 
2197  Buffer - Supplies a buffer from non-paged pool.
2198 
2199  Lbo - Supplies the starting Logical Byte Offset to begin reading from
2200 
2201  ByteCount - Supplies the number of bytes to read from the device
2202 
2203  Irp - Supplies the master Irp to associated with the async
2204  request.
2205 
2206 Return Value:
2207 
2208  None.
2209 
2210 --*/
2211 
2212 {
2214 
2215  PMDL Mdl;
2216  PMDL SavedMdl;
2217 #ifndef __REACTOS__
2218  BOOLEAN IsAWrite = FALSE;
2219 #endif
2220 
2221  PAGED_CODE();
2222 
2223  DebugTrace(+1, Dbg, "FatSingleNonAlignedAsync\n", 0);
2224  DebugTrace( 0, Dbg, "MajorFunction = %08lx\n", IrpContext->MajorFunction );
2225  DebugTrace( 0, Dbg, "Vcb = %p\n", Vcb );
2226  DebugTrace( 0, Dbg, "Buffer = %p\n", Buffer );
2227  DebugTrace( 0, Dbg, "Lbo = %08lx\n", Lbo);
2228  DebugTrace( 0, Dbg, "ByteCount = %08lx\n", ByteCount);
2229  DebugTrace( 0, Dbg, "Irp = %p\n", Irp );
2230 
2231  //
2232  // Create a new Mdl describing the buffer, saving the current one in the
2233  // Irp
2234  //
2235 
2236  SavedMdl = Irp->MdlAddress;
2237 
2238  Irp->MdlAddress = 0;
2239 
2240  Mdl = IoAllocateMdl( Buffer,
2241  ByteCount,
2242  FALSE,
2243  FALSE,
2244  Irp );
2245 
2246  if (Mdl == NULL) {
2247 
2248  Irp->MdlAddress = SavedMdl;
2249 
2251  }
2252 
2253  //
2254  // Lock the new Mdl in memory.
2255  //
2256 
2257  _SEH2_TRY {
2258 
2260 
2261  } _SEH2_FINALLY {
2262 
2263  if ( _SEH2_AbnormalTermination() ) {
2264 
2265  IoFreeMdl( Mdl );
2266  Irp->MdlAddress = SavedMdl;
2267  }
2268  } _SEH2_END;
2269 
2270  //
2271  // Set up the completion routine address in our stack frame.
2272  //
2273 
2276  IrpContext->FatIoContext,
2277  TRUE,
2278  TRUE,
2279  TRUE );
2280 
2281  //
2282  // Setup the next IRP stack location in the associated Irp for the disk
2283  // driver beneath us.
2284  //
2285 
2287 
2288  //
2289  // Setup the Stack location to do a read from the disk driver.
2290  //
2291 
2292  IrpSp->MajorFunction = IrpContext->MajorFunction;
2293  IrpSp->Parameters.Read.Length = ByteCount;
2294  IrpSp->Parameters.Read.ByteOffset.QuadPart = Lbo;
2295 
2296 #ifndef __REACTOS__
2297  IsAWrite = (IrpSp->MajorFunction == IRP_MJ_WRITE);
2298 #endif
2299 
2300  //
2301  // If this I/O originating during FatVerifyVolume, bypass the
2302  // verify logic.
2303  //
2304 
2305  if (Vcb->VerifyThread == KeGetCurrentThread()) {
2306 
2307  SetFlag( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY );
2308  }
2309 
2310  //
2311  // If this I/O requires override verify, bypass the verify logic.
2312  //
2313 
2314  if (FlagOn( IrpContext->Flags, IRP_CONTEXT_FLAG_OVERRIDE_VERIFY )) {
2315 
2317  }
2318 
2319  //
2320  // Issue the read request
2321  //
2322 
2323  DebugDoit( FatIoCallDriverCount += 1);
2324 
2325  //
2326  // If IoCallDriver returns an error, it has completed the Irp
2327  // and the error will be caught by our completion routines
2328  // and dealt with as a normal IO error.
2329  //
2330 
2331  _SEH2_TRY {
2332 
2333  (VOID)FatLowLevelReadWrite( IrpContext,
2334  Vcb->TargetDeviceObject,
2335  Irp,
2336  Vcb );
2337 
2338  FatWaitSync( IrpContext );
2339 
2340  } _SEH2_FINALLY {
2341 
2342  MmUnlockPages( Mdl );
2343  IoFreeMdl( Mdl );
2344  Irp->MdlAddress = SavedMdl;
2345  } _SEH2_END;
2346 
2347  //
2348  // We just issued an IO to the storage stack, update the counters indicating so.
2349  //
2350 
2352 
2353  FatUpdateIOCountersPCW( IsAWrite, ByteCount );
2354  }
2355 
2356  //
2357  // And return to our caller
2358  //
2359 
2360  DebugTrace(-1, Dbg, "FatSingleNonAlignedSync -> VOID\n", 0);
2361 
2362  return;
2363 }
2364 
2365 
2366 VOID
2368  IN PIRP_CONTEXT IrpContext
2369  )
2370 
2371 /*++
2372 
2373 Routine Description:
2374 
2375  This routine waits for one or more previously started I/O requests
2376  from the above routines, by simply waiting on the event.
2377 
2378 Arguments:
2379 
2380 Return Value:
2381 
2382  None
2383 
2384 --*/
2385 
2386 {
2387  PAGED_CODE();
2388 
2389  DebugTrace(+1, Dbg, "FatWaitSync, Context = %p\n", IrpContext->FatIoContext );
2390 
2391  KeWaitForSingleObject( &IrpContext->FatIoContext->Wait.SyncEvent,
2393 
2394  KeClearEvent( &IrpContext->FatIoContext->Wait.SyncEvent );
2395 
2396  DebugTrace(-1, Dbg, "FatWaitSync -> VOID\n", 0 );
2397 }
2398 
2399 
2400 //
2401 // Internal Support Routine
2402 //
2403 
2404 NTSTATUS
2405 NTAPI
2408  _In_ PIRP Irp,
2409  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2410  )
2411 
2412 /*++
2413 
2414 Routine Description:
2415 
2416  This is the completion routine for all reads and writes started via
2417  FatRead/WriteMultipleAsynch. It must synchronize its operation for
2418  multiprocessor environments with itself on all other processors, via
2419  a spin lock found via the Context parameter.
2420 
2421  The completion routine has the following responsibilities:
2422 
2423  If the individual request was completed with an error, then
2424  this completion routine must see if this is the first error
2425  (essentially by Vbo), and if so it must correctly reduce the
2426  byte count and remember the error status in the Context.
2427 
2428  If the IrpCount goes to 1, then it sets the event in the Context
2429  parameter to signal the caller that all of the asynch requests
2430  are done.
2431 
2432 Arguments:
2433 
2434  DeviceObject - Pointer to the file system device object.
2435 
2436  Irp - Pointer to the associated Irp which is being completed. (This
2437  Irp will no longer be accessible after this routine returns.)
2438 
2439  Contxt - The context parameter which was specified for all of
2440  the multiple asynch I/O requests for this MasterIrp.
2441 
2442 Return Value:
2443 
2444  The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
2445  immediately complete the Master Irp without being in a race condition
2446  with the IoCompleteRequest thread trying to decrement the IrpCount in
2447  the Master Irp.
2448 
2449 --*/
2450 
2451 {
2452 
2453  PFAT_IO_CONTEXT Context = Contxt;
2454  PIRP MasterIrp = Context->MasterIrp;
2455 
2456  DebugTrace(+1, Dbg, "FatMultiSyncCompletionRoutine, Context = %p\n", Context );
2457 
2458  //
2459  // If we got an error (or verify required), remember it in the Irp
2460  //
2461 
2462  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
2463 
2464 #if DBG
2465  if(!( NT_SUCCESS( FatBreakOnInterestingIoCompletion ) || Irp->IoStatus.Status != FatBreakOnInterestingIoCompletion )) {
2466  DbgBreakPoint();
2467  }
2468 #endif
2469 
2470 #ifdef SYSCACHE_COMPILE
2471  DbgPrint( "FAT SYSCACHE: MultiSync (IRP %08x for Master %08x) -> %08x\n", Irp, MasterIrp, Irp->IoStatus );
2472 #endif
2473 
2474  MasterIrp->IoStatus = Irp->IoStatus;
2475  }
2476 
2477  NT_ASSERT( !(NT_SUCCESS( Irp->IoStatus.Status ) && Irp->IoStatus.Information == 0 ));
2478 
2479  //
2480  // We must do this here since IoCompleteRequest won't get a chance
2481  // on this associated Irp.
2482  //
2483 
2484  IoFreeMdl( Irp->MdlAddress );
2485  IoFreeIrp( Irp );
2486 
2487  if (InterlockedDecrement(&Context->IrpCount) == 0) {
2488 
2489  FatDoCompletionZero( MasterIrp, Context );
2490  KeSetEvent( &Context->Wait.SyncEvent, 0, FALSE );
2491  }
2492 
2493  DebugTrace(-1, Dbg, "FatMultiSyncCompletionRoutine -> SUCCESS\n", 0 );
2494 
2496 
2498 }
2499 
2500 
2501 //
2502 // Internal Support Routine
2503 //
2504 
2505 NTSTATUS
2506 NTAPI
2509  _In_ PIRP Irp,
2510  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2511  )
2512 
2513 /*++
2514 
2515 Routine Description:
2516 
2517  This is the completion routine for all reads and writes started via
2518  FatRead/WriteMultipleAsynch. It must synchronize its operation for
2519  multiprocessor environments with itself on all other processors, via
2520  a spin lock found via the Context parameter.
2521 
2522  The completion routine has has the following responsibilities:
2523 
2524  If the individual request was completed with an error, then
2525  this completion routine must see if this is the first error
2526  (essentially by Vbo), and if so it must correctly reduce the
2527  byte count and remember the error status in the Context.
2528 
2529  If the IrpCount goes to 1, then it sets the event in the Context
2530  parameter to signal the caller that all of the asynch requests
2531  are done.
2532 
2533 Arguments:
2534 
2535  DeviceObject - Pointer to the file system device object.
2536 
2537  Irp - Pointer to the associated Irp which is being completed. (This
2538  Irp will no longer be accessible after this routine returns.)
2539 
2540  Contxt - The context parameter which was specified for all of
2541  the multiple asynch I/O requests for this MasterIrp.
2542 
2543 Return Value:
2544 
2545  The routine returns STATUS_MORE_PROCESSING_REQUIRED so that we can
2546  immediately complete the Master Irp without being in a race condition
2547  with the IoCompleteRequest thread trying to decrement the IrpCount in
2548  the Master Irp.
2549 
2550 --*/
2551 
2552 {
2554  PFAT_IO_CONTEXT Context = Contxt;
2555  PIRP MasterIrp = Context->MasterIrp;
2556  BOOLEAN PostRequest = FALSE;
2557 
2558  DebugTrace(+1, Dbg, "FatMultiAsyncCompletionRoutine, Context = %p\n", Context );
2559 
2560  //
2561  // If we got an error (or verify required), remember it in the Irp
2562  //
2563 
2564  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
2565 
2566 #if DBG
2567  if (!( NT_SUCCESS( FatBreakOnInterestingIoCompletion ) || Irp->IoStatus.Status != FatBreakOnInterestingIoCompletion )) {
2568  DbgBreakPoint();
2569  }
2570 #endif
2571 
2572 #ifdef SYSCACHE_COMPILE
2573  DbgPrint( "FAT SYSCACHE: MultiAsync (IRP %08x for Master %08x) -> %08x\n", Irp, MasterIrp, Irp->IoStatus );
2574 #endif
2575 
2576  MasterIrp->IoStatus = Irp->IoStatus;
2577 
2578  }
2579 
2580  NT_ASSERT( !(NT_SUCCESS( Irp->IoStatus.Status ) && Irp->IoStatus.Information == 0 ));
2581 
2582  if (InterlockedDecrement(&Context->IrpCount) == 0) {
2583 
2584  FatDoCompletionZero( MasterIrp, Context );
2585 
2586  if (NT_SUCCESS(MasterIrp->IoStatus.Status)) {
2587 
2588  MasterIrp->IoStatus.Information =
2589  Context->Wait.Async.RequestedByteCount;
2590 
2591  NT_ASSERT(MasterIrp->IoStatus.Information != 0);
2592 
2593  //
2594  // Now if this wasn't PagingIo, set either the read or write bit.
2595  //
2596 
2597  if (!FlagOn(MasterIrp->Flags, IRP_PAGING_IO)) {
2598 
2599  SetFlag( Context->Wait.Async.FileObject->Flags,
2600  IoGetCurrentIrpStackLocation(MasterIrp)->MajorFunction == IRP_MJ_READ ?
2602  }
2603 
2604  } else {
2605 
2606  //
2607  // Post STATUS_VERIFY_REQUIRED failures. Only post top level IRPs, because recursive I/Os
2608  // cannot process volume verification.
2609  //
2610 
2611  if (!FlagOn(Context->IrpContextFlags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) &&
2612  (MasterIrp->IoStatus.Status == STATUS_VERIFY_REQUIRED)) {
2613  PostRequest = TRUE;
2614  }
2615 
2616  }
2617 
2618  //
2619  // If this was a special async write, decrement the count. Set the
2620  // event if this was the final outstanding I/O for the file. We will
2621  // also want to queue an APC to deal with any error conditionions.
2622  //
2623  _Analysis_assume_(!(Context->Wait.Async.NonPagedFcb) &&
2624  (ExInterlockedAddUlong( &Context->Wait.Async.NonPagedFcb->OutstandingAsyncWrites,
2625  0xffffffff,
2626  &FatData.GeneralSpinLock ) != 1));
2627  if ((Context->Wait.Async.NonPagedFcb) &&
2628  (ExInterlockedAddUlong( &Context->Wait.Async.NonPagedFcb->OutstandingAsyncWrites,
2629  0xffffffff,
2630  &FatData.GeneralSpinLock ) == 1)) {
2631 
2632  KeSetEvent( Context->Wait.Async.NonPagedFcb->OutstandingAsyncEvent, 0, FALSE );
2633  }
2634 
2635  //
2636  // Now release the resources.
2637  //
2638 
2639  if (Context->Wait.Async.Resource != NULL) {
2640 
2641  ExReleaseResourceForThreadLite( Context->Wait.Async.Resource,
2642  Context->Wait.Async.ResourceThreadId );
2643  }
2644 
2645  if (Context->Wait.Async.Resource2 != NULL) {
2646 
2647  ExReleaseResourceForThreadLite( Context->Wait.Async.Resource2,
2648  Context->Wait.Async.ResourceThreadId );
2649  }
2650 
2651  //
2652  // Mark the master Irp pending
2653  //
2654 
2655  IoMarkIrpPending( MasterIrp );
2656 
2657  //
2658  // and finally, free the context record.
2659  //
2660 
2661  ExFreePool( Context );
2662 
2663  if (PostRequest) {
2664 
2665  PIRP_CONTEXT IrpContext = NULL;
2666 
2667  _SEH2_TRY {
2668 
2669  IrpContext = FatCreateIrpContext(Irp, TRUE );
2670  ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL);
2671  FatFsdPostRequest( IrpContext, Irp );
2673 
2675 
2676  //
2677  // If we failed to post the IRP, we just have to return the failure
2678  // to the user. :(
2679  //
2680 
2681  NOTHING;
2682  } _SEH2_END;
2683  }
2684  }
2685 
2686  DebugTrace(-1, Dbg, "FatMultiAsyncCompletionRoutine -> SUCCESS\n", 0 );
2687 
2689 
2690  return Status;
2691 }
2692 
2693 
2694 NTSTATUS
2696  IN PIRP Irp,
2698  )
2699 
2700 /*++
2701 
2702 Routine Description:
2703 
2704  This routine attempts to guarantee that the media is marked dirty
2705  with the surface test bit if a paging file IO fails.
2706 
2707  The work done here has several basic problems
2708 
2709  1) when paging file writes start failing, this is a good sign
2710  that the rest of the system is about to fall down around us
2711 
2712  2) it has no forward progress guarantee
2713 
2714  With Whistler, it is actually quite intentional that we're rejiggering
2715  the paging file write path to make forward progress at all times. This
2716  means that the cases where it *does* fail, we're truly seeing media errors
2717  and this is probably going to mean the paging file is going to stop working
2718  very soon.
2719 
2720  It'd be nice to make this guarantee progress. It would need
2721 
2722  1) a guaranteed worker thread which can only be used by items which
2723  will make forward progress (i.e., not block out this one)
2724 
2725  2) the virtual volume file's pages containing the boot sector and
2726  1st FAT entry would have to be pinned resident and have a guaranteed
2727  mapping address
2728 
2729  3) mark volume would have to have a stashed irp/mdl and roll the write
2730  irp, or use a generalized mechanism to guarantee issue of the irp
2731 
2732  4) the lower stack would have to guarantee progress
2733 
2734  Of these, 1 and 4 may actually exist shortly.
2735 
2736 Arguments:
2737 
2738  Irp - Pointer to the associated Irp which is being failed.
2739 
2740  Event - Pointer to optional event to be signalled instead of completing
2741  the IRP
2742 
2743 Return Value:
2744 
2745  Returns STATUS_MORE_PROCESSING_REQUIRED if we managed to queue off the workitem,
2746  STATUS_SUCCESS otherwise.
2747 
2748 --*/
2749 
2750 {
2751  NTSTATUS Status;
2752 
2753  //
2754  // If this was a media error, we want to chkdsk /r the next time we boot.
2755  //
2756 
2757  if (FsRtlIsTotalDeviceFailure(Irp->IoStatus.Status)) {
2758 
2760 
2761  } else {
2762 
2764 
2765  //
2766  // We are going to try to mark the volume needing recover.
2767  // If we can't get pool, oh well....
2768  //
2769 
2770  Packet = ExAllocatePoolWithTag(NonPagedPoolNx, sizeof(CLEAN_AND_DIRTY_VOLUME_PACKET), ' taF');
2771 
2772  if ( Packet ) {
2773 
2775  Packet->Irp = Irp;
2776  Packet->Event = Event;
2777 
2778  ExInitializeWorkItem( &Packet->Item,
2780  Packet );
2781 
2782 #ifdef _MSC_VER
2783 #pragma prefast( suppress:28159, "prefast indicates this is obsolete, but it is ok for fastfat to use it" )
2784 #endif
2786 
2788 
2789  } else {
2790 
2792  }
2793  }
2794 
2795  return Status;
2796 }
2797 
2798 
2799 //
2800 // Internal Support Routine
2801 //
2802 
2803 NTSTATUS
2804 NTAPI
2807  _In_ PIRP Irp,
2808  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2809  )
2810 
2811 /*++
2812 
2813 Routine Description:
2814 
2815  This is the completion routine for all reads and writes started via
2816  FatPagingFileIo that reuse the master irp (that we have to catch
2817  on the way back). It is always invoked.
2818 
2819  The completion routine has has the following responsibility:
2820 
2821  If the error implies a media problem, it enqueues a
2822  worker item to write out the dirty bit so that the next
2823  time we run we will do a autochk /r. This is not forward
2824  progress guaranteed at the moment.
2825 
2826  Clean up the Mdl used for this partial request.
2827 
2828  Note that if the Irp is failing, the error code is already where
2829  we want it.
2830 
2831 Arguments:
2832 
2833  DeviceObject - Pointer to the file system device object.
2834 
2835  Irp - Pointer to the associated Irp which is being completed. (This
2836  Irp will no longer be accessible after this routine returns.)
2837 
2838  MasterIrp - Pointer to the master Irp.
2839 
2840 Return Value:
2841 
2842  Always returns STATUS_MORE_PROCESSING_REQUIRED.
2843 
2844 --*/
2845 
2846 {
2848 
2850 
2851  DebugTrace(+1, Dbg, "FatPagingFileCompletionRoutineCatch, Context = %p\n", Context );
2852 
2853  //
2854  // Cleanup the existing Mdl, perhaps by returning the reserve.
2855  //
2856 
2857  if (Irp->MdlAddress == FatReserveMdl) {
2858 
2859  MmPrepareMdlForReuse( Irp->MdlAddress );
2861 
2862  } else {
2863 
2864  IoFreeMdl( Irp->MdlAddress );
2865  }
2866 
2867  //
2868  // Restore the original Mdl.
2869  //
2870 
2871  Irp->MdlAddress = Context->RestoreMdl;
2872 
2873  DebugTrace(-1, Dbg, "FatPagingFileCompletionRoutine => (done)\n", 0 );
2874 
2875  //
2876  // If the IRP is succeeding or the failure handler did not post off the
2877  // completion, we're done and should set the event to let the master
2878  // know the IRP is his again.
2879  //
2880 
2881  if (NT_SUCCESS( Irp->IoStatus.Status ) ||
2883 
2884  KeSetEvent( &Context->Event, 0, FALSE );
2885  }
2886 
2888 
2889 }
2890 
2891 
2892 //
2893 // Internal Support Routine
2894 //
2895 
2896 NTSTATUS
2897 NTAPI
2900  _In_ PIRP Irp,
2901  _In_reads_opt_(_Inexpressible_("varies")) PVOID MasterIrp
2902  )
2903 
2904 /*++
2905 
2906 Routine Description:
2907 
2908  This is the completion routine for all reads and writes started via
2909  FatPagingFileIo. It should only be invoked on error or cancel.
2910 
2911  The completion routine has has the following responsibility:
2912 
2913  Since the individual request was completed with an error,
2914  this completion routine must stuff it into the master irp.
2915 
2916  If the error implies a media problem, it also enqueues a
2917  worker item to write out the dirty bit so that the next
2918  time we run we will do a autochk /r
2919 
2920 Arguments:
2921 
2922  DeviceObject - Pointer to the file system device object.
2923 
2924  Irp - Pointer to the associated Irp which is being completed. (This
2925  Irp will no longer be accessible after this routine returns.)
2926 
2927  MasterIrp - Pointer to the master Irp.
2928 
2929 Return Value:
2930 
2931  Always returns STATUS_SUCCESS.
2932 
2933 --*/
2934 
2935 {
2936  DebugTrace(+1, Dbg, "FatPagingFileCompletionRoutine, MasterIrp = %p\n", MasterIrp );
2937 
2938  //
2939  // If we got an error (or verify required), remember it in the Irp
2940  //
2941 
2942  NT_ASSERT( !NT_SUCCESS( Irp->IoStatus.Status ));
2943 
2944  //
2945  // If we were invoked with an assoicated Irp, copy the error over.
2946  //
2947 
2948  if (Irp != MasterIrp) {
2949 
2950  ((PIRP)MasterIrp)->IoStatus = Irp->IoStatus;
2951  }
2952 
2953  DebugTrace(-1, Dbg, "FatPagingFileCompletionRoutine => (done)\n", 0 );
2954 
2956 
2957  return FatPagingFileErrorHandler( Irp, NULL );
2958 }
2959 
2960 
2961 //
2962 // Internal Support Routine
2963 //
2964 
2965 NTSTATUS
2966 NTAPI
2969  _In_ PIRP Irp,
2970  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2971  )
2972 
2973 /*++
2974 
2975 Routine Description:
2976 
2977  This is the completion routine for a special set of sub irps
2978  that have to work at APC level.
2979 
2980  The completion routine has has the following responsibilities:
2981 
2982  It sets the event passed as the context to signal that the
2983  request is done.
2984 
2985  By doing this, the caller will be released before final APC
2986  completion with knowledge that the IRP is finished. Final
2987  completion will occur at an indeterminate time after this
2988  occurs, and by using this completion routine the caller expects
2989  to not have any output or status returned. A junk user Iosb
2990  should be used to capture the status without forcing Io to take
2991  an exception on NULL.
2992 
2993 Arguments:
2994 
2995  DeviceObject - Pointer to the file system device object.
2996 
2997  Irp - Pointer to the Irp for this request. (This Irp will no longer
2998  be accessible after this routine returns.)
2999 
3000  Contxt - The context parameter which was specified in the call to
3001  FatRead/WriteSingleAsynch.
3002 
3003 Return Value:
3004 
3005  Currently always returns STATUS_SUCCESS.
3006 
3007 --*/
3008 
3009 {
3010  PFAT_SYNC_CONTEXT SyncContext = (PFAT_SYNC_CONTEXT)Contxt;
3011 
3013 
3014  DebugTrace(+1, Dbg, "FatSpecialSyncCompletionRoutine, Context = %p\n", Contxt );
3015 
3016  SyncContext->Iosb = Irp->IoStatus;
3017 
3018  KeSetEvent( &SyncContext->Event, 0, FALSE );
3019 
3020  DebugTrace(-1, Dbg, "FatSpecialSyncCompletionRoutine -> STATUS_SUCCESS\n", 0 );
3021 
3023 
3024  return STATUS_SUCCESS;
3025 }
3026 
3027 
3028 //
3029 // Internal Support Routine
3030 //
3031 
3032 NTSTATUS
3033 NTAPI
3036  _In_ PIRP Irp,
3037  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
3038  )
3039 
3040 /*++
3041 
3042 Routine Description:
3043 
3044  This is the completion routine for all reads and writes started via
3045  FatRead/WriteSingleAsynch.
3046 
3047  The completion routine has has the following responsibilities:
3048 
3049  Copy the I/O status from the Irp to the Context, since the Irp
3050  will no longer be accessible.
3051 
3052  It sets the event in the Context parameter to signal the caller
3053  that all of the asynch requests are done.
3054 
3055 Arguments:
3056 
3057  DeviceObject - Pointer to the file system device object.
3058 
3059  Irp - Pointer to the Irp for this request. (This Irp will no longer
3060  be accessible after this routine returns.)
3061 
3062  Contxt - The context parameter which was specified in the call to
3063  FatRead/WriteSingleAsynch.
3064 
3065 Return Value:
3066 
3067  Currently always returns STATUS_SUCCESS.
3068 
3069 --*/
3070 
3071 {
3072  PFAT_IO_CONTEXT Context = Contxt;
3073 
3074  DebugTrace(+1, Dbg, "FatSingleSyncCompletionRoutine, Context = %p\n", Context );
3075 
3077 
3078  if (!NT_SUCCESS( Irp->IoStatus.Status )) {
3079 
3080 #if DBG
3081  if(!( NT_SUCCESS( FatBreakOnInterestingIoCompletion ) || Irp->IoStatus.Status != FatBreakOnInterestingIoCompletion )) {
3082  DbgBreakPoint();
3083  }
3084 #endif
3085 
3086  }
3087 
3088  NT_ASSERT( !(NT_SUCCESS( Irp->IoStatus.Status ) && Irp->IoStatus.Information == 0 ));
3089 
3090  KeSetEvent( &Context->Wait.SyncEvent, 0, FALSE );
3091 
3092  DebugTrace(-1, Dbg, "FatSingleSyncCompletionRoutine -> STATUS_MORE_PROCESSING_REQUIRED\n", 0 );
3093 
3095 
3097 }
3098 
3099 
3100 //
3101 // Internal Support Routine
3102 //
3103 
3104 NTSTATUS
3105 NTAPI
3108  _In_ PIRP Irp,
3109  _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
3110  )
3111 
3112 /*++
3113 
3114 Routine Description:
3115 
3116  This is the completion routine for all reads and writes started via
3117  FatRead/WriteSingleAsynch.
3118 
3119  The completion routine has has the following responsibilities:
3120 
3121  Copy the I/O status from the Irp to the Context, since the Irp
3122  will no longer be accessible.
3123 
3124  It sets the event in the Context parameter to signal the caller
3125  that all of the asynch requests are done.
3126 
3127 Arguments:
3128 
3129  DeviceObject - Pointer to the file system device object.
3130 
3131  Irp - Pointer to the Irp for this request. (This Irp will no longer
3132  be accessible after this routine returns.)
3133 
3134  Contxt - The context parameter which was specified in the call to
3135  FatRead/WriteSingleAsynch.
3136 
3137 Return Value:
3138 
3139  Currently always returns STATUS_SUCCESS.
3140 
3141 --*/
3142 
3143 {
3145 
3146  PFAT_IO_CONTEXT Context = Contxt;
3147  BOOLEAN PostRequest = FALSE;
3148 
3149  DebugTrace(+1, Dbg, "FatSingleAsyncCompletionRoutine, Context = %p\n", Context );
3150 
3151  //
3152  // Fill in the information field correctedly if this worked.
3153  //
3154 
3156 
3157  if (NT_SUCCESS(Irp->IoStatus.Status)) {
3158 
3159  NT_ASSERT( Irp->IoStatus.Information != 0 );
3160  Irp->IoStatus.Information = Context->Wait.Async.RequestedByteCount;
3161  NT_ASSERT( Irp->IoStatus.Information != 0 );
3162 
3163  //
3164  // Now if this wasn't PagingIo, set either the read or write bit.
3165  //
3166 
3167  if (!FlagOn(Irp->Flags, IRP_PAGING_IO)) {
3168 
3169  SetFlag( Context->Wait.Async.FileObject->Flags,
3170  IoGetCurrentIrpStackLocation(Irp)->MajorFunction == IRP_MJ_READ ?
3172  }
3173 
3174  } else {
3175 
3176 #if DBG
3177  if(!( NT_SUCCESS( FatBreakOnInterestingIoCompletion ) || Irp->IoStatus.Status != FatBreakOnInterestingIoCompletion )) {
3178  DbgBreakPoint();
3179  }
3180 #endif
3181 
3182 #ifdef SYSCACHE_COMPILE
3183  DbgPrint( "FAT SYSCACHE: SingleAsync (IRP %08x) -> %08x\n", Irp, Irp->IoStatus );
3184 #endif
3185 
3186  //
3187  // Post STATUS_VERIFY_REQUIRED failures. Only post top level IRPs, because recursive I/Os
3188  // cannot process volume verification.
3189  //
3190 
3191  if (!FlagOn(Context->IrpContextFlags, IRP_CONTEXT_FLAG_RECURSIVE_CALL) &&
3192  (Irp->IoStatus.Status == STATUS_VERIFY_REQUIRED)) {
3193  PostRequest = TRUE;
3194  }
3195 
3196  }
3197 
3198  //
3199  // If this was a special async write, decrement the count. Set the
3200  // event if this was the final outstanding I/O for the file. We will
3201  // also want to queue an APC to deal with any error conditionions.
3202  //
3203  _Analysis_assume_(!(Context->Wait.Async.NonPagedFcb) &&
3204  (ExInterlockedAddUlong( &Context->Wait.Async.NonPagedFcb->OutstandingAsyncWrites,
3205  0xffffffff,
3206  &FatData.GeneralSpinLock ) != 1));
3207 
3208  if ((Context->Wait.Async.NonPagedFcb) &&
3209  (ExInterlockedAddUlong( &Context->Wait.Async.NonPagedFcb->OutstandingAsyncWrites,
3210  0xffffffff,
3211  &FatData.GeneralSpinLock ) == 1)) {
3212 
3213  KeSetEvent( Context->Wait.Async.NonPagedFcb->OutstandingAsyncEvent, 0, FALSE );
3214  }
3215 
3216  //
3217  // Now release the resources
3218  //
3219 
3220  if (Context->Wait.Async.Resource != NULL) {
3221 
3222  ExReleaseResourceForThreadLite( Context->Wait.Async.Resource,
3223  Context->Wait.Async.ResourceThreadId );
3224  }
3225 
3226  if (Context->Wait.Async.Resource2 != NULL) {
3227 
3228  ExReleaseResourceForThreadLite( Context->Wait.Async.Resource2,
3229  Context->Wait.Async.ResourceThreadId );
3230  }
3231 
3232  //
3233  // Mark the Irp pending
3234  //
3235 
3236  IoMarkIrpPending( Irp );
3237 
3238  //
3239  // and finally, free the context record.
3240  //
3241 
3242  ExFreePool( Context );
3243 
3244  if (PostRequest) {
3245 
3246  PIRP_CONTEXT IrpContext = NULL;
3247 
3248  _SEH2_TRY {
3249 
3250  IrpContext = FatCreateIrpContext(Irp, TRUE );
3251  ClearFlag(IrpContext->Flags, IRP_CONTEXT_FLAG_RECURSIVE_CALL);
3252  FatFsdPostRequest( IrpContext, Irp );
3254 
3256 
3257  //
3258  // If we failed to post the IRP, we just have to return the failure
3259  // to the user. :(
3260  //
3261 
3262  NOTHING;
3263  } _SEH2_END;
3264  }
3265 
3266 
3267  DebugTrace(-1, Dbg, "FatSingleAsyncCompletionRoutine -> STATUS_MORE_PROCESSING_REQUIRED\n", 0 );
3268 
3270 
3271  return Status;
3272 }
3273 
3274 
3275 VOID
3277  IN PIRP_CONTEXT IrpContext,
3278  IN OUT PIRP Irp,
3281  )
3282 
3283 /*++
3284 
3285 Routine Description:
3286 
3287  This routine locks the specified buffer for the specified type of
3288  access. The file system requires this routine since it does not
3289  ask the I/O system to lock its buffers for direct I/O. This routine
3290  may only be called from the Fsd while still in the user context.
3291 
3292  Note that this is the *input/output* buffer.
3293 
3294 Arguments:
3295 
3296  Irp - Pointer to the Irp for which the buffer is to be locked.
3297 
3298  Operation - IoWriteAccess for read operations, or IoReadAccess for
3299  write operations.
3300 
3301  BufferLength - Length of user buffer.
3302 
3303 Return Value:
3304 
3305  None
3306 
3307 --*/
3308 
3309 {
3310  PMDL Mdl = NULL;
3311 
3312  PAGED_CODE();
3313 
3314  if (Irp->MdlAddress == NULL) {
3315 
3316  //
3317  // Allocate the Mdl, and Raise if we fail.
3318  //
3319 
3320  Mdl = IoAllocateMdl( Irp->UserBuffer, BufferLength, FALSE, FALSE, Irp );
3321 
3322  if (Mdl == NULL) {
3323 
3325  }
3326 
3327  //
3328  // Now probe the buffer described by the Irp. If we get an exception,
3329  // deallocate the Mdl and return the appropriate "expected" status.
3330  //
3331 
3332  _SEH2_TRY {
3333 
3334  MmProbeAndLockPages( Mdl,
3335  Irp->RequestorMode,
3336  Operation );
3337 
3339 
3340  NTSTATUS Status;
3341 
3343 
3344  IoFreeMdl( Mdl );
3345  Irp->MdlAddress = NULL;
3346 
3347  FatRaiseStatus( IrpContext,
3349  } _SEH2_END;
3350  }
3351 
3352  UNREFERENCED_PARAMETER( IrpContext );
3353 }
3354 
3355 
3356 PVOID
3358  IN PIRP_CONTEXT IrpContext,
3359  IN OUT PIRP Irp
3360  )
3361 
3362 /*++
3363 
3364 Routine Description:
3365 
3366  This routine conditionally maps the user buffer for the current I/O
3367  request in the specified mode. If the buffer is already mapped, it
3368  just returns its address.
3369 
3370  Note that this is the *input/output* buffer.
3371 
3372 Arguments:
3373 
3374  Irp - Pointer to the Irp for the request.
3375 
3376 Return Value:
3377 
3378  Mapped address
3379 
3380 --*/
3381 
3382 {
3383  UNREFERENCED_PARAMETER( IrpContext );
3384 
3385  PAGED_CODE();
3386 
3387  //
3388  // If there is no Mdl, then we must be in the Fsd, and we can simply
3389  // return the UserBuffer field from the Irp.
3390  //
3391 
3392  if (Irp->MdlAddress == NULL) {
3393 
3394  return Irp->UserBuffer;
3395 
3396  } else {
3397 
3398  PVOID Address = MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority | MdlMappingNoExecute );
3399 
3400  if (Address == NULL) {
3401 
3403  }
3404 
3405  return Address;
3406  }
3407 }
3408 
3409 
3410 PVOID
3412  IN PIRP_CONTEXT IrpContext,
3413  IN OUT PIRP Irp,
3415  )
3416 
3417 /*++
3418 
3419 Routine Description:
3420 
3421  This routine conditionally buffers the user buffer for the current I/O
3422  request. If the buffer is already buffered, it just returns its address.
3423 
3424  Note that this is the *input* buffer.
3425 
3426 Arguments:
3427 
3428  Irp - Pointer to the Irp for the request.
3429 
3430  BufferLength - Length of user buffer.
3431 
3432 Return Value:
3433 
3434  Buffered address.
3435 
3436 --*/
3437 
3438 {
3439  PUCHAR UserBuffer;
3440 
3441  UNREFERENCED_PARAMETER( IrpContext );
3442 
3443  PAGED_CODE();
3444 
3445  //
3446  // Handle the no buffer case.
3447  //
3448 
3449  if (BufferLength == 0) {
3450 
3451  return NULL;
3452  }
3453 
3454  //
3455  // If there is no system buffer we must have been supplied an Mdl
3456  // describing the users input buffer, which we will now snapshot.
3457  //
3458 
3459  if (Irp->AssociatedIrp.SystemBuffer == NULL) {
3460 
3461  UserBuffer = FatMapUserBuffer( IrpContext, Irp );
3462 
3463  Irp->AssociatedIrp.SystemBuffer = FsRtlAllocatePoolWithQuotaTag( NonPagedPoolNx,
3464  BufferLength,
3466 
3467  //
3468  // Set the flags so that the completion code knows to deallocate the
3469  // buffer.
3470  //
3471 
3473 
3474  _SEH2_TRY {
3475 
3476  RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer,
3477  UserBuffer,
3478  BufferLength );
3479 
3481 
3482  NTSTATUS Status;
3483 
3485  FatRaiseStatus( IrpContext,
3487  } _SEH2_END;
3488  }
3489 
3490  return Irp->AssociatedIrp.SystemBuffer;
3491 }
3492 
3493 
3494 NTSTATUS
3496  IN PIRP_CONTEXT IrpContext,
3497  IN PVCB Vcb,
3498  IN BOOLEAN PreventRemoval
3499  )
3500 
3501 /*++
3502 
3503 Routine Description:
3504 
3505  The routine either enables or disables the eject button on removable
3506  media.
3507 
3508 Arguments:
3509 
3510  Vcb - Descibes the volume to operate on
3511 
3512  PreventRemoval - TRUE if we should disable the media eject button. FALSE
3513  if we want to enable it.
3514 
3515 Return Value:
3516 
3517  Status of the operation.
3518 
3519 --*/
3520 
3521 {
3522  PIRP Irp;
3523  KIRQL SavedIrql;
3524  NTSTATUS Status;
3525  FAT_SYNC_CONTEXT SyncContext;
3526  PREVENT_MEDIA_REMOVAL Prevent;
3527 
3528  UNREFERENCED_PARAMETER( IrpContext );
3529 
3530  //
3531  // If PreventRemoval is the same as VCB_STATE_FLAG_REMOVAL_PREVENTED,
3532  // no-op this call, otherwise toggle the state of the flag.
3533  //
3534 
3535  KeAcquireSpinLock( &FatData.GeneralSpinLock, &SavedIrql );
3536 
3537  if ((PreventRemoval ^
3539 
3540  KeReleaseSpinLock( &FatData.GeneralSpinLock, SavedIrql );
3541 
3542  return STATUS_SUCCESS;
3543 
3544  } else {
3545 
3547 
3548  KeReleaseSpinLock( &FatData.GeneralSpinLock, SavedIrql );
3549  }
3550 
3551  Prevent.PreventMediaRemoval = PreventRemoval;
3552 
3553  KeInitializeEvent( &SyncContext.Event, NotificationEvent, FALSE );
3554 
3555  //
3556  // We build this IRP using a junk Iosb that will receive the final
3557  // completion status since we won't be around for it.
3558  //
3559  // We fill in the UserIosb manually below,
3560  // So passing NULL for the final parameter is ok in this special case.
3561  //
3562 #ifdef _MSC_VER
3563 #pragma warning(suppress: 6387)
3564 #endif
3566  Vcb->TargetDeviceObject,
3567  &Prevent,
3568  sizeof(PREVENT_MEDIA_REMOVAL),
3569  NULL,
3570  0,
3571  FALSE,
3572  NULL,
3573  NULL );
3574 
3575  if ( Irp != NULL ) {
3576 
3577  //
3578  // Use our special completion routine which will remove the requirement that
3579  // the caller must be below APC level. All it tells us is that the Irp got
3580  // back, but will not tell us if it was succesful or not. We don't care,
3581  // and there is of course no fallback if the attempt to prevent removal
3582  // doesn't work for some mysterious reason.
3583  //
3584  // Normally, all IO is done at passive level. However, MM needs to be able
3585  // to issue IO with fast mutexes locked down, which raises us to APC. The
3586  // overlying IRP is set up to complete in yet another magical fashion even
3587  // though APCs are disabled, and any IRPage we do in these cases has to do
3588  // the same. Marking media dirty (and toggling eject state) is one.
3589  //
3590 
3591  Irp->UserIosb = &Irp->IoStatus;
3592 
3595  &SyncContext,
3596  TRUE,
3597  TRUE,
3598  TRUE );
3599 
3600  Status = IoCallDriver( Vcb->TargetDeviceObject, Irp );
3601 
3602  if (Status == STATUS_PENDING) {
3603 
3604  (VOID) KeWaitForSingleObject( &SyncContext.Event,
3605  Executive,
3606  KernelMode,
3607  FALSE,
3608  NULL );
3609 
3610  Status = SyncContext.Iosb.Status;
3611  }
3612 
3613  return Status;
3614  }
3615 
3617 }
3618 
3619 
3620 NTSTATUS
3622  IN PIRP_CONTEXT IrpContext,
3630  IN BOOLEAN OverrideVerify,
3632  )
3633 
3634 /*++
3635 
3636 Routine Description:
3637 
3638  This routine is called to perform DevIoCtrl functions internally within
3639  the filesystem. We take the status from the driver and return it to our
3640  caller.
3641 
3642 Arguments:
3643 
3644  IoControlCode - Code to send to driver.
3645 
3646  Device - This is the device to send the request to.
3647 
3648  OutPutBuffer - Pointer to output buffer.
3649 
3650  OutputBufferLength - Length of output buffer above.
3651 
3652  InternalDeviceIoControl - Indicates if this is an internal or external
3653  Io control code.
3654 
3655  OverrideVerify - Indicates if we should tell the driver not to return
3656  STATUS_VERIFY_REQUIRED for mount and verify.
3657 
3658  Iosb - If specified, we return the results of the operation here.
3659 
3660 Return Value:
3661 
3662  NTSTATUS - Status returned by next lower driver.
3663 
3664 --*/
3665 
3666 {
3667  NTSTATUS Status;
3668  PIRP Irp;
3669  KEVENT Event;
3670  IO_STATUS_BLOCK LocalIosb;
3671  PIO_STATUS_BLOCK IosbToUse = &LocalIosb;
3672 
3673  PAGED_CODE();
3674 
3675  UNREFERENCED_PARAMETER( IrpContext );
3676 
3677  //
3678  // Check if the user gave us an Iosb.
3679  //
3680 
3681  if (ARGUMENT_PRESENT( Iosb )) {
3682 
3683  IosbToUse = Iosb;
3684  }
3685 
3686  IosbToUse->Status = 0;
3687  IosbToUse->Information = 0;
3688 
3690 
3692  Device,
3693  InputBuffer,
3695  OutputBuffer,
3698  &Event,
3699  IosbToUse );
3700 
3701  if (Irp == NULL) {
3702 
3704  }
3705 
3706  if (OverrideVerify) {
3707 
3709  }
3710 
3711  Status = IoCallDriver( Device, Irp );
3712 
3713  //
3714  // We check for device not ready by first checking Status
3715  // and then if status pending was returned, the Iosb status
3716  // value.
3717  //
3718 
3719  if (Status == STATUS_PENDING) {
3720 
3722  Executive,
3723  KernelMode,
3724  FALSE,
3725  (PLARGE_INTEGER)NULL );
3726 
3727  Status = IosbToUse->Status;
3728  }
3729 
3730  return Status;
3731 }
3732 
3733 PMDL
3735  __in PIRP_CONTEXT IrpContext,
3736  __in ULONG Length
3737  )
3738 /*++
3739 
3740 Routine Description:
3741 
3742  Create an efficient mdl that describe a given length of zeros. We'll only
3743  use a one page buffer and make a mdl that maps all the pages back to the single
3744  physical page. We'll default to a smaller size buffer down to 1 PAGE if memory
3745  is tight. The caller should check the Mdl->ByteCount to see the true size
3746 
3747 Arguments:
3748 
3749  Length - The desired length of the zero buffer. We may return less than this
3750 
3751 Return Value:
3752 
3753  a MDL if successful / NULL if not
3754 
3755 --*/
3756 
3757 {
3758  PMDL ZeroMdl;
3759  ULONG SavedByteCount;
3760  PPFN_NUMBER Page;
3761  ULONG i;
3762 
3763  UNREFERENCED_PARAMETER( IrpContext );
3764 
3765  //
3766  // Spin down trying to get an MDL which can describe our operation.
3767  //
3768 
3769  while (TRUE) {
3770 
3771  ZeroMdl = IoAllocateMdl( FatData.ZeroPage, Length, FALSE, FALSE, NULL );
3772 
3773  //
3774  // Throttle ourselves to what we've physically allocated. Note that
3775  // we could have started with an odd multiple of this number. If we
3776  // tried for exactly that size and failed, we're toast.
3777  //
3778 
3779  if (ZeroMdl || (Length <= PAGE_SIZE)) {
3780 
3781  break;
3782  }
3783 
3784  //
3785  // Fallback by half and round down to a page multiple.
3786  //
3787 
3788  ASSERT( IrpContext->Vcb->Bpb.BytesPerSector <= PAGE_SIZE );
3790  if (Length < PAGE_SIZE) {
3791  Length = PAGE_SIZE;
3792  }
3793  }
3794 
3795  if (ZeroMdl == NULL) {
3796  return NULL;
3797  }
3798 
3799  //
3800  // If we have throttled all the way down, stop and just build a
3801  // simple MDL describing our previous allocation.
3802  //
3803 
3804  if (Length == PAGE_SIZE) {
3805 
3806  MmBuildMdlForNonPagedPool( ZeroMdl );
3807  return ZeroMdl;
3808  }
3809 
3810  //
3811  // Now we will temporarily lock the allocated pages
3812  // only, and then replicate the page frame numbers through
3813  // the entire Mdl to keep writing the same pages of zeros.
3814  //
3815  // It would be nice if Mm exported a way for us to not have
3816  // to pull the Mdl apart and rebuild it ourselves, but this
3817  // is so bizarre a purpose as to be tolerable.
3818  //
3819 
3820  SavedByteCount = ZeroMdl->ByteCount;
3821  ZeroMdl->ByteCount = PAGE_SIZE;
3822  MmBuildMdlForNonPagedPool( ZeroMdl );
3823 
3824  ZeroMdl->MdlFlags &= ~MDL_SOURCE_IS_NONPAGED_POOL;
3825  ZeroMdl->MdlFlags |= MDL_PAGES_LOCKED;
3826  ZeroMdl->MappedSystemVa = NULL;
3827  ZeroMdl->StartVa = NULL;
3828  ZeroMdl->ByteCount = SavedByteCount;
3829  Page = MmGetMdlPfnArray( ZeroMdl );
3830  for (i = 1; i < (ADDRESS_AND_SIZE_TO_SPAN_PAGES( 0, SavedByteCount )); i++) {
3831  *(Page + i) = *(Page);
3832  }
3833 
3834 
3835  return ZeroMdl;
3836 }
3837 
3838 
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
Definition: util.c:115
_Requires_lock_held_(_Global_critical_region_)
Definition: deviosup.c:102
signed char * PCHAR
Definition: retypes.h:7
#define VCB_STATE_FLAG_REMOVAL_PREVENTED
Definition: fatstruc.h:570
struct _FAT_SYNC_CONTEXT * PFAT_SYNC_CONTEXT
#define IN
Definition: typedefs.h:39
ULONG NonCachedReadBytes
Definition: winioctl.h:681
#define TAG_IO_RUNS
Definition: nodetype.h:168
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1221
ULONG NonCachedWrites
Definition: winioctl.h:682
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:717
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
PVOID ZeroPage
Definition: fatstruc.h:162
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
PVOID FatMapUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp)
Definition: deviosup.c:3357
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG IoControlCode
Definition: fltkernel.h:1383
struct _FILE_SYSTEM_STATISTICS * Statistics
Definition: fatstruc.h:505
_In_ PIRP _In_ PDEVICE_OBJECT Device
Definition: fatprocs.h:2029
#define MmGetMdlPfnArray(_Mdl)
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1548
#define DebugDoit(X)
Definition: fatdata.h:316
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define DbgPrint
Definition: loader.c:25
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
ULONG NonCachedReads
Definition: winioctl.h:680
#define MmGetMdlVirtualAddress(_Mdl)
_In_ PIRP Irp
Definition: csq.h:116
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:323
Definition: cdstruc.h:908
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
LOGICAL FatDiskAccountingEnabled
Definition: fatdata.c:129
BOOLEAN NTAPI FsRtlIsTotalDeviceFailure(IN NTSTATUS NtStatus)
Definition: filter.c:37
PMDL FatBuildZeroMdl(__in PIRP_CONTEXT IrpContext, __in ULONG Length)
Definition: deviosup.c:3734
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1079
VOID FatLockUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN LOCK_OPERATION Operation, IN ULONG BufferLength)
Definition: deviosup.c:3276
ULONG32 VBO
Definition: fat.h:38
unsigned char * PUCHAR
Definition: retypes.h:3
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 NTSTATUS
Definition: precomp.h:26
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
KSPIN_LOCK GeneralSpinLock
Definition: fatstruc.h:151
IN PFCB IN VBO OUT PLBO Lbo
Definition: fatprocs.h:306
#define ExRaiseStatus
Definition: ntoskrnl.h:96
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG _In_ ULONG OutputBufferLength
Definition: fltkernel.h:1374
Definition: cdstruc.h:504
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1439
IO_COMPLETION_ROUTINE FatSingleAsyncCompletionRoutine
Definition: deviosup.c:108
IO_STATUS_BLOCK IoStatus
VOID FatWaitSync(IN PIRP_CONTEXT IrpContext)
Definition: deviosup.c:2367
PVOID NTAPI FsRtlAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:189
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:775
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2974
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
void DbgBreakPoint()
Definition: mach.c:553
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
PVOID FatBufferUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN ULONG BufferLength)
Definition: deviosup.c:3411
ULONG NonCachedDiskWrites
Definition: winioctl.h:685
CHAR InputBuffer[80]
Definition: conmgr.c:33
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3167
IN PIRP IN PFCB IN ULONG IN ULONG IN ULONG UserByteCount
Definition: fatprocs.h:589
_SEH2_TRY
Definition: create.c:4226
ULONG NonCachedWriteBytes
Definition: winioctl.h:683
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:498
FAT_STATISTICS Fat
Definition: fatstruc.h:601
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:337
#define FAT_RESERVE_MDL_SIZE
Definition: fatdata.h:70
UCHAR KIRQL
Definition: env_spec_w32.h:591
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
ULONG * PPFN_NUMBER
Definition: ke.h:8
#define FO_FILE_MODIFIED
Definition: iotypes.h:1745
IN PFCB FcbOrDcb
Definition: fatprocs.h:306
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN OUT PBOOLEAN EndOnMax
Definition: fatprocs.h:306
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
LARGE_INTEGER Fat30Milliseconds
Definition: fatdata.c:70
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define IO_DISK_INCREMENT
Definition: iotypes.h:568
NTSTATUS(* NTAPI)(IN PFILE_FULL_EA_INFORMATION EaBuffer, IN ULONG EaLength, OUT PULONG ErrorOffset)
Definition: IoEaTest.cpp:117
ULONG NumberProcessors
Definition: fatstruc.h:80
BOOLEAN FatLookupMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN VBO Vbo, OUT PLBO Lbo, OUT PULONG ByteCount OPTIONAL, OUT PULONG Index OPTIONAL)
Definition: fsctrl.c:418
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1194
#define FO_FILE_FAST_IO_READ
Definition: iotypes.h:1752
VOID FatPagingFileIo(IN PIRP Irp, IN PFCB Fcb)
Definition: deviosup.c:211
long LONG
Definition: pedump.c:60
VOID FatSingleNonAlignedSync(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PUCHAR Buffer, IN LBO Lbo, IN ULONG ByteCount, IN PIRP Irp)
Definition: deviosup.c:2171
_In_ ULONG BufferLength
Definition: usbdlib.h:225
LONGLONG LBO
Definition: fat.h:34
NTSTATUS NTAPI KeDelayExecutionThread(IN KPROCESSOR_MODE WaitMode, IN BOOLEAN Alertable, IN PLARGE_INTEGER Interval OPTIONAL)
Definition: wait.c:283
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
_In_ PVOID _In_ ULONG Event
Definition: iotypes.h:435
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:11
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
static WCHAR Address[46]
Definition: ping.c:68
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:13
#define MDL_SOURCE_IS_NONPAGED_POOL
Definition: mmtypes.h:20
#define IoCompleteRequest
Definition: irp.c:1240
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1780
Definition: bufpool.h:45
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID OutputBuffer
Definition: iofuncs.h:713
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
Definition: irp.c:1925
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2289
#define CollectDiskIoStats(VCB, FUNCTION, IS_USER_IO, COUNT)
Definition: deviosup.c:30
NTSTATUS FatPerformDevIoCtrl(IN PIRP_CONTEXT IrpContext, IN ULONG IoControlCode, IN PDEVICE_OBJECT Device, IN PVOID InputBuffer OPTIONAL, IN ULONG InputBufferLength, OUT PVOID OutputBuffer OPTIONAL, IN ULONG OutputBufferLength, IN BOOLEAN InternalDeviceIoControl, IN BOOLEAN OverrideVerify, OUT PIO_STATUS_BLOCK Iosb OPTIONAL)
Definition: deviosup.c:3621
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define IRP_CONTEXT_FLAG_USER_IO
Definition: ext2fs.h:1086
IO_STATUS_BLOCK Iosb
Definition: deviosup.c:53
NTSTATUS FatToggleMediaEjectDisable(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN PreventRemoval)
Definition: deviosup.c:3495
#define DebugUnwind(X)
Definition: fatdata.h:315
FAT_DATA FatData
Definition: fatdata.c:56
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
ULONG NonCachedDiskReads
Definition: winioctl.h:684
return Iosb
Definition: create.c:4402
PDEVICE_OBJECT TargetDeviceObject
Definition: cdstruc.h:523
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
#define STATUS_PENDING
Definition: ntstatus.h:82
#define try_return(S)
Definition: cdprocs.h:2189
char CCHAR
Definition: typedefs.h:51
KEVENT FatReserveEvent
Definition: fatdata.c:123
uint64_t ULONGLONG
Definition: typedefs.h:66
#define ARGUMENT_PRESENT(ArgumentPointer)
#define Vcb
Definition: cdprocs.h:1425
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
USHORT BytesPerSector
Definition: fat.h:104
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:2867
struct FAT_PAGING_FILE_CONTEXT FAT_PAGING_FILE_CONTEXT
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
BOOLEAN FatGetNextMcbEntry(IN PVCB Vcb, IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PVBO Vbo, OUT PLBO Lbo, OUT PULONG ByteCount)
Definition: fsctrl.c:541
IO_COMPLETION_ROUTINE FatPagingFileCompletionRoutine
Definition: deviosup.c:118
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
struct _IRP * PIRP
IO_COMPLETION_ROUTINE FatSingleSyncCompletionRoutine
Definition: deviosup.c:98
struct FAT_PAGING_FILE_CONTEXT * PFAT_PAGING_FILE_CONTEXT
VOID NTAPI IoFreeMdl(PMDL Mdl)
Definition: iomdl.c:146
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define FAT_MAX_IO_RUNS_ON_STACK
Definition: fatdata.h:102
unsigned __int64 ULONG64
Definition: imports.h:198
CD_MCB Mcb
Definition: cdstruc.h:1022
BOOLEAN PreventMediaRemoval
Definition: ntddstor.h:251
#define InterlockedDecrement
Definition: armddk.h:52
NTSTATUS FatPagingFileErrorHandler(IN PIRP Irp, IN PKEVENT Event OPTIONAL)
Definition: deviosup.c:2695
IO_COMPLETION_ROUTINE FatMultiAsyncCompletionRoutine
Definition: deviosup.c:78
#define VOID
Definition: acefi.h:82
#define PAGE_SIZE
Definition: env_spec_w32.h:49
IO_COMPLETION_ROUTINE FatSpecialSyncCompletionRoutine
Definition: deviosup.c:88
#define NOTHING
Definition: env_spec_w32.h:461
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define Dbg
Definition: deviosup.c:28
VOID NTAPI ExSetResourceOwnerPointer(IN PERESOURCE Resource, IN PVOID OwnerPointer)
Definition: resource.c:2045
#define FatDoCompletionZero(I, C)
Definition: deviosup.c:171
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2647
#define MmPrepareMdlForReuse(_Mdl)
IN PVCB IN VBO StartingVbo
Definition: fatprocs.h:411
_Must_inspect_result_ _In_ PFILE_OBJECT _In_ ULONG _In_ ULONG InputBufferLength
Definition: fltkernel.h:1372
ClearFlag(Dirent->Flags, DIRENT_FLAG_NOT_PERSISTENT)
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1061
Status
Definition: gdiplustypes.h:24
PMDL NTAPI IoAllocateMdl(IN PVOID VirtualAddress, IN ULONG Length, IN BOOLEAN SecondaryBuffer, IN BOOLEAN ChargeQuota, IN PIRP Irp)
Definition: iomdl.c:22
#define _In_
Definition: no_sal2.h:204
IN PDEVICE_OBJECT DeviceObject
Definition: fatprocs.h:1569
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2745
#define TAG_IO_USER_BUFFER
Definition: nodetype.h:184
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
_SEH2_END
Definition: create.c:4400
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:170
WORKER_THREAD_ROUTINE FatFspMarkVolumeDirtyWithRecover
Definition: fatprocs.h:2000
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define IRP_BUFFERED_IO
IO_COMPLETION_ROUTINE FatMultiSyncCompletionRoutine
Definition: deviosup.c:68
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:935
enum _LOCK_OPERATION LOCK_OPERATION
#define ROUND_TO_PAGES(Size)
PMDL FatReserveMdl
Definition: fatdata.c:119
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
IO_COMPLETION_ROUTINE FatPagingFileCompletionRoutineCatch
Definition: deviosup.c:128
_SEH2_FINALLY
Definition: create.c:4371
NTSTATUS NTAPI IoCallDriver(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
Definition: irp.c:1218
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define IRP_PAGING_IO
#define TAG_IO_BUFFER
Definition: cdprocs.h:87
#define SL_WRITE_THROUGH
Definition: iotypes.h:1781
ULONG NTAPI ExInterlockedAddUlong(IN OUT PULONG Addend, IN ULONG Increment, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:88
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
#define _In_reads_opt_(size)
Definition: no_sal2.h:231
#define IRP_DEALLOCATE_BUFFER
BIOS_PARAMETER_BLOCK Bpb
Definition: fatstruc.h:335
struct _FAT_SYNC_CONTEXT FAT_SYNC_CONTEXT
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
#define OUT
Definition: typedefs.h:40
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
struct tagContext Context
Definition: acpixf.h:1034
unsigned int ULONG
Definition: retypes.h:1
#define IRP_CONTEXT_FLAG_RECURSIVE_CALL
Definition: fatstruc.h:1561
_In_ FLT_SET_CONTEXT_OPERATION Operation
Definition: fltkernel.h:1468
PVCB Vcb
Definition: cdstruc.h:939
VOID NTAPI ExReleaseResourceForThreadLite(IN PERESOURCE Resource, IN ERESOURCE_THREAD Thread)
Definition: resource.c:1844
#define BlockAlignTruncate(P, V)
Definition: fatprocs.h:3101
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
VOID FatMultipleAsync(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PIRP MasterIrp, IN ULONG MultipleIrpCount, IN PIO_RUN IoRuns)
Definition: deviosup.c:1622
_In_ ULONG SectorSize
Definition: halfuncs.h:291
#define IOCTL_DISK_MEDIA_REMOVAL
Definition: cdrw_usr.h:176
IN PIRP IN PFCB IN ULONG IN ULONG IN ULONG IN ULONG StreamFlags
Definition: fatprocs.h:589
#define KeGetCurrentThread
Definition: hal.h:44
struct _NAMED_PIPE_CREATE_PARAMETERS * Parameters
Definition: iotypes.h:2772
_In_ PFCB Fcb
Definition: cdprocs.h:151
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define IRP_CONTEXT_FLAG_OVERRIDE_VERIFY
Definition: fatstruc.h:1569
return STATUS_SUCCESS
Definition: btrfs.c:3014
IoMarkIrpPending(Irp)
#define __in
Definition: dbghelp.h:35
ULONG FcbState
Definition: cdstruc.h:977
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2632
IN PFCB IN VBO Vbo
Definition: fatprocs.h:306
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define FatUpdateIOCountersPCW(IsAWrite, Count)
Definition: deviosup.c:184
VOID FatSingleAsync(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN LBO Lbo, IN ULONG ByteCount, IN PIRP Irp)
Definition: deviosup.c:1990
VOID FatUpdateDiskStats(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN ULONG ByteCount)
Definition: deviosup.c:760
#define _Analysis_assume_(expr)
Definition: no_sal2.h:10
#define PAGED_CODE()
IN BOOLEAN Wait
Definition: fatprocs.h:1538
#define NT_ASSERT
Definition: rtlfuncs.h:3312
#define FatLowLevelReadWrite(IRPCONTEXT, DO, IRP, VCB)
Definition: deviosup.c:163
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68