2 * PROJECT: ReactOS Kernel
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: ntoskrnl/fsrtl/fastio.c
5 * PURPOSE: Provides Fast I/O entrypoints to the Cache Manager
6 * PROGRAMMERS: Dominique Cote (buzdelabuz2@gmail.com)
7 * Alex Ionescu (alex.ionescu@reactos.org)
8 * Aleksey Bragin (aleksey@reactos.org)
11 /* INCLUDES ******************************************************************/
17 /* PUBLIC FUNCTIONS **********************************************************/
24 FsRtlIncrementCcFastReadResourceMiss(VOID
)
26 CcFastReadResourceMiss
++;
34 FsRtlIncrementCcFastReadNotPossible(VOID
)
36 CcFastReadNotPossible
++;
44 FsRtlIncrementCcFastReadWait(VOID
)
54 FsRtlIncrementCcFastReadNoWait(VOID
)
64 FsRtlCopyRead(IN PFILE_OBJECT FileObject
,
65 IN PLARGE_INTEGER FileOffset
,
70 OUT PIO_STATUS_BLOCK IoStatus
,
71 IN PDEVICE_OBJECT DeviceObject
)
74 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
76 PFAST_IO_DISPATCH FastIoDispatch
;
77 PDEVICE_OBJECT Device
;
78 BOOLEAN Result
= TRUE
;
79 ULONG PageCount
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset
, Length
);
83 ASSERT(FileObject
->FsContext
);
89 IoStatus
->Status
= STATUS_SUCCESS
;
90 IoStatus
->Information
= 0;
94 if (Length
> MAXLONGLONG
- FileOffset
->QuadPart
)
96 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
97 IoStatus
->Information
= 0;
101 /* Get the offset and FCB header */
102 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
103 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
107 /* Use a Resource Acquire */
108 FsRtlEnterFileSystem();
110 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
114 /* Acquire the resource without blocking. Return false and the I/O manager
115 * will retry using the standard IRP method. Use a Resource Acquire.
117 FsRtlEnterFileSystem();
118 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, FALSE
))
120 FsRtlExitFileSystem();
121 FsRtlIncrementCcFastReadResourceMiss();
126 /* Check if this is a fast I/O cached file */
127 if (!(FileObject
->PrivateCacheMap
) ||
128 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
130 /* It's not, so fail */
135 /* Check if we need to find out if fast I/O is available */
136 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
139 ASSERT(!KeIsExecutingDpc());
141 /* Get the Fast I/O table */
142 Device
= IoGetRelatedDeviceObject(FileObject
);
143 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
146 ASSERT(FastIoDispatch
!= NULL
);
147 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
149 /* Ask the driver if we can do it */
150 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
165 /* Check if we read too much */
166 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
168 /* We did, check if the file offset is past the end */
169 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
171 /* Set end of file */
172 IoStatus
->Status
= STATUS_END_OF_FILE
;
173 IoStatus
->Information
= 0;
177 /* Otherwise, just normalize the length */
178 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
181 /* Set this as top-level IRP */
182 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
186 /* Make sure the IO and file size is below 4GB */
187 if (Wait
&& !(Offset
.HighPart
| FcbHeader
->FileSize
.HighPart
))
190 /* Call the cache controller */
191 CcFastCopyRead(FileObject
,
198 /* File was accessed */
199 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
201 if (IoStatus
->Status
!= STATUS_END_OF_FILE
)
203 ASSERT((ULONGLONG
)FcbHeader
->FileSize
.QuadPart
>=
204 ((ULONGLONG
)FileOffset
->QuadPart
+ IoStatus
->Information
));
210 /* Call the cache controller */
211 Result
= CcCopyRead(FileObject
,
218 /* File was accessed */
219 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
223 ASSERT((IoStatus
->Status
== STATUS_END_OF_FILE
) ||
224 (((ULONGLONG
)FileOffset
->QuadPart
+ IoStatus
->Information
) <=
225 (ULONGLONG
)FcbHeader
->FileSize
.QuadPart
));
229 /* Update the current file offset */
232 FileObject
->CurrentByteOffset
.QuadPart
= FileOffset
->QuadPart
+ IoStatus
->Information
;
235 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
236 EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
)
242 PsGetCurrentThread()->TopLevelIrp
= 0;
244 /* Return to caller */
247 ExReleaseResourceLite(FcbHeader
->Resource
);
248 FsRtlExitFileSystem();
252 CcFastReadNotPossible
+= 1;
264 FsRtlCopyWrite(IN PFILE_OBJECT FileObject
,
265 IN PLARGE_INTEGER FileOffset
,
270 OUT PIO_STATUS_BLOCK IoStatus
,
271 IN PDEVICE_OBJECT DeviceObject
)
273 BOOLEAN Result
= TRUE
;
274 PFAST_IO_DISPATCH FastIoDispatch
;
275 PDEVICE_OBJECT Device
;
276 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
277 PSHARED_CACHE_MAP SharedCacheMap
;
280 * Offset == 0xffffffffffffffff indicates append to the end of file.
282 BOOLEAN FileOffsetAppend
= (FileOffset
->HighPart
== (LONG
)0xffffffff) &&
283 (FileOffset
->LowPart
== 0xffffffff);
285 BOOLEAN ResourceAcquiredShared
= FALSE
;
286 BOOLEAN b_4GB
= FALSE
;
287 BOOLEAN FileSizeModified
= FALSE
;
288 LARGE_INTEGER OldFileSize
;
289 LARGE_INTEGER OldValidDataLength
;
290 LARGE_INTEGER NewSize
;
291 LARGE_INTEGER Offset
;
296 ASSERT(FileObject
->FsContext
);
298 /* Initialize some of the vars and pointers */
299 NewSize
.QuadPart
= 0;
300 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
301 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
304 * Check with Cc if we can write and check if the IO > 64kB (WDK macro).
306 if ((CcCanIWrite(FileObject
, Length
, Wait
, FALSE
) == FALSE
) ||
307 (CcCopyWriteWontFlush(FileObject
, FileOffset
, Length
) == FALSE
) ||
308 ((FileObject
->Flags
& FO_WRITE_THROUGH
)))
313 /* Already init IO_STATUS_BLOCK */
314 IoStatus
->Status
= STATUS_SUCCESS
;
315 IoStatus
->Information
= Length
;
323 FsRtlEnterFileSystem();
326 * The CcFastCopyWrite doesn't deal with filesize beyond 4GB.
328 if (Wait
&& (FcbHeader
->AllocationSize
.HighPart
== 0))
330 /* If the file offset is not past the file size,
331 * then we can acquire the lock shared.
333 if ((FileOffsetAppend
== FALSE
) &&
334 (Offset
.LowPart
<= FcbHeader
->ValidDataLength
.LowPart
))
336 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
337 ResourceAcquiredShared
= TRUE
;
341 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
345 * If we append, use the file size as offset.
346 * Also, check that we aren't crossing the 4GB boundary.
348 if (FileOffsetAppend
!= FALSE
)
350 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
;
351 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
352 b_4GB
= (NewSize
.LowPart
< FcbHeader
->FileSize
.LowPart
);
357 Offset
.LowPart
= FileOffset
->LowPart
;
358 NewSize
.LowPart
= FileOffset
->LowPart
+ Length
;
359 b_4GB
= (NewSize
.LowPart
< FileOffset
->LowPart
) ||
360 (FileOffset
->HighPart
!= 0);
364 * Make sure that caching is initated.
365 * That fast are allowed for this file stream.
366 * That we are not extending past the allocated size.
367 * That we are not creating a hole bigger than 8k.
368 * That we are not crossing the 4GB boundary.
370 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
371 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
372 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
373 (Offset
.LowPart
< FcbHeader
->ValidDataLength
.LowPart
+ 0x2000) &&
376 /* If we are extending past the file size, we need to
377 * release the lock and acquire it exclusively, because
378 * we are going to need to update the FcbHeader.
380 if (ResourceAcquiredShared
&&
381 (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
+ 0x2000))
383 /* Then we need to acquire the resource exclusive */
384 ExReleaseResourceLite(FcbHeader
->Resource
);
385 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
386 if (FileOffsetAppend
!= FALSE
)
388 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
; // ??
389 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
391 /* Make sure we don't cross the 4GB boundary */
392 b_4GB
= (NewSize
.LowPart
< Offset
.LowPart
);
395 /* Recheck some of the conditions since we let the lock go */
396 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
397 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
398 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
399 (FcbHeader
->AllocationSize
.HighPart
== 0) &&
416 /* Check if we need to find out if fast I/O is available */
417 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
419 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
422 ASSERT(!KeIsExecutingDpc());
424 /* Get the Fast I/O table */
425 Device
= IoGetRelatedDeviceObject(FileObject
);
426 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
429 ASSERT(FastIoDispatch
!= NULL
);
430 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
432 /* Ask the driver if we can do it */
433 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
435 &FcbHeader
->FileSize
:
441 &FastIoCheckIfPossibleStatus
,
449 /* If we are going to extend the file then save
450 * the old file size in case the operation fails.
452 if (NewSize
.LowPart
> FcbHeader
->FileSize
.LowPart
)
454 FileSizeModified
= TRUE
;
455 OldFileSize
.LowPart
= FcbHeader
->FileSize
.LowPart
;
456 OldValidDataLength
.LowPart
= FcbHeader
->ValidDataLength
.LowPart
;
457 FcbHeader
->FileSize
.LowPart
= NewSize
.LowPart
;
460 /* Set this as top-level IRP */
461 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
465 if (Offset
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
467 LARGE_INTEGER OffsetVar
;
468 OffsetVar
.LowPart
= Offset
.LowPart
;
469 OffsetVar
.HighPart
= 0;
470 CcZeroData(FileObject
, &FcbHeader
->ValidDataLength
, &OffsetVar
, TRUE
);
473 /* Call the cache manager */
474 CcFastCopyWrite(FileObject
, Offset
.LowPart
, Length
, Buffer
);
476 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
477 EXCEPTION_EXECUTE_HANDLER
:
478 EXCEPTION_CONTINUE_SEARCH
)
484 /* Remove ourselves at the top level component after the IO is done */
485 PsGetCurrentThread()->TopLevelIrp
= 0;
487 /* Did the operation succeed? */
490 /* Update the valid file size if necessary */
491 if (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
493 FcbHeader
->ValidDataLength
.LowPart
= NewSize
.LowPart
;
496 /* Flag the file as modified */
497 FileObject
->Flags
|= FO_FILE_MODIFIED
;
499 /* Update the strucutres if the file size changed */
500 if (FileSizeModified
)
503 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
504 SharedCacheMap
->FileSize
.LowPart
= NewSize
.LowPart
;
505 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
508 /* Update the file object current file offset */
509 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.LowPart
;
514 /* Result == FALSE if we get here */
515 if (FileSizeModified
)
517 /* If the file size was modified then restore the old file size */
518 if (FcbHeader
->PagingIoResource
!= NULL
)
521 * Restore the old file size if operation didn't succeed.
523 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
524 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
525 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
526 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
530 /* If there is no lock and do it without */
531 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
532 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
545 LARGE_INTEGER OldFileSize
;
548 ASSERT(!KeIsExecutingDpc());
551 * Check if we need to acquire the resource exclusive.
553 if ((FileOffsetAppend
== FALSE
) &&
554 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
556 /* Acquire the resource shared */
557 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, Wait
))
559 goto LeaveCriticalAndFail
;
561 ResourceAcquiredShared
= TRUE
;
565 /* Acquire the resource exclusive */
566 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
568 goto LeaveCriticalAndFail
;
572 /* Check if we are appending */
573 if (FileOffsetAppend
!= FALSE
)
575 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
576 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
580 Offset
.QuadPart
= FileOffset
->QuadPart
;
581 NewSize
.QuadPart
+= FileOffset
->QuadPart
+ Length
;
585 * Make sure that caching is initated.
586 * That fast are allowed for this file stream.
587 * That we are not extending past the allocated size.
588 * That we are not creating a hole bigger than 8k.
590 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
591 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
592 (FcbHeader
->ValidDataLength
.QuadPart
+ 0x2000 > Offset
.QuadPart
) &&
593 (Length
<= MAXLONGLONG
- Offset
.QuadPart
) &&
594 (FcbHeader
->AllocationSize
.QuadPart
>= NewSize
.QuadPart
))
596 /* Check if we can keep the lock shared */
597 if (ResourceAcquiredShared
&&
598 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
600 ExReleaseResourceLite(FcbHeader
->Resource
);
601 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
603 goto LeaveCriticalAndFail
;
606 /* Compute the offset and the new filesize */
607 if (FileOffsetAppend
)
609 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
610 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
613 /* Recheck the above points since we released and reacquire the lock */
614 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
615 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
616 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
626 /* Check if we need to find out if fast I/O is available */
627 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
629 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
632 ASSERT(!KeIsExecutingDpc());
634 /* Get the Fast I/O table */
635 Device
= IoGetRelatedDeviceObject(FileObject
);
636 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
639 ASSERT(FastIoDispatch
!= NULL
);
640 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
642 /* Ask the driver if we can do it */
643 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
645 &FcbHeader
->FileSize
:
651 &FastIoCheckIfPossibleStatus
,
659 /* If we are going to modify the filesize,
660 * save the old fs in case the operation fails.
662 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
664 FileSizeModified
= TRUE
;
665 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
666 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
668 /* If the high part of the filesize is going
669 * to change, grab the Paging IoResouce.
671 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
672 FcbHeader
->PagingIoResource
)
674 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
675 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
676 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
680 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
685 * Set ourselves as top component.
687 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
691 BOOLEAN CallCc
= TRUE
;
693 /* Check if there is a gap between the end of the file
694 * and the offset. If yes, then we have to zero the data.
696 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
698 if (!(Result
= CcZeroData(FileObject
,
699 &FcbHeader
->ValidDataLength
,
703 /* If this operation fails, then we have to exit. We can't jump
704 * outside the SEH, so I am using a variable to exit normally.
710 /* Unless the CcZeroData failed, call the cache manager */
713 Result
= CcCopyWrite(FileObject
, &Offset
, Length
, Wait
, Buffer
);
716 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
717 EXCEPTION_EXECUTE_HANDLER
:
718 EXCEPTION_CONTINUE_SEARCH
)
724 /* Reset the top component */
725 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
727 /* Did the operation suceeded */
730 /* Check if we need to update the filesize */
731 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
733 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
734 FcbHeader
->PagingIoResource
)
736 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
737 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
738 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
742 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
746 /* Flag the file as modified */
747 FileObject
->Flags
|= FO_FILE_MODIFIED
;
749 /* Check if the filesize has changed */
750 if (FileSizeModified
)
752 /* Update the file sizes */
754 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
755 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
756 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
759 /* Update the current FO byte offset */
760 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.QuadPart
;
764 /* The operation did not succeed.
765 * Reset the file size to what it should be.
767 if (FileSizeModified
)
769 if (FcbHeader
->PagingIoResource
)
771 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
772 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
773 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
774 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
778 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
779 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
792 LeaveCriticalAndFail
:
794 FsRtlExitFileSystem();
799 ExReleaseResourceLite(FcbHeader
->Resource
);
800 FsRtlExitFileSystem();
805 ExReleaseResourceLite(FcbHeader
->Resource
);
806 FsRtlExitFileSystem();
815 FsRtlGetFileSize(IN PFILE_OBJECT FileObject
,
816 IN OUT PLARGE_INTEGER FileSize
)
818 FILE_STANDARD_INFORMATION Info
;
820 IO_STATUS_BLOCK IoStatus
;
821 PDEVICE_OBJECT DeviceObject
;
822 PFAST_IO_DISPATCH FastDispatch
;
824 PIO_STACK_LOCATION IoStackLocation
;
826 BOOLEAN OldHardError
;
830 /* Get Device Object and Fast Calls */
831 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
832 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
834 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo.
835 * Call the function and see if it succeeds.
838 !FastDispatch
->FastIoQueryStandardInfo
||
839 !FastDispatch
->FastIoQueryStandardInfo(FileObject
,
845 /* If any of the above failed, then we are going to send an
846 * IRP to the device object. Initialize the event for the IO.
848 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
850 /* Allocate the IRP */
851 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
855 return STATUS_INSUFFICIENT_RESOURCES
;
858 /* Don't process hard error */
859 OldHardError
= IoSetThreadHardErrorMode(FALSE
);
862 Irp
->UserIosb
= &IoStatus
;
863 Irp
->UserEvent
= &Event
;
864 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
865 Irp
->Flags
= IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
;
866 Irp
->RequestorMode
= KernelMode
;
867 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
868 Irp
->AssociatedIrp
.SystemBuffer
= &Info
;
870 /* Setup out stack location */
871 IoStackLocation
= Irp
->Tail
.Overlay
.CurrentStackLocation
;
873 IoStackLocation
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
874 IoStackLocation
->FileObject
= FileObject
;
875 IoStackLocation
->DeviceObject
= DeviceObject
;
876 IoStackLocation
->Parameters
.QueryFile
.Length
=
877 sizeof(FILE_STANDARD_INFORMATION
);
878 IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
=
879 FileStandardInformation
;
881 /* Send the IRP to the related device object */
882 Status
= IoCallDriver(DeviceObject
, Irp
);
884 /* Standard DDK IRP result processing */
885 if (Status
== STATUS_PENDING
)
887 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
890 /* If there was a synchronous error, signal it */
891 if (!NT_SUCCESS(Status
))
893 IoStatus
.Status
= Status
;
896 IoSetThreadHardErrorMode(OldHardError
);
899 /* Check the sync/async IO result */
900 if (NT_SUCCESS(IoStatus
.Status
))
902 /* Was the request for a directory? */
905 IoStatus
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
909 FileSize
->QuadPart
= Info
.EndOfFile
.QuadPart
;
913 return IoStatus
.Status
;
921 FsRtlMdlRead(IN PFILE_OBJECT FileObject
,
922 IN PLARGE_INTEGER FileOffset
,
926 OUT PIO_STATUS_BLOCK IoStatus
)
928 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
929 PFAST_IO_DISPATCH FastDispatch
;
931 /* Get Device Object and Fast Calls */
932 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
933 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
935 /* Check if we support Fast Calls, and check this one */
936 if (FastDispatch
&& FastDispatch
->MdlRead
)
938 /* Use the fast path */
939 return FastDispatch
->MdlRead(FileObject
,
948 /* Get the Base File System (Volume) and Fast Calls */
949 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
950 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
952 /* If the Base Device Object has its own FastDispatch Routine, fail */
953 if (FastDispatch
&& FastDispatch
->MdlRead
&& BaseDeviceObject
!= DeviceObject
)
958 /* No fast path, use slow path */
959 return FsRtlMdlReadDev(FileObject
,
973 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject
,
974 IN OUT PMDL MdlChain
)
976 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
977 PFAST_IO_DISPATCH FastDispatch
;
979 /* Get Device Object and Fast Calls */
980 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
981 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
983 /* Check if we support Fast Calls, and check this one */
984 if (FastDispatch
&& FastDispatch
->MdlReadComplete
)
986 /* Use the fast path */
987 return FastDispatch
->MdlReadComplete(FileObject
, MdlChain
, DeviceObject
);
990 /* Get the Base File System (Volume) and Fast Calls */
991 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
992 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
994 /* If the Base Device Object has its own FastDispatch Routine, fail */
995 if ((BaseDeviceObject
!= DeviceObject
) &&
997 FastDispatch
->MdlReadComplete
)
1002 /* No fast path, use slow path */
1003 return FsRtlMdlReadCompleteDev(FileObject
, MdlChain
, DeviceObject
);
1011 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject
,
1012 IN PMDL MemoryDescriptorList
,
1013 IN PDEVICE_OBJECT DeviceObject
)
1015 /* Call the Cache Manager */
1016 CcMdlReadComplete2(FileObject
, MemoryDescriptorList
);
1025 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject
,
1026 IN PLARGE_INTEGER FileOffset
,
1030 OUT PIO_STATUS_BLOCK IoStatus
,
1031 IN PDEVICE_OBJECT DeviceObject
)
1033 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1034 BOOLEAN Result
= TRUE
;
1035 LARGE_INTEGER Offset
;
1036 PFAST_IO_DISPATCH FastIoDispatch
;
1037 PDEVICE_OBJECT Device
;
1040 /* No actual read */
1043 /* Return success */
1044 IoStatus
->Status
= STATUS_SUCCESS
;
1045 IoStatus
->Information
= 0;
1050 ASSERT(MAXLONGLONG
- FileOffset
->QuadPart
>= (LONGLONG
)Length
);
1052 /* Get the offset and FCB header */
1053 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1054 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1057 FsRtlEnterFileSystem();
1058 CcFastMdlReadWait
++;
1061 ExAcquireResourceShared(FcbHeader
->Resource
, TRUE
);
1063 /* Check if this is a fast I/O cached file */
1064 if (!(FileObject
->PrivateCacheMap
) ||
1065 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
1067 /* It's not, so fail */
1068 CcFastMdlReadNotPossible
+= 1;
1073 /* Check if we need to find out if fast I/O is available */
1074 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1076 /* Get the Fast I/O table */
1077 Device
= IoGetRelatedDeviceObject(FileObject
);
1078 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1081 ASSERT(!KeIsExecutingDpc());
1082 ASSERT(FastIoDispatch
!= NULL
);
1083 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1085 /* Ask the driver if we can do it */
1086 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1095 /* It's not, fail */
1096 CcFastMdlReadNotPossible
+= 1;
1102 /* Check if we read too much */
1103 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1105 /* We did, check if the file offset is past the end */
1106 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
1108 /* Set end of file */
1109 IoStatus
->Status
= STATUS_END_OF_FILE
;
1110 IoStatus
->Information
= 0;
1114 /* Otherwise, just normalize the length */
1115 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
1118 /* Set this as top-level IRP */
1119 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1123 /* Attempt a read */
1124 CcMdlRead(FileObject
, FileOffset
, Length
, MdlChain
, IoStatus
);
1125 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
1127 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1128 EXCEPTION_EXECUTE_HANDLER
:
1129 EXCEPTION_CONTINUE_SEARCH
)
1136 /* Remove the top-level IRP flag */
1137 PsGetCurrentThread()->TopLevelIrp
= 0;
1139 /* Return to caller */
1142 ExReleaseResourceLite(FcbHeader
->Resource
);
1143 FsRtlExitFileSystem();
1153 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject
,
1154 IN PLARGE_INTEGER FileOffset
,
1157 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1158 PFAST_IO_DISPATCH FastDispatch
;
1160 /* Get Device Object and Fast Calls */
1161 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1162 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1164 /* Check if we support Fast Calls, and check this one */
1165 if (FastDispatch
&& FastDispatch
->MdlWriteComplete
)
1167 /* Use the fast path */
1168 return FastDispatch
->MdlWriteComplete(FileObject
,
1174 /* Get the Base File System (Volume) and Fast Calls */
1175 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1176 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1178 /* If the Base Device Object has its own FastDispatch Routine, fail */
1180 FastDispatch
->MdlWriteComplete
&&
1181 BaseDeviceObject
!= DeviceObject
)
1186 /* No fast path, use slow path */
1187 return FsRtlMdlWriteCompleteDev(FileObject
,
1198 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject
,
1199 IN PLARGE_INTEGER FileOffset
,
1201 IN PDEVICE_OBJECT DeviceObject
)
1203 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1208 /* Call the Cache Manager */
1209 CcMdlWriteComplete2(FileObject
, FileOffset
, MdlChain
);
1218 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject
,
1219 IN PLARGE_INTEGER FileOffset
,
1223 OUT PIO_STATUS_BLOCK IoStatus
)
1225 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1226 PFAST_IO_DISPATCH FastDispatch
;
1228 /* Get Device Object and Fast Calls */
1229 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1230 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1232 /* Check if we support Fast Calls, and check this one */
1233 if (FastDispatch
&& FastDispatch
->PrepareMdlWrite
)
1235 /* Use the fast path */
1236 return FastDispatch
->PrepareMdlWrite(FileObject
,
1245 /* Get the Base File System (Volume) and Fast Calls */
1246 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1247 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1249 /* If the Base Device Object has its own FastDispatch Routine, fail */
1251 FastDispatch
->PrepareMdlWrite
&&
1252 BaseDeviceObject
!= DeviceObject
)
1257 /* No fast path, use slow path */
1258 return FsRtlPrepareMdlWriteDev(FileObject
,
1272 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject
,
1273 IN PLARGE_INTEGER FileOffset
,
1277 OUT PIO_STATUS_BLOCK IoStatus
,
1278 IN PDEVICE_OBJECT DeviceObject
)
1280 BOOLEAN Result
= TRUE
;
1281 PFAST_IO_DISPATCH FastIoDispatch
;
1282 PDEVICE_OBJECT Device
;
1283 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1284 PSHARED_CACHE_MAP SharedCacheMap
;
1286 LARGE_INTEGER OldFileSize
;
1287 LARGE_INTEGER OldValidDataLength
;
1288 LARGE_INTEGER NewSize
;
1289 LARGE_INTEGER Offset
;
1292 * Offset == 0xffffffffffffffff indicates append to the end of file.
1294 BOOLEAN FileOffsetAppend
= (FileOffset
->HighPart
== (LONG
)0xffffffff) &&
1295 (FileOffset
->LowPart
== 0xffffffff);
1297 BOOLEAN FileSizeModified
= FALSE
;
1298 BOOLEAN ResourceAcquiredShared
= FALSE
;
1300 /* Initialize some of the vars and pointers */
1301 OldFileSize
.QuadPart
= 0;
1302 OldValidDataLength
.QuadPart
= 0;
1306 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1309 * Check with Cc if we can write.
1311 if (!CcCanIWrite(FileObject
, Length
, TRUE
, FALSE
) ||
1312 (FileObject
->Flags
& FO_WRITE_THROUGH
))
1317 IoStatus
->Status
= STATUS_SUCCESS
;
1319 /* No actual read */
1325 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1326 FsRtlEnterFileSystem();
1328 /* Check we are going to extend the file */
1329 if ((FileOffsetAppend
== FALSE
) &&
1330 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
1332 /* Acquire the resource shared */
1333 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
1334 ResourceAcquiredShared
= TRUE
;
1338 /* Acquire the resource exclusive */
1339 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1342 /* Check if we are appending */
1343 if (FileOffsetAppend
!= FALSE
)
1345 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1346 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1350 Offset
.QuadPart
= FileOffset
->QuadPart
;
1351 NewSize
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1354 if ((FileObject
->PrivateCacheMap
) &&
1355 (FcbHeader
->IsFastIoPossible
) &&
1356 (Length
<= MAXLONGLONG
- FileOffset
->QuadPart
) &&
1357 (NewSize
.QuadPart
<= FcbHeader
->AllocationSize
.QuadPart
))
1359 /* Check if we can keep the lock shared */
1360 if (ResourceAcquiredShared
&&
1361 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
1363 ExReleaseResourceLite(FcbHeader
->Resource
);
1364 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1366 /* Compute the offset and the new filesize */
1367 if (FileOffsetAppend
)
1369 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1370 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1373 /* Recheck the above points since we released and reacquire the lock */
1374 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
1375 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
1376 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
1382 goto FailAndCleanup
;
1386 /* Check if we need to find out if fast I/O is available */
1387 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1390 /* ASSERT(!KeIsExecutingDpc()); */
1392 /* Get the Fast I/O table */
1393 Device
= IoGetRelatedDeviceObject(FileObject
);
1394 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1397 ASSERT(FastIoDispatch
!= NULL
);
1398 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1400 /* Ask the driver if we can do it */
1401 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1410 /* It's not, fail */
1411 goto FailAndCleanup
;
1415 /* If we are going to modify the filesize,
1416 * save the old fs in case the operation fails.
1418 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1420 FileSizeModified
= TRUE
;
1421 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1422 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
1424 /* If the high part of the filesize is going
1425 * to change, grab the Paging IoResouce.
1427 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
1428 FcbHeader
->PagingIoResource
)
1430 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1431 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1432 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1436 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1442 * Set ourselves as top component.
1444 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1447 /* Check if there is a gap between the end of the file and the offset.
1448 * If yes, then we have to zero the data.
1450 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1452 Result
= CcZeroData(FileObject
,
1453 &FcbHeader
->ValidDataLength
,
1458 CcPrepareMdlWrite(FileObject
,
1467 CcPrepareMdlWrite(FileObject
, &Offset
, Length
, MdlChain
, IoStatus
);
1471 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1472 EXCEPTION_EXECUTE_HANDLER
:
1473 EXCEPTION_CONTINUE_SEARCH
)
1479 /* Reset the top component */
1480 PsGetCurrentThread()->TopLevelIrp
= 0;
1482 /* Did the operation suceeded */
1485 /* Check if we need to update the filesize */
1486 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1488 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
1489 FcbHeader
->PagingIoResource
)
1491 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1492 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1493 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1497 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1501 /* Flag the file as modified */
1502 FileObject
->Flags
|= FO_FILE_MODIFIED
;
1504 /* Check if the filesize has changed */
1505 if (FileSizeModified
)
1508 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
1509 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1510 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
1515 /* The operation did not succeed.
1516 * Reset the file size to what it should be.
1518 if (FileSizeModified
)
1520 if (FcbHeader
->PagingIoResource
)
1522 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1523 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1524 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1525 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1529 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1530 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1539 goto FailAndCleanup
;
1544 ExReleaseResourceLite(FcbHeader
->Resource
);
1545 FsRtlExitFileSystem();
1550 ExReleaseResourceLite(FcbHeader
->Resource
);
1551 FsRtlExitFileSystem();
1557 FsRtlAcquireFileExclusiveCommon(IN PFILE_OBJECT FileObject
,
1558 IN FS_FILTER_SECTION_SYNC_TYPE SyncType
,
1561 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1562 PDEVICE_OBJECT DeviceObject
;
1563 PFAST_IO_DISPATCH FastDispatch
;
1565 /* Get Device Object and Fast Calls */
1566 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1567 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1568 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1570 /* Get master FsRtl lock */
1571 FsRtlEnterFileSystem();
1573 /* Check if Fast Calls are supported, and check AcquireFileForNtCreateSection */
1575 FastDispatch
->AcquireFileForNtCreateSection
)
1577 /* Call the AcquireFileForNtCreateSection FastIo handler */
1578 FastDispatch
->AcquireFileForNtCreateSection(FileObject
);
1582 /* No FastIo handler, acquire file's resource exclusively */
1583 if (FcbHeader
&& FcbHeader
->Resource
) ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1586 return STATUS_SUCCESS
;
1594 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject
)
1598 /* Call the common routine. Don't care about the result */
1599 (VOID
)FsRtlAcquireFileExclusiveCommon(FileObject
, SyncTypeOther
, 0);
1607 FsRtlReleaseFile(IN PFILE_OBJECT FileObject
)
1609 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1610 PDEVICE_OBJECT DeviceObject
;
1611 PFAST_IO_DISPATCH FastDispatch
;
1613 /* Get Device Object and Fast Calls */
1614 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1615 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1616 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1618 /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
1620 FastDispatch
->ReleaseFileForNtCreateSection
)
1622 /* Call the ReleaseFileForNtCreateSection FastIo handler */
1623 FastDispatch
->ReleaseFileForNtCreateSection(FileObject
);
1627 /* No FastIo handler, release file's resource */
1628 if (FcbHeader
&& FcbHeader
->Resource
) ExReleaseResourceLite(FcbHeader
->Resource
);
1631 /* Release master FsRtl lock */
1632 FsRtlExitFileSystem();
1640 FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject
)
1642 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1643 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1644 PFAST_IO_DISPATCH FastDispatch
;
1647 /* Get the Base File System (Volume) and Fast Calls */
1648 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1649 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1650 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1651 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1653 /* Get master FsRtl lock */
1654 FsRtlEnterFileSystem();
1656 /* Check if Fast Calls are supported, and check AcquireForCcFlush */
1658 FastDispatch
->AcquireForCcFlush
)
1660 /* Call the AcquireForCcFlush FastIo handler */
1661 Status
= FastDispatch
->AcquireForCcFlush(FileObject
, BaseDeviceObject
);
1663 /* Return either success or inability to wait.
1664 In case of other failure - fall through */
1665 if (Status
== STATUS_SUCCESS
||
1666 Status
== STATUS_CANT_WAIT
)
1672 /* No FastIo handler (or it failed). Acquire Main resource */
1673 if (FcbHeader
->Resource
)
1675 /* Acquire it - either shared if it's already acquired
1676 or exclusively if we are the first */
1677 if (ExIsResourceAcquiredSharedLite(FcbHeader
->Resource
))
1678 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
1680 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1683 /* Also acquire its PagingIO resource */
1684 if (FcbHeader
->PagingIoResource
)
1685 ExAcquireResourceSharedLite(FcbHeader
->PagingIoResource
, TRUE
);
1687 return STATUS_SUCCESS
;
1695 FsRtlAcquireFileForCcFlush(IN PFILE_OBJECT FileObject
)
1699 /* Call the common routine. Don't care about the result */
1700 (VOID
)FsRtlAcquireFileForCcFlushEx(FileObject
);
1709 FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject
)
1711 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1712 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1713 PFAST_IO_DISPATCH FastDispatch
;
1714 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
1716 /* Get Device Object and Fast Calls */
1717 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1718 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1719 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1720 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1722 /* Check if Fast Calls are supported, and check ReleaseForCcFlush */
1724 FastDispatch
->ReleaseForCcFlush
)
1726 /* Call the ReleaseForCcFlush FastIo handler */
1727 Status
= FastDispatch
->ReleaseForCcFlush(FileObject
, BaseDeviceObject
);
1730 if (!NT_SUCCESS(Status
))
1732 /* No FastIo handler (or it failed). Release PagingIO resource and
1733 then Main resource */
1734 if (FcbHeader
->PagingIoResource
) ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1735 if (FcbHeader
->Resource
) ExReleaseResourceLite(FcbHeader
->Resource
);
1738 /* Release master FsRtl lock */
1739 FsRtlExitFileSystem();
1747 FsRtlAcquireFileForModWriteEx(IN PFILE_OBJECT FileObject
,
1748 IN PLARGE_INTEGER EndingOffset
,
1749 IN PERESOURCE
*ResourceToRelease
)
1751 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1752 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1753 PFAST_IO_DISPATCH FastDispatch
;
1754 PERESOURCE ResourceToAcquire
= NULL
;
1755 BOOLEAN Exclusive
= FALSE
;
1757 NTSTATUS Status
= STATUS_SUCCESS
;
1759 /* Get Device Object and Fast Calls */
1760 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1761 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1762 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1763 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1765 /* Check if Fast Calls are supported, and check AcquireForModWrite */
1767 FastDispatch
->AcquireForModWrite
)
1769 /* Call the AcquireForModWrite FastIo handler */
1770 Status
= FastDispatch
->AcquireForModWrite(FileObject
,
1775 /* Return either success or inability to wait.
1776 In case of other failure - fall through */
1777 if (Status
== STATUS_SUCCESS
||
1778 Status
== STATUS_CANT_WAIT
)
1784 Status
= STATUS_SUCCESS
;
1786 /* No FastIo handler, use algorithm from Nagar p.550. */
1787 if (!FcbHeader
->Resource
)
1789 *ResourceToRelease
= NULL
;
1790 return STATUS_SUCCESS
;
1793 /* Default condition - shared acquiring of Paging IO Resource */
1794 ResourceToAcquire
= FcbHeader
->PagingIoResource
;
1796 /* Decide on type of locking and type of resource based on historical magic
1797 well explain by Nagar in p. 550-551 */
1798 if ((EndingOffset
->QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
&&
1799 FcbHeader
->FileSize
.QuadPart
!= FcbHeader
->ValidDataLength
.QuadPart
) ||
1800 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
))
1802 /* Either exclusive flag is set or write operation is extending
1803 the valid data length. Prefer exclusive acquire then */
1805 ResourceToAcquire
= FcbHeader
->Resource
;
1807 else if (!FcbHeader
->PagingIoResource
||
1808 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
))
1810 /* Acquire main resource shared if flag is specified or
1811 if PagingIo resource is missing */
1813 ResourceToAcquire
= FcbHeader
->Resource
;
1816 /* Acquire the resource in the loop, since the above code is unsafe */
1822 Result
= ExAcquireResourceExclusiveLite(ResourceToAcquire
, FALSE
);
1824 Result
= ExAcquireSharedWaitForExclusive(ResourceToAcquire
, FALSE
);
1827 Status
= STATUS_CANT_WAIT
;
1831 /* Do the magic ifs again */
1832 if ((EndingOffset
->QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) ||
1833 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
))
1835 /* Check what we have */
1838 /* Asked for exclusive, got exclusive! */
1843 /* Asked for exclusive, got shared. Release it and retry. */
1844 ExReleaseResourceLite(ResourceToAcquire
);
1846 ResourceToAcquire
= FcbHeader
->Resource
;
1849 else if (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
)
1853 /* Asked for shared, got exclusive - convert */
1854 ExConvertExclusiveToSharedLite(ResourceToAcquire
);
1857 else if (ResourceToAcquire
!= FcbHeader
->Resource
)
1859 /* Asked for main resource, got something else */
1860 ExReleaseResourceLite(ResourceToAcquire
);
1861 ResourceToAcquire
= FcbHeader
->Resource
;
1865 else if (FcbHeader
->PagingIoResource
&&
1866 ResourceToAcquire
!= FcbHeader
->PagingIoResource
)
1868 /* There is PagingIo resource, but other resource was acquired */
1869 ResourceToAcquire
= FcbHeader
->PagingIoResource
;
1870 if (!ExAcquireSharedWaitForExclusive(ResourceToAcquire
, FALSE
))
1872 Status
= STATUS_CANT_WAIT
;
1873 ExReleaseResourceLite(FcbHeader
->Resource
);
1880 /* Asked for shared got exclusive - convert */
1881 ExConvertExclusiveToSharedLite(ResourceToAcquire
);
1886 /* If the resource was acquired successfully - pass it to the caller */
1887 if (NT_SUCCESS(Status
))
1888 *ResourceToRelease
= ResourceToAcquire
;
1898 FsRtlReleaseFileForModWrite(IN PFILE_OBJECT FileObject
,
1899 IN PERESOURCE ResourceToRelease
)
1901 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1902 PFAST_IO_DISPATCH FastDispatch
;
1903 NTSTATUS Status
= STATUS_SUCCESS
;
1905 /* Get Device Object and Fast Calls */
1906 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1907 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1908 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1910 /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
1912 FastDispatch
->ReleaseForModWrite
)
1914 /* Call the ReleaseForModWrite FastIo handler */
1915 Status
= FastDispatch
->ReleaseForModWrite(FileObject
,
1920 /* Just release the resource if previous op failed */
1921 if (!NT_SUCCESS(Status
))
1923 ExReleaseResourceLite(ResourceToRelease
);
1929 * @name FsRtlRegisterFileSystemFilterCallbacks
1934 * @param FilterDriverObject
1947 FsRtlRegisterFileSystemFilterCallbacks(
1948 PDRIVER_OBJECT FilterDriverObject
,
1949 PFS_FILTER_CALLBACKS Callbacks
)
1951 PFS_FILTER_CALLBACKS NewCallbacks
;
1952 PEXTENDED_DRIVER_EXTENSION DriverExtension
;
1955 /* Verify parameters */
1956 if ((FilterDriverObject
== NULL
) || (Callbacks
== NULL
))
1958 return STATUS_INVALID_PARAMETER
;
1961 /* Allocate a buffer for a copy of the callbacks */
1962 NewCallbacks
= ExAllocatePoolWithTag(NonPagedPool
,
1963 Callbacks
->SizeOfFsFilterCallbacks
,
1965 if (NewCallbacks
== NULL
)
1967 return STATUS_INSUFFICIENT_RESOURCES
;
1970 /* Copy the callbacks */
1971 RtlCopyMemory(NewCallbacks
, Callbacks
, Callbacks
->SizeOfFsFilterCallbacks
);
1973 /* Set the callbacks in the driver extension */
1974 DriverExtension
= (PEXTENDED_DRIVER_EXTENSION
)FilterDriverObject
->DriverExtension
;
1975 DriverExtension
->FsFilterCallbacks
= NewCallbacks
;
1977 return STATUS_SUCCESS
;