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
)))
316 IoStatus
->Status
= STATUS_SUCCESS
;
317 IoStatus
->Information
= Length
;
321 FsRtlEnterFileSystem();
324 * The CcFastCopyWrite doesn't deal with filesize beyond 4GB.
326 if (Wait
&& (FcbHeader
->AllocationSize
.HighPart
== 0))
328 /* If the file offset is not past the file size,
329 * then we can acquire the lock shared.
331 if ((FileOffsetAppend
== FALSE
) &&
332 (Offset
.LowPart
<= FcbHeader
->ValidDataLength
.LowPart
))
334 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
335 ResourceAcquiredShared
= TRUE
;
339 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
343 * If we append, use the file size as offset.
344 * Also, check that we aren't crossing the 4GB boundary.
346 if (FileOffsetAppend
== TRUE
)
348 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
;
349 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
350 b_4GB
= (NewSize
.LowPart
< FcbHeader
->FileSize
.LowPart
);
355 Offset
.LowPart
= FileOffset
->LowPart
;
356 NewSize
.LowPart
= FileOffset
->LowPart
+ Length
;
357 b_4GB
= (NewSize
.LowPart
< FileOffset
->LowPart
) ||
358 (FileOffset
->HighPart
!= 0);
362 * Make sure that caching is initated.
363 * That fast are allowed for this file stream.
364 * That we are not extending past the allocated size.
365 * That we are not creating a hole bigger than 8k.
366 * That we are not crossing the 4GB boundary.
368 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
369 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
370 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
371 (Offset
.LowPart
< FcbHeader
->ValidDataLength
.LowPart
+ 0x2000) &&
374 /* If we are extending past the file size, we need to
375 * release the lock and acquire it exclusively, because
376 * we are going to need to update the FcbHeader.
378 if (ResourceAcquiredShared
&&
379 (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
+ 0x2000))
381 /* Then we need to acquire the resource exclusive */
382 ExReleaseResourceLite(FcbHeader
->Resource
);
383 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
384 if (FileOffsetAppend
== TRUE
)
386 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
; // ??
387 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
389 /* Make sure we don't cross the 4GB boundary */
390 b_4GB
= (NewSize
.LowPart
< Offset
.LowPart
);
393 /* Recheck some of the conditions since we let the lock go */
394 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
395 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
396 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
397 (FcbHeader
->AllocationSize
.HighPart
== 0) &&
414 /* Check if we need to find out if fast I/O is available */
415 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
417 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
420 ASSERT(!KeIsExecutingDpc());
422 /* Get the Fast I/O table */
423 Device
= IoGetRelatedDeviceObject(FileObject
);
424 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
427 ASSERT(FastIoDispatch
!= NULL
);
428 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
430 /* Ask the driver if we can do it */
431 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
433 &FcbHeader
->FileSize
:
439 &FastIoCheckIfPossibleStatus
,
447 /* If we are going to extend the file then save
448 * the old file size in case the operation fails.
450 if (NewSize
.LowPart
> FcbHeader
->FileSize
.LowPart
)
452 FileSizeModified
= TRUE
;
453 OldFileSize
.LowPart
= FcbHeader
->FileSize
.LowPart
;
454 OldValidDataLength
.LowPart
= FcbHeader
->ValidDataLength
.LowPart
;
455 FcbHeader
->FileSize
.LowPart
= NewSize
.LowPart
;
458 /* Set this as top-level IRP */
459 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
463 if (Offset
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
465 LARGE_INTEGER OffsetVar
;
466 OffsetVar
.LowPart
= Offset
.LowPart
;
467 OffsetVar
.HighPart
= 0;
468 CcZeroData(FileObject
, &FcbHeader
->ValidDataLength
, &OffsetVar
, TRUE
);
471 /* Call the cache manager */
472 CcFastCopyWrite(FileObject
, Offset
.LowPart
, Length
, Buffer
);
474 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
475 EXCEPTION_EXECUTE_HANDLER
:
476 EXCEPTION_CONTINUE_SEARCH
)
482 /* Remove ourselves at the top level component after the IO is done */
483 PsGetCurrentThread()->TopLevelIrp
= 0;
485 /* Did the operation succeed? */
488 /* Update the valid file size if necessary */
489 if (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
491 FcbHeader
->ValidDataLength
.LowPart
= NewSize
.LowPart
;
494 /* Flag the file as modified */
495 FileObject
->Flags
|= FO_FILE_MODIFIED
;
497 /* Update the strucutres if the file size changed */
498 if (FileSizeModified
)
501 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
502 SharedCacheMap
->FileSize
.LowPart
= NewSize
.LowPart
;
503 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
506 /* Update the file object current file offset */
507 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.LowPart
;
512 /* Result == FALSE if we get here */
513 if (FileSizeModified
)
515 /* If the file size was modified then restore the old file size */
516 if (FcbHeader
->PagingIoResource
!= NULL
)
519 * Restore the old file size if operation didn't succeed.
521 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
522 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
523 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
524 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
528 /* If there is no lock and do it without */
529 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
530 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
543 LARGE_INTEGER OldFileSize
;
546 ASSERT(!KeIsExecutingDpc());
549 * Check if we need to acquire the resource exclusive.
551 if ((FileOffsetAppend
== FALSE
) &&
552 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
554 /* Acquire the resource shared */
555 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, Wait
))
557 goto LeaveCriticalAndFail
;
559 ResourceAcquiredShared
= TRUE
;
563 /* Acquire the resource exclusive */
564 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
566 goto LeaveCriticalAndFail
;
570 /* Check if we are appending */
571 if (FileOffsetAppend
== TRUE
)
573 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
574 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
578 Offset
.QuadPart
= FileOffset
->QuadPart
;
579 NewSize
.QuadPart
+= FileOffset
->QuadPart
+ Length
;
583 * Make sure that caching is initated.
584 * That fast are allowed for this file stream.
585 * That we are not extending past the allocated size.
586 * That we are not creating a hole bigger than 8k.
588 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
589 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
590 (FcbHeader
->ValidDataLength
.QuadPart
+ 0x2000 > Offset
.QuadPart
) &&
591 (Length
<= MAXLONGLONG
- Offset
.QuadPart
) &&
592 (FcbHeader
->AllocationSize
.QuadPart
>= NewSize
.QuadPart
))
594 /* Check if we can keep the lock shared */
595 if (ResourceAcquiredShared
&&
596 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
598 ExReleaseResourceLite(FcbHeader
->Resource
);
599 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
601 goto LeaveCriticalAndFail
;
604 /* Compute the offset and the new filesize */
605 if (FileOffsetAppend
)
607 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
608 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
611 /* Recheck the above points since we released and reacquire the lock */
612 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
613 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
614 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
624 /* Check if we need to find out if fast I/O is available */
625 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
627 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
630 ASSERT(!KeIsExecutingDpc());
632 /* Get the Fast I/O table */
633 Device
= IoGetRelatedDeviceObject(FileObject
);
634 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
637 ASSERT(FastIoDispatch
!= NULL
);
638 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
640 /* Ask the driver if we can do it */
641 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
643 &FcbHeader
->FileSize
:
649 &FastIoCheckIfPossibleStatus
,
657 /* If we are going to modify the filesize,
658 * save the old fs in case the operation fails.
660 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
662 FileSizeModified
= TRUE
;
663 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
664 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
666 /* If the high part of the filesize is going
667 * to change, grab the Paging IoResouce.
669 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
670 FcbHeader
->PagingIoResource
)
672 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
673 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
674 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
678 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
683 * Set ourselves as top component.
685 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
689 BOOLEAN CallCc
= TRUE
;
691 /* Check if there is a gap between the end of the file
692 * and the offset. If yes, then we have to zero the data.
694 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
696 if (!(Result
= CcZeroData(FileObject
,
697 &FcbHeader
->ValidDataLength
,
701 /* If this operation fails, then we have to exit. We can't jump
702 * outside the SEH, so I am using a variable to exit normally.
708 /* Unless the CcZeroData failed, call the cache manager */
711 Result
= CcCopyWrite(FileObject
, &Offset
, Length
, Wait
, Buffer
);
714 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
715 EXCEPTION_EXECUTE_HANDLER
:
716 EXCEPTION_CONTINUE_SEARCH
)
722 /* Reset the top component */
723 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
725 /* Did the operation suceeded */
728 /* Check if we need to update the filesize */
729 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
731 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
732 FcbHeader
->PagingIoResource
)
734 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
735 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
736 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
740 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
744 /* Flag the file as modified */
745 FileObject
->Flags
|= FO_FILE_MODIFIED
;
747 /* Check if the filesize has changed */
748 if (FileSizeModified
)
750 /* Update the file sizes */
752 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
753 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
754 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
757 /* Update the current FO byte offset */
758 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.QuadPart
;
762 /* The operation did not succeed.
763 * Reset the file size to what it should be.
765 if (FileSizeModified
)
767 if (FcbHeader
->PagingIoResource
)
769 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
770 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
771 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
772 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
776 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
777 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
790 LeaveCriticalAndFail
:
792 FsRtlExitFileSystem();
797 ExReleaseResourceLite(FcbHeader
->Resource
);
798 FsRtlExitFileSystem();
803 ExReleaseResourceLite(FcbHeader
->Resource
);
804 FsRtlExitFileSystem();
813 FsRtlGetFileSize(IN PFILE_OBJECT FileObject
,
814 IN OUT PLARGE_INTEGER FileSize
)
816 FILE_STANDARD_INFORMATION Info
;
818 IO_STATUS_BLOCK IoStatus
;
819 PDEVICE_OBJECT DeviceObject
;
820 PFAST_IO_DISPATCH FastDispatch
;
822 PIO_STACK_LOCATION IoStackLocation
;
824 BOOLEAN OldHardError
;
828 /* Get Device Object and Fast Calls */
829 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
830 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
832 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo.
833 * Call the function and see if it succeeds.
836 !FastDispatch
->FastIoQueryStandardInfo
||
837 !FastDispatch
->FastIoQueryStandardInfo(FileObject
,
843 /* If any of the above failed, then we are going to send an
844 * IRP to the device object. Initialize the event for the IO.
846 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
848 /* Allocate the IRP */
849 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
853 return STATUS_INSUFFICIENT_RESOURCES
;
856 /* Don't process hard error */
857 OldHardError
= IoSetThreadHardErrorMode(FALSE
);
860 Irp
->UserIosb
= &IoStatus
;
861 Irp
->UserEvent
= &Event
;
862 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
863 Irp
->Flags
= IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
;
864 Irp
->RequestorMode
= KernelMode
;
865 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
866 Irp
->AssociatedIrp
.SystemBuffer
= &Info
;
868 /* Setup out stack location */
869 IoStackLocation
= Irp
->Tail
.Overlay
.CurrentStackLocation
;
871 IoStackLocation
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
872 IoStackLocation
->FileObject
= FileObject
;
873 IoStackLocation
->DeviceObject
= DeviceObject
;
874 IoStackLocation
->Parameters
.QueryFile
.Length
=
875 sizeof(FILE_STANDARD_INFORMATION
);
876 IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
=
877 FileStandardInformation
;
879 /* Send the IRP to the related device object */
880 Status
= IoCallDriver(DeviceObject
, Irp
);
882 /* Standard DDK IRP result processing */
883 if (Status
== STATUS_PENDING
)
885 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
888 /* If there was a synchronous error, signal it */
889 if (!NT_SUCCESS(Status
))
891 IoStatus
.Status
= Status
;
894 IoSetThreadHardErrorMode(OldHardError
);
897 /* Check the sync/async IO result */
898 if (NT_SUCCESS(IoStatus
.Status
))
900 /* Was the request for a directory? */
903 IoStatus
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
907 FileSize
->QuadPart
= Info
.EndOfFile
.QuadPart
;
911 return IoStatus
.Status
;
919 FsRtlMdlRead(IN PFILE_OBJECT FileObject
,
920 IN PLARGE_INTEGER FileOffset
,
924 OUT PIO_STATUS_BLOCK IoStatus
)
926 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
927 PFAST_IO_DISPATCH FastDispatch
;
929 /* Get Device Object and Fast Calls */
930 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
931 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
933 /* Check if we support Fast Calls, and check this one */
934 if (FastDispatch
&& FastDispatch
->MdlRead
)
936 /* Use the fast path */
937 return FastDispatch
->MdlRead(FileObject
,
946 /* Get the Base File System (Volume) and Fast Calls */
947 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
948 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
950 /* If the Base Device Object has its own FastDispatch Routine, fail */
951 if (FastDispatch
&& FastDispatch
->MdlRead
&& BaseDeviceObject
!= DeviceObject
)
956 /* No fast path, use slow path */
957 return FsRtlMdlReadDev(FileObject
,
971 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject
,
972 IN OUT PMDL MdlChain
)
974 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
975 PFAST_IO_DISPATCH FastDispatch
;
977 /* Get Device Object and Fast Calls */
978 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
979 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
981 /* Check if we support Fast Calls, and check this one */
982 if (FastDispatch
&& FastDispatch
->MdlReadComplete
)
984 /* Use the fast path */
985 return FastDispatch
->MdlReadComplete(FileObject
, MdlChain
, DeviceObject
);
988 /* Get the Base File System (Volume) and Fast Calls */
989 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
990 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
992 /* If the Base Device Object has its own FastDispatch Routine, fail */
993 if ((BaseDeviceObject
!= DeviceObject
) &&
995 FastDispatch
->MdlReadComplete
)
1000 /* No fast path, use slow path */
1001 return FsRtlMdlReadCompleteDev(FileObject
, MdlChain
, DeviceObject
);
1009 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject
,
1010 IN PMDL MemoryDescriptorList
,
1011 IN PDEVICE_OBJECT DeviceObject
)
1013 /* Call the Cache Manager */
1014 CcMdlReadComplete2(FileObject
, MemoryDescriptorList
);
1023 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject
,
1024 IN PLARGE_INTEGER FileOffset
,
1028 OUT PIO_STATUS_BLOCK IoStatus
,
1029 IN PDEVICE_OBJECT DeviceObject
)
1031 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1032 BOOLEAN Result
= TRUE
;
1033 LARGE_INTEGER Offset
;
1034 PFAST_IO_DISPATCH FastIoDispatch
;
1035 PDEVICE_OBJECT Device
;
1038 /* No actual read */
1041 /* Return success */
1042 IoStatus
->Status
= STATUS_SUCCESS
;
1043 IoStatus
->Information
= 0;
1048 ASSERT(MAXLONGLONG
- FileOffset
->QuadPart
>= (LONGLONG
)Length
);
1050 /* Get the offset and FCB header */
1051 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1052 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1055 FsRtlEnterFileSystem();
1056 CcFastMdlReadWait
++;
1059 ExAcquireResourceShared(FcbHeader
->Resource
, TRUE
);
1061 /* Check if this is a fast I/O cached file */
1062 if (!(FileObject
->PrivateCacheMap
) ||
1063 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
1065 /* It's not, so fail */
1066 CcFastMdlReadNotPossible
+= 1;
1071 /* Check if we need to find out if fast I/O is available */
1072 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1074 /* Get the Fast I/O table */
1075 Device
= IoGetRelatedDeviceObject(FileObject
);
1076 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1079 ASSERT(!KeIsExecutingDpc());
1080 ASSERT(FastIoDispatch
!= NULL
);
1081 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1083 /* Ask the driver if we can do it */
1084 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1093 /* It's not, fail */
1094 CcFastMdlReadNotPossible
+= 1;
1100 /* Check if we read too much */
1101 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1103 /* We did, check if the file offset is past the end */
1104 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
1106 /* Set end of file */
1107 IoStatus
->Status
= STATUS_END_OF_FILE
;
1108 IoStatus
->Information
= 0;
1112 /* Otherwise, just normalize the length */
1113 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
1116 /* Set this as top-level IRP */
1117 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1121 /* Attempt a read */
1122 CcMdlRead(FileObject
, FileOffset
, Length
, MdlChain
, IoStatus
);
1123 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
1125 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1126 EXCEPTION_EXECUTE_HANDLER
:
1127 EXCEPTION_CONTINUE_SEARCH
)
1134 /* Remove the top-level IRP flag */
1135 PsGetCurrentThread()->TopLevelIrp
= 0;
1137 /* Return to caller */
1140 ExReleaseResourceLite(FcbHeader
->Resource
);
1141 FsRtlExitFileSystem();
1151 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject
,
1152 IN PLARGE_INTEGER FileOffset
,
1155 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1156 PFAST_IO_DISPATCH FastDispatch
;
1158 /* Get Device Object and Fast Calls */
1159 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1160 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1162 /* Check if we support Fast Calls, and check this one */
1163 if (FastDispatch
&& FastDispatch
->MdlWriteComplete
)
1165 /* Use the fast path */
1166 return FastDispatch
->MdlWriteComplete(FileObject
,
1172 /* Get the Base File System (Volume) and Fast Calls */
1173 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1174 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1176 /* If the Base Device Object has its own FastDispatch Routine, fail */
1178 FastDispatch
->MdlWriteComplete
&&
1179 BaseDeviceObject
!= DeviceObject
)
1184 /* No fast path, use slow path */
1185 return FsRtlMdlWriteCompleteDev(FileObject
,
1196 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject
,
1197 IN PLARGE_INTEGER FileOffset
,
1199 IN PDEVICE_OBJECT DeviceObject
)
1201 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1206 /* Call the Cache Manager */
1207 CcMdlWriteComplete2(FileObject
, FileOffset
, MdlChain
);
1216 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject
,
1217 IN PLARGE_INTEGER FileOffset
,
1221 OUT PIO_STATUS_BLOCK IoStatus
)
1223 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1224 PFAST_IO_DISPATCH FastDispatch
;
1226 /* Get Device Object and Fast Calls */
1227 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1228 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1230 /* Check if we support Fast Calls, and check this one */
1231 if (FastDispatch
&& FastDispatch
->PrepareMdlWrite
)
1233 /* Use the fast path */
1234 return FastDispatch
->PrepareMdlWrite(FileObject
,
1243 /* Get the Base File System (Volume) and Fast Calls */
1244 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1245 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1247 /* If the Base Device Object has its own FastDispatch Routine, fail */
1249 FastDispatch
->PrepareMdlWrite
&&
1250 BaseDeviceObject
!= DeviceObject
)
1255 /* No fast path, use slow path */
1256 return FsRtlPrepareMdlWriteDev(FileObject
,
1270 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject
,
1271 IN PLARGE_INTEGER FileOffset
,
1275 OUT PIO_STATUS_BLOCK IoStatus
,
1276 IN PDEVICE_OBJECT DeviceObject
)
1278 BOOLEAN Result
= TRUE
;
1279 PFAST_IO_DISPATCH FastIoDispatch
;
1280 PDEVICE_OBJECT Device
;
1281 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1282 PSHARED_CACHE_MAP SharedCacheMap
;
1284 LARGE_INTEGER OldFileSize
;
1285 LARGE_INTEGER OldValidDataLength
;
1286 LARGE_INTEGER NewSize
;
1287 LARGE_INTEGER Offset
;
1290 * Offset == 0xffffffffffffffff indicates append to the end of file.
1292 BOOLEAN FileOffsetAppend
= (FileOffset
->HighPart
== (LONG
)0xffffffff) &&
1293 (FileOffset
->LowPart
== 0xffffffff);
1295 BOOLEAN FileSizeModified
= FALSE
;
1296 BOOLEAN ResourceAcquiredShared
= FALSE
;
1298 /* Initialize some of the vars and pointers */
1299 OldFileSize
.QuadPart
= 0;
1300 OldValidDataLength
.QuadPart
= 0;
1304 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1307 * Check with Cc if we can write.
1309 if (!CcCanIWrite(FileObject
, Length
, TRUE
, FALSE
) ||
1310 (FileObject
->Flags
& FO_WRITE_THROUGH
))
1315 IoStatus
->Status
= STATUS_SUCCESS
;
1317 /* No actual read */
1323 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1324 FsRtlEnterFileSystem();
1326 /* Check we are going to extend the file */
1327 if ((FileOffsetAppend
== FALSE
) &&
1328 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
1330 /* Acquire the resource shared */
1331 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
1332 ResourceAcquiredShared
= TRUE
;
1336 /* Acquire the resource exclusive */
1337 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1340 /* Check if we are appending */
1341 if (FileOffsetAppend
== TRUE
)
1343 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1344 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1348 Offset
.QuadPart
= FileOffset
->QuadPart
;
1349 NewSize
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1352 if ((FileObject
->PrivateCacheMap
) &&
1353 (FcbHeader
->IsFastIoPossible
) &&
1354 (Length
<= MAXLONGLONG
- FileOffset
->QuadPart
) &&
1355 (NewSize
.QuadPart
<= FcbHeader
->AllocationSize
.QuadPart
))
1357 /* Check if we can keep the lock shared */
1358 if (ResourceAcquiredShared
&&
1359 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
1361 ExReleaseResourceLite(FcbHeader
->Resource
);
1362 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1364 /* Compute the offset and the new filesize */
1365 if (FileOffsetAppend
)
1367 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1368 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1371 /* Recheck the above points since we released and reacquire the lock */
1372 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
1373 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
1374 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
1380 goto FailAndCleanup
;
1384 /* Check if we need to find out if fast I/O is available */
1385 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1388 /* ASSERT(!KeIsExecutingDpc()); */
1390 /* Get the Fast I/O table */
1391 Device
= IoGetRelatedDeviceObject(FileObject
);
1392 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1395 ASSERT(FastIoDispatch
!= NULL
);
1396 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1398 /* Ask the driver if we can do it */
1399 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1408 /* It's not, fail */
1409 goto FailAndCleanup
;
1413 /* If we are going to modify the filesize,
1414 * save the old fs in case the operation fails.
1416 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1418 FileSizeModified
= TRUE
;
1419 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1420 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
1422 /* If the high part of the filesize is going
1423 * to change, grab the Paging IoResouce.
1425 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
1426 FcbHeader
->PagingIoResource
)
1428 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1429 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1430 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1434 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1440 * Set ourselves as top component.
1442 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1445 /* Check if there is a gap between the end of the file and the offset.
1446 * If yes, then we have to zero the data.
1448 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1450 Result
= CcZeroData(FileObject
,
1451 &FcbHeader
->ValidDataLength
,
1456 CcPrepareMdlWrite(FileObject
,
1465 CcPrepareMdlWrite(FileObject
, &Offset
, Length
, MdlChain
, IoStatus
);
1469 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1470 EXCEPTION_EXECUTE_HANDLER
:
1471 EXCEPTION_CONTINUE_SEARCH
)
1477 /* Reset the top component */
1478 PsGetCurrentThread()->TopLevelIrp
= 0;
1480 /* Did the operation suceeded */
1483 /* Check if we need to update the filesize */
1484 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1486 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
1487 FcbHeader
->PagingIoResource
)
1489 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1490 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1491 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1495 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1499 /* Flag the file as modified */
1500 FileObject
->Flags
|= FO_FILE_MODIFIED
;
1502 /* Check if the filesize has changed */
1503 if (FileSizeModified
)
1506 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
1507 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1508 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
1513 /* The operation did not succeed.
1514 * Reset the file size to what it should be.
1516 if (FileSizeModified
)
1518 if (FcbHeader
->PagingIoResource
)
1520 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1521 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1522 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1523 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1527 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1528 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1537 goto FailAndCleanup
;
1542 ExReleaseResourceLite(FcbHeader
->Resource
);
1543 FsRtlExitFileSystem();
1548 ExReleaseResourceLite(FcbHeader
->Resource
);
1549 FsRtlExitFileSystem();
1555 FsRtlAcquireFileExclusiveCommon(IN PFILE_OBJECT FileObject
,
1556 IN FS_FILTER_SECTION_SYNC_TYPE SyncType
,
1559 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1560 PDEVICE_OBJECT DeviceObject
;
1561 PFAST_IO_DISPATCH FastDispatch
;
1563 /* Get Device Object and Fast Calls */
1564 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1565 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1566 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1568 /* Get master FsRtl lock */
1569 FsRtlEnterFileSystem();
1571 /* Check if Fast Calls are supported, and check AcquireFileForNtCreateSection */
1573 FastDispatch
->AcquireFileForNtCreateSection
)
1575 /* Call the AcquireFileForNtCreateSection FastIo handler */
1576 FastDispatch
->AcquireFileForNtCreateSection(FileObject
);
1580 /* No FastIo handler, acquire file's resource exclusively */
1581 if (FcbHeader
&& FcbHeader
->Resource
) ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1584 return STATUS_SUCCESS
;
1592 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject
)
1596 /* Call the common routine. Don't care about the result */
1597 (VOID
)FsRtlAcquireFileExclusiveCommon(FileObject
, SyncTypeOther
, 0);
1605 FsRtlReleaseFile(IN PFILE_OBJECT FileObject
)
1607 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1608 PDEVICE_OBJECT DeviceObject
;
1609 PFAST_IO_DISPATCH FastDispatch
;
1611 /* Get Device Object and Fast Calls */
1612 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1613 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1614 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1616 /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
1618 FastDispatch
->ReleaseFileForNtCreateSection
)
1620 /* Call the ReleaseFileForNtCreateSection FastIo handler */
1621 FastDispatch
->ReleaseFileForNtCreateSection(FileObject
);
1625 /* No FastIo handler, release file's resource */
1626 if (FcbHeader
&& FcbHeader
->Resource
) ExReleaseResourceLite(FcbHeader
->Resource
);
1629 /* Release master FsRtl lock */
1630 FsRtlExitFileSystem();
1638 FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject
)
1640 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1641 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1642 PFAST_IO_DISPATCH FastDispatch
;
1645 /* Get the Base File System (Volume) and Fast Calls */
1646 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1647 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1648 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1649 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1651 /* Get master FsRtl lock */
1652 FsRtlEnterFileSystem();
1654 /* Check if Fast Calls are supported, and check AcquireForCcFlush */
1656 FastDispatch
->AcquireForCcFlush
)
1658 /* Call the AcquireForCcFlush FastIo handler */
1659 Status
= FastDispatch
->AcquireForCcFlush(FileObject
, BaseDeviceObject
);
1661 /* Return either success or inability to wait.
1662 In case of other failure - fall through */
1663 if (Status
== STATUS_SUCCESS
||
1664 Status
== STATUS_CANT_WAIT
)
1670 /* No FastIo handler (or it failed). Acquire Main resource */
1671 if (FcbHeader
->Resource
)
1673 /* Acquire it - either shared if it's already acquired
1674 or exclusively if we are the first */
1675 if (ExIsResourceAcquiredSharedLite(FcbHeader
->Resource
))
1676 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
1678 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1681 /* Also acquire its PagingIO resource */
1682 if (FcbHeader
->PagingIoResource
)
1683 ExAcquireResourceSharedLite(FcbHeader
->PagingIoResource
, TRUE
);
1685 return STATUS_SUCCESS
;
1693 FsRtlAcquireFileForCcFlush(IN PFILE_OBJECT FileObject
)
1697 /* Call the common routine. Don't care about the result */
1698 (VOID
)FsRtlAcquireFileForCcFlushEx(FileObject
);
1707 FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject
)
1709 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1710 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1711 PFAST_IO_DISPATCH FastDispatch
;
1712 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
1714 /* Get Device Object and Fast Calls */
1715 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1716 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1717 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1718 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1720 /* Check if Fast Calls are supported, and check ReleaseForCcFlush */
1722 FastDispatch
->ReleaseForCcFlush
)
1724 /* Call the ReleaseForCcFlush FastIo handler */
1725 Status
= FastDispatch
->ReleaseForCcFlush(FileObject
, BaseDeviceObject
);
1728 if (!NT_SUCCESS(Status
))
1730 /* No FastIo handler (or it failed). Release PagingIO resource and
1731 then Main resource */
1732 if (FcbHeader
->PagingIoResource
) ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1733 if (FcbHeader
->Resource
) ExReleaseResourceLite(FcbHeader
->Resource
);
1736 /* Release master FsRtl lock */
1737 FsRtlExitFileSystem();
1745 FsRtlAcquireFileForModWriteEx(IN PFILE_OBJECT FileObject
,
1746 IN PLARGE_INTEGER EndingOffset
,
1747 IN PERESOURCE
*ResourceToRelease
)
1749 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1750 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1751 PFAST_IO_DISPATCH FastDispatch
;
1752 PERESOURCE ResourceToAcquire
= NULL
;
1753 BOOLEAN Exclusive
= FALSE
;
1755 NTSTATUS Status
= STATUS_SUCCESS
;
1757 /* Get Device Object and Fast Calls */
1758 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1759 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1760 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1761 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1763 /* Check if Fast Calls are supported, and check AcquireForModWrite */
1765 FastDispatch
->AcquireForModWrite
)
1767 /* Call the AcquireForModWrite FastIo handler */
1768 Status
= FastDispatch
->AcquireForModWrite(FileObject
,
1773 /* Return either success or inability to wait.
1774 In case of other failure - fall through */
1775 if (Status
== STATUS_SUCCESS
||
1776 Status
== STATUS_CANT_WAIT
)
1782 Status
= STATUS_SUCCESS
;
1784 /* No FastIo handler, use algorithm from Nagar p.550. */
1785 if (!FcbHeader
->Resource
)
1787 *ResourceToRelease
= NULL
;
1788 return STATUS_SUCCESS
;
1791 /* Default condition - shared acquiring of Paging IO Resource */
1792 ResourceToAcquire
= FcbHeader
->PagingIoResource
;
1794 /* Decide on type of locking and type of resource based on historical magic
1795 well explain by Nagar in p. 550-551 */
1796 if ((EndingOffset
->QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
&&
1797 FcbHeader
->FileSize
.QuadPart
!= FcbHeader
->ValidDataLength
.QuadPart
) ||
1798 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
))
1800 /* Either exclusive flag is set or write operation is extending
1801 the valid data length. Prefer exclusive acquire then */
1803 ResourceToAcquire
= FcbHeader
->Resource
;
1805 else if (!FcbHeader
->PagingIoResource
||
1806 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
))
1808 /* Acquire main resource shared if flag is specified or
1809 if PagingIo resource is missing */
1811 ResourceToAcquire
= FcbHeader
->Resource
;
1814 /* Acquire the resource in the loop, since the above code is unsafe */
1820 Result
= ExAcquireResourceExclusiveLite(ResourceToAcquire
, FALSE
);
1822 Result
= ExAcquireSharedWaitForExclusive(ResourceToAcquire
, FALSE
);
1825 Status
= STATUS_CANT_WAIT
;
1829 /* Do the magic ifs again */
1830 if ((EndingOffset
->QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) ||
1831 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
))
1833 /* Check what we have */
1836 /* Asked for exclusive, got exclusive! */
1841 /* Asked for exclusive, got shared. Release it and retry. */
1842 ExReleaseResourceLite(ResourceToAcquire
);
1844 ResourceToAcquire
= FcbHeader
->Resource
;
1847 else if (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
)
1851 /* Asked for shared, got exclusive - convert */
1852 ExConvertExclusiveToSharedLite(ResourceToAcquire
);
1855 else if (ResourceToAcquire
!= FcbHeader
->Resource
)
1857 /* Asked for main resource, got something else */
1858 ExReleaseResourceLite(ResourceToAcquire
);
1859 ResourceToAcquire
= FcbHeader
->Resource
;
1863 else if (FcbHeader
->PagingIoResource
&&
1864 ResourceToAcquire
!= FcbHeader
->PagingIoResource
)
1866 /* There is PagingIo resource, but other resource was acquired */
1867 ResourceToAcquire
= FcbHeader
->PagingIoResource
;
1868 if (!ExAcquireSharedWaitForExclusive(ResourceToAcquire
, FALSE
))
1870 Status
= STATUS_CANT_WAIT
;
1871 ExReleaseResourceLite(FcbHeader
->Resource
);
1878 /* Asked for shared got exclusive - convert */
1879 ExConvertExclusiveToSharedLite(ResourceToAcquire
);
1884 /* If the resource was acquired successfully - pass it to the caller */
1885 if (NT_SUCCESS(Status
))
1886 *ResourceToRelease
= ResourceToAcquire
;
1896 FsRtlReleaseFileForModWrite(IN PFILE_OBJECT FileObject
,
1897 IN PERESOURCE ResourceToRelease
)
1899 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1900 PFAST_IO_DISPATCH FastDispatch
;
1901 NTSTATUS Status
= STATUS_SUCCESS
;
1903 /* Get Device Object and Fast Calls */
1904 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1905 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1906 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1908 /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
1910 FastDispatch
->ReleaseForModWrite
)
1912 /* Call the ReleaseForModWrite FastIo handler */
1913 Status
= FastDispatch
->ReleaseForModWrite(FileObject
,
1918 /* Just release the resource if previous op failed */
1919 if (!NT_SUCCESS(Status
))
1921 ExReleaseResourceLite(ResourceToRelease
);
1927 * @name FsRtlRegisterFileSystemFilterCallbacks
1932 * @param FilterDriverObject
1945 FsRtlRegisterFileSystemFilterCallbacks(
1946 PDRIVER_OBJECT FilterDriverObject
,
1947 PFS_FILTER_CALLBACKS Callbacks
)
1949 PFS_FILTER_CALLBACKS NewCallbacks
;
1950 PEXTENDED_DRIVER_EXTENSION DriverExtension
;
1953 /* Verify parameters */
1954 if ((FilterDriverObject
== NULL
) || (Callbacks
== NULL
))
1956 return STATUS_INVALID_PARAMETER
;
1959 /* Allocate a buffer for a copy of the callbacks */
1960 NewCallbacks
= ExAllocatePoolWithTag(NonPagedPool
,
1961 Callbacks
->SizeOfFsFilterCallbacks
,
1963 if (NewCallbacks
== NULL
)
1965 return STATUS_INSUFFICIENT_RESOURCES
;
1968 /* Copy the callbacks */
1969 RtlCopyMemory(NewCallbacks
, Callbacks
, Callbacks
->SizeOfFsFilterCallbacks
);
1971 /* Set the callbacks in the driver extension */
1972 DriverExtension
= (PEXTENDED_DRIVER_EXTENSION
)FilterDriverObject
->DriverExtension
;
1973 DriverExtension
->FsFilterCallbacks
= NewCallbacks
;
1975 return STATUS_SUCCESS
;