ReactOS 0.4.15-dev-7961-gdcf9eb0
deviosup.c
Go to the documentation of this file.
1/*++
2
3Copyright (c) 1989-2000 Microsoft Corporation
4
5Module Name:
6
7 DevIoSup.c
8
9Abstract:
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
47typedef 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
68IO_COMPLETION_ROUTINE FatMultiSyncCompletionRoutine;
69
75 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
76 );
77
78IO_COMPLETION_ROUTINE FatMultiAsyncCompletionRoutine;
79
85 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
86 );
87
88IO_COMPLETION_ROUTINE FatSpecialSyncCompletionRoutine;
89
95 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
96 );
97
98IO_COMPLETION_ROUTINE FatSingleSyncCompletionRoutine;
99
101NTAPI
104 _In_ PIRP Irp,
105 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
106 );
107
109
111NTAPI
114 _In_ PIRP Irp,
115 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
116 );
117
118IO_COMPLETION_ROUTINE FatPagingFileCompletionRoutine;
119
121NTAPI
124 _In_ PIRP Irp,
125 _In_reads_opt_(_Inexpressible_("varies")) PVOID MasterIrp
126 );
127
129
131NTAPI
134 _In_ PIRP Irp,
135 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
136 );
137
138VOID
140 IN PIRP_CONTEXT IrpContext,
141 IN PVCB Vcb,
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
208
209
210VOID
212 IN PIRP Irp,
213 IN PFCB Fcb
214 )
215
216/*++
217
218Routine 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
224Arguments:
225
226 Irp - Supplies the requesting Irp.
227
228 Fcb - Supplies the file to act on.
229
230Return 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
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
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
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
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
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
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
759VOID
761 IN PIRP_CONTEXT IrpContext,
762 IN PIRP Irp,
764 )
765/*++
766
767Routine Description:
768
769 Charge appropriate process for the IO this IRP will cause.
770
771Arguments:
772
773 IrpContext- The Irp Context
774
775 Irp - Supplies the requesting Irp.
776
777 ByteCount - The lengh of the operation.
778
779Return 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_)
882FatNonCachedIo (
883 IN PIRP_CONTEXT IrpContext,
884 IN PIRP Irp,
890 )
891/*++
892
893Routine 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
899Arguments:
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
915Return 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
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;
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,
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
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_)
1294VOID
1295FatNonCachedNonAlignedRead (
1296 IN PIRP_CONTEXT IrpContext,
1297 IN PIRP Irp,
1301 )
1302
1303/*++
1304
1305Routine 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
1311Arguments:
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
1323Return 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
1342 ULONG OriginalByteCount;
1343 ULONG OriginalStartingVbo;
1344
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,
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,
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
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
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
1523 }
1524
1525 //
1526 // Now copy over the part of this last sector that we need.
1527 //
1528
1530
1531 UserBuffer += LastSectorVbo - OriginalStartingVbo;
1532
1533 RtlCopyMemory( UserBuffer, DiskBuffer, BytesToCopy );
1534
1536
1537 if ( ByteCount == 0 ) {
1538
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,
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
1621VOID
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
1632Routine 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
1660Arguments:
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
1674Return 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
1989VOID
1991 IN PIRP_CONTEXT IrpContext,
1992 IN PVCB Vcb,
1993 IN LBO Lbo,
1995 IN PIRP Irp
1996 )
1997
1998/*++
1999
2000Routine 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
2008Arguments:
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
2021Return 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
2170VOID
2172 IN PIRP_CONTEXT IrpContext,
2173 IN PVCB Vcb,
2175 IN LBO Lbo,
2177 IN PIRP Irp
2178 )
2179
2180/*++
2181
2182Routine 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
2191Arguments:
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
2206Return 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
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
2366VOID
2368 IN PIRP_CONTEXT IrpContext
2369 )
2370
2371/*++
2372
2373Routine 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
2378Arguments:
2379
2380Return 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
2405NTAPI
2408 _In_ PIRP Irp,
2409 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2410 )
2411
2412/*++
2413
2414Routine 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
2432Arguments:
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
2442Return 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
2506NTAPI
2509 _In_ PIRP Irp,
2510 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2511 )
2512
2513/*++
2514
2515Routine 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
2533Arguments:
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
2543Return 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,
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
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
2696 IN PIRP Irp,
2698 )
2699
2700/*++
2701
2702Routine 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
2736Arguments:
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
2743Return Value:
2744
2745 Returns STATUS_MORE_PROCESSING_REQUIRED if we managed to queue off the workitem,
2746 STATUS_SUCCESS otherwise.
2747
2748--*/
2749
2750{
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
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
2804NTAPI
2807 _In_ PIRP Irp,
2808 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2809 )
2810
2811/*++
2812
2813Routine 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
2831Arguments:
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
2840Return 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
2897NTAPI
2900 _In_ PIRP Irp,
2901 _In_reads_opt_(_Inexpressible_("varies")) PVOID MasterIrp
2902 )
2903
2904/*++
2905
2906Routine 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
2920Arguments:
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
2929Return 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
2958}
2959
2960
2961//
2962// Internal Support Routine
2963//
2964
2966NTAPI
2969 _In_ PIRP Irp,
2970 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
2971 )
2972
2973/*++
2974
2975Routine 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
2993Arguments:
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
3003Return 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
3033NTAPI
3036 _In_ PIRP Irp,
3037 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
3038 )
3039
3040/*++
3041
3042Routine 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
3055Arguments:
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
3065Return 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
3105NTAPI
3108 _In_ PIRP Irp,
3109 _In_reads_opt_(_Inexpressible_("varies")) PVOID Contxt
3110 )
3111
3112/*++
3113
3114Routine 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
3127Arguments:
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
3137Return 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,
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
3237
3238 //
3239 // and finally, free the context record.
3240 //
3241
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
3275VOID
3277 IN PIRP_CONTEXT IrpContext,
3278 IN OUT PIRP Irp,
3281 )
3282
3283/*++
3284
3285Routine 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
3294Arguments:
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
3303Return 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
3335 Irp->RequestorMode,
3336 Operation );
3337
3339
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
3356PVOID
3358 IN PIRP_CONTEXT IrpContext,
3359 IN OUT PIRP Irp
3360 )
3361
3362/*++
3363
3364Routine 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
3372Arguments:
3373
3374 Irp - Pointer to the Irp for the request.
3375
3376Return 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
3410PVOID
3412 IN PIRP_CONTEXT IrpContext,
3413 IN OUT PIRP Irp,
3415 )
3416
3417/*++
3418
3419Routine 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
3426Arguments:
3427
3428 Irp - Pointer to the Irp for the request.
3429
3430 BufferLength - Length of user buffer.
3431
3432Return 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,
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
3483
3485 FatRaiseStatus( IrpContext,
3487 } _SEH2_END;
3488 }
3489
3490 return Irp->AssociatedIrp.SystemBuffer;
3491}
3492
3493
3496 IN PIRP_CONTEXT IrpContext,
3497 IN PVCB Vcb,
3498 IN BOOLEAN PreventRemoval
3499 )
3500
3501/*++
3502
3503Routine Description:
3504
3505 The routine either enables or disables the eject button on removable
3506 media.
3507
3508Arguments:
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
3515Return Value:
3516
3517 Status of the operation.
3518
3519--*/
3520
3521{
3522 PIRP Irp;
3523 KIRQL SavedIrql;
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
3536
3537 if ((PreventRemoval ^
3539
3541
3542 return STATUS_SUCCESS;
3543
3544 } else {
3545
3547
3549 }
3550
3551 Prevent.PreventMediaRemoval = PreventRemoval;
3552
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
3622 IN PIRP_CONTEXT IrpContext,
3630 IN BOOLEAN OverrideVerify,
3632 )
3633
3634/*++
3635
3636Routine 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
3642Arguments:
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
3660Return Value:
3661
3662 NTSTATUS - Status returned by next lower driver.
3663
3664--*/
3665
3666{
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,
3698 &Event,
3699 IosbToUse );
3700
3701 if (Irp == NULL) {
3702
3704 }
3705
3706 if (OverrideVerify) {
3707
3709 }
3710
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,
3726
3727 Status = IosbToUse->Status;
3728 }
3729
3730 return Status;
3731}
3732
3733PMDL
3735 __in PIRP_CONTEXT IrpContext,
3737 )
3738/*++
3739
3740Routine 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
3747Arguments:
3748
3749 Length - The desired length of the zero buffer. We may return less than this
3750
3751Return Value:
3752
3753 a MDL if successful / NULL if not
3754
3755--*/
3756
3757{
3758 PMDL ZeroMdl;
3759 ULONG SavedByteCount;
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
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
static PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(PIRP Irp)
struct _IRP * PIRP
#define PAGED_CODE()
unsigned char BOOLEAN
#define VOID
Definition: acefi.h:82
#define InterlockedDecrement
Definition: armddk.h:52
LONG NTSTATUS
Definition: precomp.h:26
PEPROCESS __stdcall PsGetThreadProcess(_In_ PETHREAD Thread)
#define TAG_IO_BUFFER
Definition: cdprocs.h:95
_In_ PFCB Fcb
Definition: cdprocs.h:159
#define try_return(S)
Definition: cdprocs.h:2179
#define IOCTL_DISK_MEDIA_REMOVAL
Definition: cdrw_usr.h:176
#define IRP_CONTEXT_FLAG_WAIT
Definition: cdstruc.h:1215
VOLUME_DEVICE_OBJECT * PVOLUME_DEVICE_OBJECT
Definition: cdstruc.h:769
Definition: bufpool.h:45
#define _Requires_lock_held_(lock)
_In_ PIRP Irp
Definition: csq.h:116
#define __in
Definition: dbghelp.h:35
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
_In_ PIO_STACK_LOCATION IrpSp
Definition: create.c:4137
return Iosb
Definition: create.c:4402
LONGLONG LBO
Definition: fat.h:34
ULONG32 VBO
Definition: fat.h:38
#define TAG_IO_USER_BUFFER
Definition: nodetype.h:184
#define FatBugCheck(A, B, C)
Definition: nodetype.h:104
#define TAG_IO_RUNS
Definition: nodetype.h:168
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define ExReleaseResourceForThreadLite(res, thrdID)
Definition: env_spec_w32.h:635
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PsGetCurrentThread()
Definition: env_spec_w32.h:81
#define KeWaitForSingleObject(pEvt, foo, a, b, c)
Definition: env_spec_w32.h:478
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define KeReleaseSpinLock(sl, irql)
Definition: env_spec_w32.h:627
#define PAGE_SIZE
Definition: env_spec_w32.h:49
#define KeSetEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:476
#define KeAcquireSpinLock(sl, irql)
Definition: env_spec_w32.h:609
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define KeDelayExecutionThread(mode, foo, t)
Definition: env_spec_w32.h:484
#define PagedPool
Definition: env_spec_w32.h:308
VOID NTAPI KeClearEvent(IN PKEVENT Event)
Definition: eventobj.c:22
#define ClearFlag(_F, _SF)
Definition: ext2fs.h:191
#define SetFlag(_F, _SF)
Definition: ext2fs.h:187
#define FlagOn(_F, _SF)
Definition: ext2fs.h:179
#define IRP_CONTEXT_FLAG_USER_IO
Definition: ext2fs.h:1095
#define IRP_CONTEXT_FLAG_WRITE_THROUGH
Definition: ext2fs.h:1088
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
#define FatLowLevelReadWrite(IRPCONTEXT, DO, IRP, VCB)
Definition: deviosup.c:163
NTSTATUS FatToggleMediaEjectDisable(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN BOOLEAN PreventRemoval)
Definition: deviosup.c:3495
struct FAT_PAGING_FILE_CONTEXT * PFAT_PAGING_FILE_CONTEXT
PVOID FatBufferUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN ULONG BufferLength)
Definition: deviosup.c:3411
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
VOID FatUpdateDiskStats(IN PIRP_CONTEXT IrpContext, IN PIRP Irp, IN ULONG ByteCount)
Definition: deviosup.c:760
PVOID FatMapUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp)
Definition: deviosup.c:3357
#define FatDoCompletionZero(I, C)
Definition: deviosup.c:171
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
VOID FatMultipleAsync(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN PIRP MasterIrp, IN ULONG MultipleIrpCount, IN PIO_RUN IoRuns)
Definition: deviosup.c:1622
IO_COMPLETION_ROUTINE FatSpecialSyncCompletionRoutine
Definition: deviosup.c:88
NTSTATUS FatPagingFileErrorHandler(IN PIRP Irp, IN PKEVENT Event OPTIONAL)
Definition: deviosup.c:2695
IO_COMPLETION_ROUTINE FatPagingFileCompletionRoutineCatch
Definition: deviosup.c:128
PMDL FatBuildZeroMdl(__in PIRP_CONTEXT IrpContext, __in ULONG Length)
Definition: deviosup.c:3734
VOID FatWaitSync(IN PIRP_CONTEXT IrpContext)
Definition: deviosup.c:2367
VOID FatSingleAsync(IN PIRP_CONTEXT IrpContext, IN PVCB Vcb, IN LBO Lbo, IN ULONG ByteCount, IN PIRP Irp)
Definition: deviosup.c:1990
struct _FAT_SYNC_CONTEXT * PFAT_SYNC_CONTEXT
IO_COMPLETION_ROUTINE FatSingleAsyncCompletionRoutine
Definition: deviosup.c:108
VOID FatLockUserBuffer(IN PIRP_CONTEXT IrpContext, IN OUT PIRP Irp, IN LOCK_OPERATION Operation, IN ULONG BufferLength)
Definition: deviosup.c:3276
IO_COMPLETION_ROUTINE FatPagingFileCompletionRoutine
Definition: deviosup.c:118
#define CollectDiskIoStats(VCB, FUNCTION, IS_USER_IO, COUNT)
Definition: deviosup.c:30
#define Dbg
Definition: deviosup.c:28
IO_COMPLETION_ROUTINE FatMultiSyncCompletionRoutine
Definition: deviosup.c:68
struct _FAT_SYNC_CONTEXT FAT_SYNC_CONTEXT
VOID FatPagingFileIo(IN PIRP Irp, IN PFCB Fcb)
Definition: deviosup.c:211
IO_COMPLETION_ROUTINE FatMultiAsyncCompletionRoutine
Definition: deviosup.c:78
#define FatUpdateIOCountersPCW(IsAWrite, Count)
Definition: deviosup.c:184
IO_COMPLETION_ROUTINE FatSingleSyncCompletionRoutine
Definition: deviosup.c:98
KEVENT FatReserveEvent
Definition: fatdata.c:123
LARGE_INTEGER Fat30Milliseconds
Definition: fatdata.c:70
LOGICAL FatDiskAccountingEnabled
Definition: fatdata.c:129
ULONG FatExceptionFilter(IN PIRP_CONTEXT IrpContext, IN PEXCEPTION_POINTERS ExceptionPointer)
Definition: fatdata.c:204
FAT_DATA FatData
Definition: fatdata.c:56
PMDL FatReserveMdl
Definition: fatdata.c:119
#define FAT_RESERVE_MDL_SIZE
Definition: fatdata.h:70
#define DebugDoit(X)
Definition: fatdata.h:316
#define FAT_MAX_IO_RUNS_ON_STACK
Definition: fatdata.h:102
#define DebugTrace(INDENT, LEVEL, X, Y)
Definition: fatdata.h:313
#define DebugUnwind(X)
Definition: fatdata.h:315
#define BlockAlignTruncate(P, V)
Definition: fatprocs.h:3104
IN PVCB IN VBO StartingVbo
Definition: fatprocs.h:412
WORKER_THREAD_ROUTINE FatFspMarkVolumeDirtyWithRecover
Definition: fatprocs.h:2000
NTSTATUS FatFsdPostRequest(IN PIRP_CONTEXT IrpContext, IN PIRP Irp)
Definition: workque.c:229
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
IN PFCB IN VBO OUT PLBO Lbo
Definition: fatprocs.h:308
IN PIRP IN PFCB IN ULONG IN ULONG IN ULONG UserByteCount
Definition: fatprocs.h:593
IN PFCB FcbOrDcb
Definition: fatprocs.h:306
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
IN PIRP IN PFCB IN ULONG IN ULONG IN ULONG IN ULONG StreamFlags
Definition: fatprocs.h:595
IN PFCB IN VBO Vbo
Definition: fatprocs.h:307
IN PFCB IN VBO OUT PLBO OUT PULONG OUT PBOOLEAN OUT PBOOLEAN EndOnMax
Definition: fatprocs.h:311
#define FatRaiseStatus(IRPCONTEXT, STATUS)
Definition: fatprocs.h:2977
PIRP_CONTEXT FatCreateIrpContext(IN PIRP Irp, IN BOOLEAN Wait)
Definition: strucsup.c:2301
#define IRP_CONTEXT_FLAG_RECURSIVE_CALL
Definition: fatstruc.h:1566
#define IRP_CONTEXT_FLAG_OVERRIDE_VERIFY
Definition: fatstruc.h:1574
#define FCB_STATE_PAGING_FILE
Definition: fatstruc.h:1195
#define VCB_STATE_FLAG_REMOVAL_PREVENTED
Definition: fatstruc.h:571
#define _SEH2_FINALLY
Definition: filesup.c:21
#define _SEH2_END
Definition: filesup.c:22
#define _SEH2_TRY
Definition: filesup.c:19
FP_OP Operation
Definition: fpcontrol.c:150
#define FSRTL_MOD_WRITE_TOP_LEVEL_IRP
Definition: fsrtltypes.h:61
#define IoFreeMdl
Definition: fxmdl.h:89
#define IoAllocateMdl
Definition: fxmdl.h:88
Status
Definition: gdiplustypes.h:25
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
#define DbgPrint
Definition: hal.h:12
#define KeGetCurrentThread
Definition: hal.h:55
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
NTSYSAPI void WINAPI DbgBreakPoint(void)
#define NOTHING
Definition: input_list.c:10
ULONG NTAPI ExInterlockedAddUlong(IN OUT PULONG Addend, IN ULONG Increment, IN OUT PKSPIN_LOCK Lock)
Definition: interlocked.c:88
VOID NTAPI IoBuildPartialMdl(IN PMDL SourceMdl, IN PMDL TargetMdl, IN PVOID VirtualAddress, IN ULONG Length)
Definition: iomdl.c:96
IoMarkIrpPending(Irp)
#define IoSetCompletionRoutine(_Irp, _CompletionRoutine, _Context, _InvokeOnSuccess, _InvokeOnError, _InvokeOnCancel)
Definition: irp.cpp:490
VOID NTAPI MmProbeAndLockPages(IN PMDL Mdl, IN KPROCESSOR_MODE AccessMode, IN LOCK_OPERATION Operation)
Definition: mdlsup.c:931
VOID NTAPI MmUnlockPages(IN PMDL Mdl)
Definition: mdlsup.c:1435
VOID NTAPI MmBuildMdlForNonPagedPool(IN PMDL Mdl)
Definition: mdlsup.c:424
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
@ NormalPagePriority
Definition: imports.h:56
#define _In_reads_opt_(size)
Definition: ms_sal.h:320
#define _In_
Definition: ms_sal.h:308
#define _Analysis_assume_(expr)
Definition: ms_sal.h:2901
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1549
_In_ UINT _In_ UINT BytesToCopy
Definition: ndis.h:3168
#define KernelMode
Definition: asm.h:34
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:317
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
#define ARGUMENT_PRESENT(ArgumentPointer)
@ NotificationEvent
@ SynchronizationEvent
VOID NTAPI ExSetResourceOwnerPointer(IN PERESOURCE Resource, IN PVOID OwnerPointer)
Definition: resource.c:2050
BOOLEAN NTAPI FsRtlIsTotalDeviceFailure(IN NTSTATUS NtStatus)
Definition: filter.c:37
PVOID NTAPI FsRtlAllocatePoolWithTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:229
BOOLEAN NTAPI FsRtlIsNtstatusExpected(IN NTSTATUS NtStatus)
Definition: filter.c:61
PVOID NTAPI FsRtlAllocatePoolWithQuotaTag(IN POOL_TYPE PoolType, IN ULONG NumberOfBytes, IN ULONG Tag)
Definition: filter.c:189
_In_ PVOID _Out_opt_ BOOLEAN _Out_opt_ PPFN_NUMBER Page
Definition: mm.h:1306
#define ExRaiseStatus
Definition: ntoskrnl.h:114
#define IoCompleteRequest
Definition: irp.c:1240
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
PIRP NTAPI IoGetTopLevelIrp(VOID)
Definition: irp.c:1843
#define IoCallDriver
Definition: irp.c:1225
VOID NTAPI IoFreeIrp(IN PIRP Irp)
Definition: irp.c:1666
PIRP NTAPI IoMakeAssociatedIrp(IN PIRP Irp, IN CCHAR StackSize)
Definition: irp.c:1925
BOOLEAN NTAPI IoIsSystemThread(IN PETHREAD Thread)
Definition: util.c:115
#define STATUS_PENDING
Definition: ntstatus.h:82
long LONG
Definition: pedump.c:60
#define Vcb
Definition: cdprocs.h:1415
static WCHAR Address[46]
Definition: ping.c:68
#define _SEH2_AbnormalTermination()
Definition: pseh2_64.h:160
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:159
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:34
#define _SEH2_GetExceptionInformation()
Definition: pseh2_64.h:158
#define IRP_MJ_READ
Definition: rdpdr.c:46
#define IRP_MJ_WRITE
Definition: rdpdr.c:47
#define KeFlushIoBuffers(_Mdl, _ReadOperation, _DmaOperation)
Definition: ke.h:174
FORCEINLINE ULONG KeGetCurrentProcessorNumber(VOID)
Definition: ke.h:341
ULONG * PPFN_NUMBER
Definition: ke.h:9
#define STATUS_MORE_PROCESSING_REQUIRED
Definition: shellext.h:68
#define STATUS_SUCCESS
Definition: shellext.h:65
PULONG MinorVersion OPTIONAL
Definition: CrossNt.h:68
USHORT BytesPerSector
Definition: fat.h:104
ULONG NumberProcessors
Definition: fatstruc.h:81
KSPIN_LOCK GeneralSpinLock
Definition: fatstruc.h:152
PVOID ZeroPage
Definition: fatstruc.h:163
ULONG NonCachedReadBytes
Definition: winioctl.h:759
ULONG NonCachedDiskWrites
Definition: winioctl.h:763
ULONG NonCachedWriteBytes
Definition: winioctl.h:761
ULONG NonCachedReads
Definition: winioctl.h:758
ULONG NonCachedDiskReads
Definition: winioctl.h:762
ULONG NonCachedWrites
Definition: winioctl.h:760
IO_STATUS_BLOCK Iosb
Definition: deviosup.c:53
Definition: cdstruc.h:902
PVCB Vcb
Definition: cdstruc.h:933
CD_MCB Mcb
Definition: cdstruc.h:1016
ULONG FcbState
Definition: cdstruc.h:971
FAT_STATISTICS Fat
Definition: fatstruc.h:602
PDEVICE_OBJECT DeviceObject
Definition: iotypes.h:3223
union _IO_STACK_LOCATION::@1564 Parameters
struct _IO_STACK_LOCATION::@3978::@3982 Read
IO_STATUS_BLOCK IoStatus
BOOLEAN PreventMediaRemoval
Definition: ntddstor.h:343
Definition: cdstruc.h:498
struct _FILE_SYSTEM_STATISTICS * Statistics
Definition: fatstruc.h:506
PDEVICE_OBJECT TargetDeviceObject
Definition: cdstruc.h:517
BIOS_PARAMETER_BLOCK Bpb
Definition: fatstruc.h:336
#define NTAPI
Definition: typedefs.h:36
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define IN
Definition: typedefs.h:39
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
#define OUT
Definition: typedefs.h:40
char CCHAR
Definition: typedefs.h:51
char * PCHAR
Definition: typedefs.h:51
#define STATUS_INVALID_USER_BUFFER
Definition: udferr_usr.h:166
#define STATUS_VERIFY_REQUIRED
Definition: udferr_usr.h:130
#define STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_Must_inspect_result_ _In_ WDFDEVICE Device
Definition: wdfchildlist.h:474
_In_ PDEVICE_OBJECT DeviceObject
Definition: wdfdevice.h:2055
_In_ UCHAR MajorFunction
Definition: wdfdevice.h:1697
_Must_inspect_result_ _In_ WDFDEVICE _In_ DEVICE_REGISTRY_PROPERTY _In_ ULONG BufferLength
Definition: wdfdevice.h:3771
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_In_ WDFDPC _In_ BOOLEAN Wait
Definition: wdfdpc.h:170
_In_ WDFREQUEST _In_ size_t _In_ size_t _In_ ULONG IoControlCode
Definition: wdfio.h:325
_In_ WDFREQUEST _In_ size_t OutputBufferLength
Definition: wdfio.h:320
_In_ WDFREQUEST _In_ size_t _In_ size_t InputBufferLength
Definition: wdfio.h:322
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR OutputBuffer
Definition: wdfiotarget.h:863
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR InputBuffer
Definition: wdfiotarget.h:953
VOID NTAPI ExQueueWorkItem(IN PWORK_QUEUE_ITEM WorkItem, IN WORK_QUEUE_TYPE QueueType)
Definition: work.c:723
_Must_inspect_result_ _In_ ULONG Flags
Definition: wsk.h:170
#define ExInitializeWorkItem(Item, Routine, Context)
Definition: exfuncs.h:265
@ CriticalWorkQueue
Definition: extypes.h:189
_In_ ULONG SectorSize
Definition: halfuncs.h:291
__drv_aliasesMem FORCEINLINE PIO_STACK_LOCATION IoGetNextIrpStackLocation(_In_ PIRP Irp)
Definition: iofuncs.h:2695
FORCEINLINE VOID IoSetNextIrpStackLocation(_Inout_ PIRP Irp)
Definition: iofuncs.h:2680
_Must_inspect_result_ __drv_aliasesMem _In_ PDEVICE_OBJECT _In_opt_ PVOID _In_ ULONG _Out_opt_ PVOID _In_ ULONG _In_ BOOLEAN InternalDeviceIoControl
Definition: iofuncs.h:720
#define SL_OVERRIDE_VERIFY_VOLUME
Definition: iotypes.h:1823
#define IRP_DEALLOCATE_BUFFER
#define IRP_PAGING_IO
#define FO_FILE_FAST_IO_READ
Definition: iotypes.h:1795
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define FO_FILE_MODIFIED
Definition: iotypes.h:1788
#define IO_DISK_INCREMENT
Definition: iotypes.h:600
#define SL_WRITE_THROUGH
Definition: iotypes.h:1824
#define IRP_BUFFERED_IO
@ Executive
Definition: ketypes.h:415
enum _LOCK_OPERATION LOCK_OPERATION
@ IoReadAccess
Definition: ketypes.h:863
@ IoWriteAccess
Definition: ketypes.h:864
#define ROUND_TO_PAGES(Size)
#define MmGetMdlVirtualAddress(_Mdl)
#define MmGetSystemAddressForMdlSafe(_Mdl, _Priority)
#define MmPrepareMdlForReuse(_Mdl)
#define MmGetMdlPfnArray(_Mdl)
#define ADDRESS_AND_SIZE_TO_SPAN_PAGES(_Va, _Size)
#define MDL_PAGES_LOCKED
Definition: mmtypes.h:19
#define NT_ASSERT
Definition: rtlfuncs.h:3310