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 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
299 /* Silence incorrect GCC 4.5.x warning */
300 OldFileSize
.LowPart
= 0;
303 /* Initialize some of the vars and pointers */
304 NewSize
.QuadPart
= 0;
305 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
306 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
309 * Check with Cc if we can write and check if the IO > 64kB (WDK macro).
311 if ((CcCanIWrite(FileObject
, Length
, Wait
, FALSE
) == FALSE
) ||
312 (CcCopyWriteWontFlush(FileObject
, FileOffset
, Length
) == FALSE
) ||
313 ((FileObject
->Flags
& FO_WRITE_THROUGH
)))
321 IoStatus
->Status
= STATUS_SUCCESS
;
322 IoStatus
->Information
= Length
;
326 FsRtlEnterFileSystem();
329 * The CcFastCopyWrite doesn't deal with filesize beyond 4GB.
331 if (Wait
&& (FcbHeader
->AllocationSize
.HighPart
== 0))
333 /* If the file offset is not past the file size,
334 * then we can acquire the lock shared.
336 if ((FileOffsetAppend
== FALSE
) &&
337 (Offset
.LowPart
<= FcbHeader
->ValidDataLength
.LowPart
))
339 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
340 ResourceAcquiredShared
= TRUE
;
344 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
348 * If we append, use the file size as offset.
349 * Also, check that we aren't crossing the 4GB boundary.
351 if (FileOffsetAppend
== TRUE
)
353 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
;
354 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
355 b_4GB
= (NewSize
.LowPart
< FcbHeader
->FileSize
.LowPart
);
360 Offset
.LowPart
= FileOffset
->LowPart
;
361 NewSize
.LowPart
= FileOffset
->LowPart
+ Length
;
362 b_4GB
= (NewSize
.LowPart
< FileOffset
->LowPart
) ||
363 (FileOffset
->HighPart
!= 0);
367 * Make sure that caching is initated.
368 * That fast are allowed for this file stream.
369 * That we are not extending past the allocated size.
370 * That we are not creating a hole bigger than 8k.
371 * That we are not crossing the 4GB boundary.
373 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
374 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
375 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
376 (Offset
.LowPart
< FcbHeader
->ValidDataLength
.LowPart
+ 0x2000) &&
379 /* If we are extending past the file size, we need to
380 * release the lock and acquire it exclusively, because
381 * we are going to need to update the FcbHeader.
383 if (ResourceAcquiredShared
&&
384 (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
+ 0x2000))
386 /* Then we need to acquire the resource exclusive */
387 ExReleaseResourceLite(FcbHeader
->Resource
);
388 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
389 if (FileOffsetAppend
== TRUE
)
391 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
; // ??
392 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
394 /* Make sure we don't cross the 4GB boundary */
395 b_4GB
= (NewSize
.LowPart
< Offset
.LowPart
);
398 /* Recheck some of the conditions since we let the lock go */
399 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
400 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
401 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
402 (FcbHeader
->AllocationSize
.HighPart
== 0) &&
419 /* Check if we need to find out if fast I/O is available */
420 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
422 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
425 ASSERT(!KeIsExecutingDpc());
427 /* Get the Fast I/O table */
428 Device
= IoGetRelatedDeviceObject(FileObject
);
429 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
432 ASSERT(FastIoDispatch
!= NULL
);
433 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
435 /* Ask the driver if we can do it */
436 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
438 &FcbHeader
->FileSize
:
444 &FastIoCheckIfPossibleStatus
,
452 /* If we are going to extend the file then save
453 * the old file size in case the operation fails.
455 if (NewSize
.LowPart
> FcbHeader
->FileSize
.LowPart
)
457 FileSizeModified
= TRUE
;
458 OldFileSize
.LowPart
= FcbHeader
->FileSize
.LowPart
;
459 OldValidDataLength
.LowPart
= FcbHeader
->ValidDataLength
.LowPart
;
460 FcbHeader
->FileSize
.LowPart
= NewSize
.LowPart
;
463 /* Set this as top-level IRP */
464 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
468 if (Offset
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
470 LARGE_INTEGER OffsetVar
;
471 OffsetVar
.LowPart
= Offset
.LowPart
;
472 OffsetVar
.HighPart
= 0;
473 CcZeroData(FileObject
, &FcbHeader
->ValidDataLength
, &OffsetVar
, TRUE
);
476 /* Call the cache manager */
477 CcFastCopyWrite(FileObject
, Offset
.LowPart
, Length
, Buffer
);
479 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
480 EXCEPTION_EXECUTE_HANDLER
:
481 EXCEPTION_CONTINUE_SEARCH
)
487 /* Remove ourselves at the top level component after the IO is done */
488 PsGetCurrentThread()->TopLevelIrp
= 0;
490 /* Did the operation succeed? */
493 /* Update the valid file size if necessary */
494 if (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
496 FcbHeader
->ValidDataLength
.LowPart
= NewSize
.LowPart
;
499 /* Flag the file as modified */
500 FileObject
->Flags
|= FO_FILE_MODIFIED
;
502 /* Update the strucutres if the file size changed */
503 if (FileSizeModified
)
506 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
507 SharedCacheMap
->FileSize
.LowPart
= NewSize
.LowPart
;
508 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
511 /* Update the file object current file offset */
512 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.LowPart
;
517 /* Result == FALSE if we get here */
518 if (FileSizeModified
)
520 /* If the file size was modified then restore the old file size */
521 if (FcbHeader
->PagingIoResource
!= NULL
)
524 * Restore the old file size if operation didn't succeed.
526 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
527 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
528 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
529 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
533 /* If there is no lock and do it without */
534 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
535 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
548 LARGE_INTEGER OldFileSize
;
550 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
551 /* Silence incorrect GCC 4.5.x warning */
552 OldFileSize
.QuadPart
= 0;
556 ASSERT(!KeIsExecutingDpc());
559 * Check if we need to acquire the resource exclusive.
561 if ((FileOffsetAppend
== FALSE
) &&
562 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
564 /* Acquire the resource shared */
565 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, Wait
))
567 goto LeaveCriticalAndFail
;
569 ResourceAcquiredShared
= TRUE
;
573 /* Acquire the resource exclusive */
574 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
576 goto LeaveCriticalAndFail
;
580 /* Check if we are appending */
581 if (FileOffsetAppend
== TRUE
)
583 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
584 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
588 Offset
.QuadPart
= FileOffset
->QuadPart
;
589 NewSize
.QuadPart
+= FileOffset
->QuadPart
+ Length
;
593 * Make sure that caching is initated.
594 * That fast are allowed for this file stream.
595 * That we are not extending past the allocated size.
596 * That we are not creating a hole bigger than 8k.
598 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
599 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
600 (FcbHeader
->ValidDataLength
.QuadPart
+ 0x2000 > Offset
.QuadPart
) &&
601 (Length
<= MAXLONGLONG
- Offset
.QuadPart
) &&
602 (FcbHeader
->AllocationSize
.QuadPart
>= NewSize
.QuadPart
))
604 /* Check if we can keep the lock shared */
605 if (ResourceAcquiredShared
&&
606 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
608 ExReleaseResourceLite(FcbHeader
->Resource
);
609 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
611 goto LeaveCriticalAndFail
;
614 /* Compute the offset and the new filesize */
615 if (FileOffsetAppend
)
617 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
618 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
621 /* Recheck the above points since we released and reacquire the lock */
622 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
623 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
624 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
634 /* Check if we need to find out if fast I/O is available */
635 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
637 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
640 ASSERT(!KeIsExecutingDpc());
642 /* Get the Fast I/O table */
643 Device
= IoGetRelatedDeviceObject(FileObject
);
644 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
647 ASSERT(FastIoDispatch
!= NULL
);
648 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
650 /* Ask the driver if we can do it */
651 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
653 &FcbHeader
->FileSize
:
659 &FastIoCheckIfPossibleStatus
,
667 /* If we are going to modify the filesize,
668 * save the old fs in case the operation fails.
670 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
672 FileSizeModified
= TRUE
;
673 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
674 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
676 /* If the high part of the filesize is going
677 * to change, grab the Paging IoResouce.
679 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
680 FcbHeader
->PagingIoResource
)
682 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
683 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
684 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
688 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
693 * Set ourselves as top component.
695 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
699 BOOLEAN CallCc
= TRUE
;
701 /* Check if there is a gap between the end of the file
702 * and the offset. If yes, then we have to zero the data.
704 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
706 if (!(Result
= CcZeroData(FileObject
,
707 &FcbHeader
->ValidDataLength
,
711 /* If this operation fails, then we have to exit. We can't jump
712 * outside the SEH, so I am using a variable to exit normally.
718 /* Unless the CcZeroData failed, call the cache manager */
721 Result
= CcCopyWrite(FileObject
, &Offset
, Length
, Wait
, Buffer
);
724 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
725 EXCEPTION_EXECUTE_HANDLER
:
726 EXCEPTION_CONTINUE_SEARCH
)
732 /* Reset the top component */
733 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
735 /* Did the operation suceeded */
738 /* Check if we need to update the filesize */
739 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
741 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
742 FcbHeader
->PagingIoResource
)
744 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
745 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
746 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
750 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
754 /* Flag the file as modified */
755 FileObject
->Flags
|= FO_FILE_MODIFIED
;
757 /* Check if the filesize has changed */
758 if (FileSizeModified
)
760 /* Update the file sizes */
762 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
763 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
764 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
767 /* Update the current FO byte offset */
768 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.QuadPart
;
772 /* The operation did not succeed.
773 * Reset the file size to what it should be.
775 if (FileSizeModified
)
777 if (FcbHeader
->PagingIoResource
)
779 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
780 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
781 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
782 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
786 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
787 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
800 LeaveCriticalAndFail
:
802 FsRtlExitFileSystem();
807 ExReleaseResourceLite(FcbHeader
->Resource
);
808 FsRtlExitFileSystem();
813 ExReleaseResourceLite(FcbHeader
->Resource
);
814 FsRtlExitFileSystem();
823 FsRtlGetFileSize(IN PFILE_OBJECT FileObject
,
824 IN OUT PLARGE_INTEGER FileSize
)
826 FILE_STANDARD_INFORMATION Info
;
828 IO_STATUS_BLOCK IoStatus
;
829 PDEVICE_OBJECT DeviceObject
;
830 PFAST_IO_DISPATCH FastDispatch
;
832 PIO_STACK_LOCATION IoStackLocation
;
834 BOOLEAN OldHardError
;
838 /* Get Device Object and Fast Calls */
839 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
840 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
842 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo.
843 * Call the function and see if it succeeds.
846 !FastDispatch
->FastIoQueryStandardInfo
||
847 !FastDispatch
->FastIoQueryStandardInfo(FileObject
,
853 /* If any of the above failed, then we are going to send an
854 * IRP to the device object. Initialize the event for the IO.
856 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
858 /* Allocate the IRP */
859 Irp
= IoAllocateIrp(DeviceObject
->StackSize
, FALSE
);
863 return STATUS_INSUFFICIENT_RESOURCES
;
866 /* Don't process hard error */
867 OldHardError
= IoSetThreadHardErrorMode(FALSE
);
870 Irp
->UserIosb
= &IoStatus
;
871 Irp
->UserEvent
= &Event
;
872 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
873 Irp
->Flags
= IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
;
874 Irp
->RequestorMode
= KernelMode
;
875 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
876 Irp
->AssociatedIrp
.SystemBuffer
= &Info
;
878 /* Setup out stack location */
879 IoStackLocation
= Irp
->Tail
.Overlay
.CurrentStackLocation
;
881 IoStackLocation
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
882 IoStackLocation
->FileObject
= FileObject
;
883 IoStackLocation
->DeviceObject
= DeviceObject
;
884 IoStackLocation
->Parameters
.QueryFile
.Length
=
885 sizeof(FILE_STANDARD_INFORMATION
);
886 IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
=
887 FileStandardInformation
;
889 /* Send the IRP to the related device object */
890 Status
= IoCallDriver(DeviceObject
, Irp
);
892 /* Standard DDK IRP result processing */
893 if (Status
== STATUS_PENDING
)
895 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
898 /* If there was a synchronous error, signal it */
899 if (!NT_SUCCESS(Status
))
901 IoStatus
.Status
= Status
;
904 IoSetThreadHardErrorMode(OldHardError
);
907 /* Check the sync/async IO result */
908 if (NT_SUCCESS(IoStatus
.Status
))
910 /* Was the request for a directory? */
913 IoStatus
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
917 FileSize
->QuadPart
= Info
.EndOfFile
.QuadPart
;
921 return IoStatus
.Status
;
929 FsRtlMdlRead(IN PFILE_OBJECT FileObject
,
930 IN PLARGE_INTEGER FileOffset
,
934 OUT PIO_STATUS_BLOCK IoStatus
)
936 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
937 PFAST_IO_DISPATCH FastDispatch
;
939 /* Get Device Object and Fast Calls */
940 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
941 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
943 /* Check if we support Fast Calls, and check this one */
944 if (FastDispatch
&& FastDispatch
->MdlRead
)
946 /* Use the fast path */
947 return FastDispatch
->MdlRead(FileObject
,
956 /* Get the Base File System (Volume) and Fast Calls */
957 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
958 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
960 /* If the Base Device Object has its own FastDispatch Routine, fail */
961 if (FastDispatch
&& FastDispatch
->MdlRead
&& BaseDeviceObject
!= DeviceObject
)
966 /* No fast path, use slow path */
967 return FsRtlMdlReadDev(FileObject
,
981 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject
,
982 IN OUT PMDL MdlChain
)
984 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
985 PFAST_IO_DISPATCH FastDispatch
;
987 /* Get Device Object and Fast Calls */
988 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
989 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
991 /* Check if we support Fast Calls, and check this one */
992 if (FastDispatch
&& FastDispatch
->MdlReadComplete
)
994 /* Use the fast path */
995 return FastDispatch
->MdlReadComplete(FileObject
, MdlChain
, DeviceObject
);
998 /* Get the Base File System (Volume) and Fast Calls */
999 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1000 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1002 /* If the Base Device Object has its own FastDispatch Routine, fail */
1003 if ((BaseDeviceObject
!= DeviceObject
) &&
1005 FastDispatch
->MdlReadComplete
)
1010 /* No fast path, use slow path */
1011 return FsRtlMdlReadCompleteDev(FileObject
, MdlChain
, DeviceObject
);
1019 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject
,
1020 IN PMDL MemoryDescriptorList
,
1021 IN PDEVICE_OBJECT DeviceObject
)
1023 /* Call the Cache Manager */
1024 CcMdlReadComplete2(FileObject
, MemoryDescriptorList
);
1033 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject
,
1034 IN PLARGE_INTEGER FileOffset
,
1038 OUT PIO_STATUS_BLOCK IoStatus
,
1039 IN PDEVICE_OBJECT DeviceObject
)
1041 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1042 BOOLEAN Result
= TRUE
;
1043 LARGE_INTEGER Offset
;
1044 PFAST_IO_DISPATCH FastIoDispatch
;
1045 PDEVICE_OBJECT Device
;
1048 /* No actual read */
1051 /* Return success */
1052 IoStatus
->Status
= STATUS_SUCCESS
;
1053 IoStatus
->Information
= 0;
1058 ASSERT(MAXLONGLONG
- FileOffset
->QuadPart
>= (LONGLONG
)Length
);
1060 /* Get the offset and FCB header */
1061 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1062 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1065 FsRtlEnterFileSystem();
1066 CcFastMdlReadWait
++;
1069 ExAcquireResourceShared(FcbHeader
->Resource
, TRUE
);
1071 /* Check if this is a fast I/O cached file */
1072 if (!(FileObject
->PrivateCacheMap
) ||
1073 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
1075 /* It's not, so fail */
1076 CcFastMdlReadNotPossible
+= 1;
1081 /* Check if we need to find out if fast I/O is available */
1082 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1084 /* Get the Fast I/O table */
1085 Device
= IoGetRelatedDeviceObject(FileObject
);
1086 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1089 ASSERT(!KeIsExecutingDpc());
1090 ASSERT(FastIoDispatch
!= NULL
);
1091 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1093 /* Ask the driver if we can do it */
1094 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1103 /* It's not, fail */
1104 CcFastMdlReadNotPossible
+= 1;
1110 /* Check if we read too much */
1111 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1113 /* We did, check if the file offset is past the end */
1114 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
1116 /* Set end of file */
1117 IoStatus
->Status
= STATUS_END_OF_FILE
;
1118 IoStatus
->Information
= 0;
1122 /* Otherwise, just normalize the length */
1123 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
1126 /* Set this as top-level IRP */
1127 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1131 /* Attempt a read */
1132 CcMdlRead(FileObject
, FileOffset
, Length
, MdlChain
, IoStatus
);
1133 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
1135 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1136 EXCEPTION_EXECUTE_HANDLER
:
1137 EXCEPTION_CONTINUE_SEARCH
)
1144 /* Remove the top-level IRP flag */
1145 PsGetCurrentThread()->TopLevelIrp
= 0;
1147 /* Return to caller */
1150 ExReleaseResourceLite(FcbHeader
->Resource
);
1151 FsRtlExitFileSystem();
1161 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject
,
1162 IN PLARGE_INTEGER FileOffset
,
1165 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1166 PFAST_IO_DISPATCH FastDispatch
;
1168 /* Get Device Object and Fast Calls */
1169 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1170 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1172 /* Check if we support Fast Calls, and check this one */
1173 if (FastDispatch
&& FastDispatch
->MdlWriteComplete
)
1175 /* Use the fast path */
1176 return FastDispatch
->MdlWriteComplete(FileObject
,
1182 /* Get the Base File System (Volume) and Fast Calls */
1183 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1184 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1186 /* If the Base Device Object has its own FastDispatch Routine, fail */
1188 FastDispatch
->MdlWriteComplete
&&
1189 BaseDeviceObject
!= DeviceObject
)
1194 /* No fast path, use slow path */
1195 return FsRtlMdlWriteCompleteDev(FileObject
,
1206 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject
,
1207 IN PLARGE_INTEGER FileOffset
,
1209 IN PDEVICE_OBJECT DeviceObject
)
1211 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1216 /* Call the Cache Manager */
1217 CcMdlWriteComplete2(FileObject
, FileOffset
, MdlChain
);
1226 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject
,
1227 IN PLARGE_INTEGER FileOffset
,
1231 OUT PIO_STATUS_BLOCK IoStatus
)
1233 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1234 PFAST_IO_DISPATCH FastDispatch
;
1236 /* Get Device Object and Fast Calls */
1237 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1238 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1240 /* Check if we support Fast Calls, and check this one */
1241 if (FastDispatch
&& FastDispatch
->PrepareMdlWrite
)
1243 /* Use the fast path */
1244 return FastDispatch
->PrepareMdlWrite(FileObject
,
1253 /* Get the Base File System (Volume) and Fast Calls */
1254 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1255 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1257 /* If the Base Device Object has its own FastDispatch Routine, fail */
1259 FastDispatch
->PrepareMdlWrite
&&
1260 BaseDeviceObject
!= DeviceObject
)
1265 /* No fast path, use slow path */
1266 return FsRtlPrepareMdlWriteDev(FileObject
,
1280 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject
,
1281 IN PLARGE_INTEGER FileOffset
,
1285 OUT PIO_STATUS_BLOCK IoStatus
,
1286 IN PDEVICE_OBJECT DeviceObject
)
1288 BOOLEAN Result
= TRUE
;
1289 PFAST_IO_DISPATCH FastIoDispatch
;
1290 PDEVICE_OBJECT Device
;
1291 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1292 PSHARED_CACHE_MAP SharedCacheMap
;
1294 LARGE_INTEGER OldFileSize
;
1295 LARGE_INTEGER OldValidDataLength
;
1296 LARGE_INTEGER NewSize
;
1297 LARGE_INTEGER Offset
;
1300 * Offset == 0xffffffffffffffff indicates append to the end of file.
1302 BOOLEAN FileOffsetAppend
= (FileOffset
->HighPart
== (LONG
)0xffffffff) &&
1303 (FileOffset
->LowPart
== 0xffffffff);
1305 BOOLEAN FileSizeModified
= FALSE
;
1306 BOOLEAN ResourceAcquiredShared
= FALSE
;
1308 /* Initialize some of the vars and pointers */
1309 OldFileSize
.QuadPart
= 0;
1310 OldValidDataLength
.QuadPart
= 0;
1314 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1317 * Check with Cc if we can write.
1319 if (!CcCanIWrite(FileObject
, Length
, TRUE
, FALSE
) ||
1320 (FileObject
->Flags
& FO_WRITE_THROUGH
))
1325 IoStatus
->Status
= STATUS_SUCCESS
;
1327 /* No actual read */
1333 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1334 FsRtlEnterFileSystem();
1336 /* Check we are going to extend the file */
1337 if ((FileOffsetAppend
== FALSE
) &&
1338 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
1340 /* Acquire the resource shared */
1341 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
1342 ResourceAcquiredShared
= TRUE
;
1346 /* Acquire the resource exclusive */
1347 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1350 /* Check if we are appending */
1351 if (FileOffsetAppend
== TRUE
)
1353 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1354 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1358 Offset
.QuadPart
= FileOffset
->QuadPart
;
1359 NewSize
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1362 if ((FileObject
->PrivateCacheMap
) &&
1363 (FcbHeader
->IsFastIoPossible
) &&
1364 (Length
<= MAXLONGLONG
- FileOffset
->QuadPart
) &&
1365 (NewSize
.QuadPart
<= FcbHeader
->AllocationSize
.QuadPart
))
1367 /* Check if we can keep the lock shared */
1368 if (ResourceAcquiredShared
&&
1369 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
1371 ExReleaseResourceLite(FcbHeader
->Resource
);
1372 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1374 /* Compute the offset and the new filesize */
1375 if (FileOffsetAppend
)
1377 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1378 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1381 /* Recheck the above points since we released and reacquire the lock */
1382 if ((FileObject
->PrivateCacheMap
!= NULL
) &&
1383 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
1384 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
1390 goto FailAndCleanup
;
1394 /* Check if we need to find out if fast I/O is available */
1395 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1398 /* ASSERT(!KeIsExecutingDpc()); */
1400 /* Get the Fast I/O table */
1401 Device
= IoGetRelatedDeviceObject(FileObject
);
1402 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1405 ASSERT(FastIoDispatch
!= NULL
);
1406 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1408 /* Ask the driver if we can do it */
1409 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1418 /* It's not, fail */
1419 goto FailAndCleanup
;
1423 /* If we are going to modify the filesize,
1424 * save the old fs in case the operation fails.
1426 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1428 FileSizeModified
= TRUE
;
1429 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1430 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
1432 /* If the high part of the filesize is going
1433 * to change, grab the Paging IoResouce.
1435 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
1436 FcbHeader
->PagingIoResource
)
1438 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1439 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1440 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1444 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1450 * Set ourselves as top component.
1452 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1455 /* Check if there is a gap between the end of the file and the offset.
1456 * If yes, then we have to zero the data.
1458 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1460 Result
= CcZeroData(FileObject
,
1461 &FcbHeader
->ValidDataLength
,
1466 CcPrepareMdlWrite(FileObject
,
1475 CcPrepareMdlWrite(FileObject
, &Offset
, Length
, MdlChain
, IoStatus
);
1479 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1480 EXCEPTION_EXECUTE_HANDLER
:
1481 EXCEPTION_CONTINUE_SEARCH
)
1487 /* Reset the top component */
1488 PsGetCurrentThread()->TopLevelIrp
= 0;
1490 /* Did the operation suceeded */
1493 /* Check if we need to update the filesize */
1494 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1496 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
1497 FcbHeader
->PagingIoResource
)
1499 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1500 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1501 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1505 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1509 /* Flag the file as modified */
1510 FileObject
->Flags
|= FO_FILE_MODIFIED
;
1512 /* Check if the filesize has changed */
1513 if (FileSizeModified
)
1516 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
1517 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1518 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
1523 /* The operation did not succeed.
1524 * Reset the file size to what it should be.
1526 if (FileSizeModified
)
1528 if (FcbHeader
->PagingIoResource
)
1530 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1531 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1532 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1533 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1537 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1538 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1547 goto FailAndCleanup
;
1552 ExReleaseResourceLite(FcbHeader
->Resource
);
1553 FsRtlExitFileSystem();
1558 ExReleaseResourceLite(FcbHeader
->Resource
);
1559 FsRtlExitFileSystem();
1565 FsRtlAcquireFileExclusiveCommon(IN PFILE_OBJECT FileObject
,
1566 IN FS_FILTER_SECTION_SYNC_TYPE SyncType
,
1569 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1570 PDEVICE_OBJECT DeviceObject
;
1571 PFAST_IO_DISPATCH FastDispatch
;
1573 /* Get Device Object and Fast Calls */
1574 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1575 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1576 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1578 /* Get master FsRtl lock */
1579 FsRtlEnterFileSystem();
1581 /* Check if Fast Calls are supported, and check AcquireFileForNtCreateSection */
1583 FastDispatch
->AcquireFileForNtCreateSection
)
1585 /* Call the AcquireFileForNtCreateSection FastIo handler */
1586 FastDispatch
->AcquireFileForNtCreateSection(FileObject
);
1590 /* No FastIo handler, acquire file's resource exclusively */
1591 if (FcbHeader
&& FcbHeader
->Resource
) ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1594 return STATUS_SUCCESS
;
1602 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject
)
1606 /* Call the common routine. Don't care about the result */
1607 (VOID
)FsRtlAcquireFileExclusiveCommon(FileObject
, SyncTypeOther
, 0);
1615 FsRtlReleaseFile(IN PFILE_OBJECT FileObject
)
1617 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1618 PDEVICE_OBJECT DeviceObject
;
1619 PFAST_IO_DISPATCH FastDispatch
;
1621 /* Get Device Object and Fast Calls */
1622 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1623 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1624 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1626 /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
1628 FastDispatch
->ReleaseFileForNtCreateSection
)
1630 /* Call the ReleaseFileForNtCreateSection FastIo handler */
1631 FastDispatch
->ReleaseFileForNtCreateSection(FileObject
);
1635 /* No FastIo handler, release file's resource */
1636 if (FcbHeader
&& FcbHeader
->Resource
) ExReleaseResourceLite(FcbHeader
->Resource
);
1639 /* Release master FsRtl lock */
1640 FsRtlExitFileSystem();
1648 FsRtlAcquireFileForCcFlushEx(IN PFILE_OBJECT FileObject
)
1650 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1651 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1652 PFAST_IO_DISPATCH FastDispatch
;
1655 /* Get the Base File System (Volume) and Fast Calls */
1656 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1657 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1658 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1659 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1661 /* Get master FsRtl lock */
1662 FsRtlEnterFileSystem();
1664 /* Check if Fast Calls are supported, and check AcquireForCcFlush */
1666 FastDispatch
->AcquireForCcFlush
)
1668 /* Call the AcquireForCcFlush FastIo handler */
1669 Status
= FastDispatch
->AcquireForCcFlush(FileObject
, BaseDeviceObject
);
1671 /* Return either success or inability to wait.
1672 In case of other failure - fall through */
1673 if (Status
== STATUS_SUCCESS
||
1674 Status
== STATUS_CANT_WAIT
)
1680 /* No FastIo handler (or it failed). Acquire Main resource */
1681 if (FcbHeader
->Resource
)
1683 /* Acquire it - either shared if it's already acquired
1684 or exclusively if we are the first */
1685 if (ExIsResourceAcquiredSharedLite(FcbHeader
->Resource
))
1686 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
1688 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, TRUE
);
1691 /* Also acquire its PagingIO resource */
1692 if (FcbHeader
->PagingIoResource
)
1693 ExAcquireResourceSharedLite(FcbHeader
->PagingIoResource
, TRUE
);
1695 return STATUS_SUCCESS
;
1703 FsRtlAcquireFileForCcFlush(IN PFILE_OBJECT FileObject
)
1707 /* Call the common routine. Don't care about the result */
1708 (VOID
)FsRtlAcquireFileForCcFlushEx(FileObject
);
1717 FsRtlReleaseFileForCcFlush(IN PFILE_OBJECT FileObject
)
1719 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1720 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1721 PFAST_IO_DISPATCH FastDispatch
;
1722 NTSTATUS Status
= STATUS_INVALID_DEVICE_REQUEST
;
1724 /* Get Device Object and Fast Calls */
1725 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1726 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1727 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1728 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1730 /* Check if Fast Calls are supported, and check ReleaseForCcFlush */
1732 FastDispatch
->ReleaseForCcFlush
)
1734 /* Call the ReleaseForCcFlush FastIo handler */
1735 Status
= FastDispatch
->ReleaseForCcFlush(FileObject
, BaseDeviceObject
);
1738 if (!NT_SUCCESS(Status
))
1740 /* No FastIo handler (or it failed). Release PagingIO resource and
1741 then Main resource */
1742 if (FcbHeader
->PagingIoResource
) ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1743 if (FcbHeader
->Resource
) ExReleaseResourceLite(FcbHeader
->Resource
);
1746 /* Release master FsRtl lock */
1747 FsRtlExitFileSystem();
1755 FsRtlAcquireFileForModWriteEx(IN PFILE_OBJECT FileObject
,
1756 IN PLARGE_INTEGER EndingOffset
,
1757 IN PERESOURCE
*ResourceToRelease
)
1759 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1760 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1761 PFAST_IO_DISPATCH FastDispatch
;
1762 PERESOURCE ResourceToAcquire
= NULL
;
1763 BOOLEAN Exclusive
= FALSE
;
1765 NTSTATUS Status
= STATUS_SUCCESS
;
1767 /* Get Device Object and Fast Calls */
1768 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1769 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1770 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1771 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1773 /* Check if Fast Calls are supported, and check AcquireForModWrite */
1775 FastDispatch
->AcquireForModWrite
)
1777 /* Call the AcquireForModWrite FastIo handler */
1778 Status
= FastDispatch
->AcquireForModWrite(FileObject
,
1783 /* Return either success or inability to wait.
1784 In case of other failure - fall through */
1785 if (Status
== STATUS_SUCCESS
||
1786 Status
== STATUS_CANT_WAIT
)
1792 Status
= STATUS_SUCCESS
;
1794 /* No FastIo handler, use algorithm from Nagar p.550. */
1795 if (!FcbHeader
->Resource
)
1797 *ResourceToRelease
= NULL
;
1798 return STATUS_SUCCESS
;
1801 /* Default condition - shared acquiring of Paging IO Resource */
1802 ResourceToAcquire
= FcbHeader
->PagingIoResource
;
1804 /* Decide on type of locking and type of resource based on historical magic
1805 well explain by Nagar in p. 550-551 */
1806 if ((EndingOffset
->QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
&&
1807 FcbHeader
->FileSize
.QuadPart
!= FcbHeader
->ValidDataLength
.QuadPart
) ||
1808 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
))
1810 /* Either exclusive flag is set or write operation is extending
1811 the valid data length. Prefer exclusive acquire then */
1813 ResourceToAcquire
= FcbHeader
->Resource
;
1815 else if (!FcbHeader
->PagingIoResource
||
1816 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
))
1818 /* Acquire main resource shared if flag is specified or
1819 if PagingIo resource is missing */
1821 ResourceToAcquire
= FcbHeader
->Resource
;
1824 /* Acquire the resource in the loop, since the above code is unsafe */
1830 Result
= ExAcquireResourceExclusiveLite(ResourceToAcquire
, FALSE
);
1832 Result
= ExAcquireSharedWaitForExclusive(ResourceToAcquire
, FALSE
);
1835 Status
= STATUS_CANT_WAIT
;
1839 /* Do the magic ifs again */
1840 if ((EndingOffset
->QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) ||
1841 (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_EX
))
1843 /* Check what we have */
1846 /* Asked for exclusive, got exclusive! */
1851 /* Asked for exclusive, got shared. Release it and retry. */
1852 ExReleaseResourceLite(ResourceToAcquire
);
1854 ResourceToAcquire
= FcbHeader
->Resource
;
1857 else if (FcbHeader
->Flags
& FSRTL_FLAG_ACQUIRE_MAIN_RSRC_SH
)
1861 /* Asked for shared, got exclusive - convert */
1862 ExConvertExclusiveToSharedLite(ResourceToAcquire
);
1865 else if (ResourceToAcquire
!= FcbHeader
->Resource
)
1867 /* Asked for main resource, got something else */
1868 ExReleaseResourceLite(ResourceToAcquire
);
1869 ResourceToAcquire
= FcbHeader
->Resource
;
1873 else if (FcbHeader
->PagingIoResource
&&
1874 ResourceToAcquire
!= FcbHeader
->PagingIoResource
)
1876 /* There is PagingIo resource, but other resource was acquired */
1877 ResourceToAcquire
= FcbHeader
->PagingIoResource
;
1878 if (!ExAcquireSharedWaitForExclusive(ResourceToAcquire
, FALSE
))
1880 Status
= STATUS_CANT_WAIT
;
1881 ExReleaseResourceLite(FcbHeader
->Resource
);
1888 /* Asked for shared got exclusive - convert */
1889 ExConvertExclusiveToSharedLite(ResourceToAcquire
);
1894 /* If the resource was acquired successfully - pass it to the caller */
1895 if (NT_SUCCESS(Status
))
1896 *ResourceToRelease
= ResourceToAcquire
;
1906 FsRtlReleaseFileForModWrite(IN PFILE_OBJECT FileObject
,
1907 IN PERESOURCE ResourceToRelease
)
1909 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1910 PFAST_IO_DISPATCH FastDispatch
;
1911 NTSTATUS Status
= STATUS_SUCCESS
;
1913 /* Get Device Object and Fast Calls */
1914 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1915 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1916 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1918 /* Check if Fast Calls are supported and check ReleaseFileForNtCreateSection */
1920 FastDispatch
->ReleaseForModWrite
)
1922 /* Call the ReleaseForModWrite FastIo handler */
1923 Status
= FastDispatch
->ReleaseForModWrite(FileObject
,
1928 /* Just release the resource if previous op failed */
1929 if (!NT_SUCCESS(Status
))
1931 ExReleaseResourceLite(ResourceToRelease
);
1937 * @name FsRtlRegisterFileSystemFilterCallbacks
1942 * @param FilterDriverObject
1955 FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject
,
1956 IN PFS_FILTER_CALLBACKS Callbacks
)
1959 return STATUS_NOT_IMPLEMENTED
;