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: buzdelabuz2@gmail.com,alex.ionescu@reactos.org
9 /* INCLUDES ******************************************************************/
15 /* PUBLIC FUNCTIONS **********************************************************/
22 FsRtlIncrementCcFastReadResourceMiss(VOID
)
24 CcFastReadResourceMiss
++;
32 FsRtlIncrementCcFastReadNotPossible(VOID
)
34 CcFastReadNotPossible
++;
42 FsRtlIncrementCcFastReadWait(VOID
)
52 FsRtlIncrementCcFastReadNoWait(VOID
)
62 FsRtlCopyRead(IN PFILE_OBJECT FileObject
,
63 IN PLARGE_INTEGER FileOffset
,
68 OUT PIO_STATUS_BLOCK IoStatus
,
69 IN PDEVICE_OBJECT DeviceObject
)
72 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
74 PFAST_IO_DISPATCH FastIoDispatch
;
75 PDEVICE_OBJECT Device
;
76 BOOLEAN Result
= TRUE
;
77 ULONG PageCount
= ADDRESS_AND_SIZE_TO_SPAN_PAGES(FileOffset
,Length
);
81 ASSERT(FileObject
->FsContext
);
87 IoStatus
->Status
= STATUS_SUCCESS
;
88 IoStatus
->Information
= 0;
92 if (Length
> MAXLONGLONG
- FileOffset
->QuadPart
)
94 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
95 IoStatus
->Information
= 0;
99 /* Get the offset and FCB header */
100 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
101 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
105 /* Use a Resource Acquire */
106 FsRtlEnterFileSystem();
108 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
112 /* Acquire the resource without blocking. Return false and the I/O manager
113 * will retry using the standard IRP method. Use a Resource Acquire.
115 FsRtlEnterFileSystem();
116 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, FALSE
))
118 FsRtlExitFileSystem();
119 FsRtlIncrementCcFastReadResourceMiss();
124 /* Check if this is a fast I/O cached file */
125 if (!(FileObject
->PrivateCacheMap
) ||
126 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
128 /* It's not, so fail */
133 /* Check if we need to find out if fast I/O is available */
134 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
137 ASSERT(!KeIsExecutingDpc());
139 /* Get the Fast I/O table */
140 Device
= IoGetRelatedDeviceObject(FileObject
);
141 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
144 ASSERT(FastIoDispatch
!= NULL
);
145 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
147 /* Ask the driver if we can do it */
148 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
163 /* Check if we read too much */
164 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
166 /* We did, check if the file offset is past the end */
167 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
169 /* Set end of file */
170 IoStatus
->Status
= STATUS_END_OF_FILE
;
171 IoStatus
->Information
= 0;
175 /* Otherwise, just normalize the length */
176 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
179 /* Set this as top-level IRP */
180 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
184 /* Make sure the IO and file size is below 4GB */
185 if (Wait
&& !(Offset
.HighPart
| FcbHeader
->FileSize
.HighPart
))
188 /* Call the cache controller */
189 CcFastCopyRead(FileObject
,
196 /* File was accessed */
197 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
199 if (IoStatus
->Status
!= STATUS_END_OF_FILE
)
201 ASSERT(FcbHeader
->FileSize
.QuadPart
>=
202 FileOffset
->QuadPart
+ IoStatus
->Information
);
208 /* Call the cache controller */
209 Result
= CcCopyRead(FileObject
,
216 /* File was accessed */
217 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
221 ASSERT( (IoStatus
->Status
== STATUS_END_OF_FILE
) ||
222 ((LONGLONG
)(FileOffset
->QuadPart
+ IoStatus
->Information
) <=
223 FcbHeader
->FileSize
.QuadPart
));
227 /* Update the current file offset */
230 FileObject
->CurrentByteOffset
.QuadPart
+= IoStatus
->Information
;
233 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
234 EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH
)
240 PsGetCurrentThread()->TopLevelIrp
= 0;
242 /* Return to caller */
245 ExReleaseResourceLite(FcbHeader
->Resource
);
246 FsRtlExitFileSystem();
250 CcFastReadNotPossible
+= 1;
262 FsRtlCopyWrite(IN PFILE_OBJECT FileObject
,
263 IN PLARGE_INTEGER FileOffset
,
268 OUT PIO_STATUS_BLOCK IoStatus
,
269 IN PDEVICE_OBJECT DeviceObject
)
271 BOOLEAN Result
= TRUE
;
272 PFAST_IO_DISPATCH FastIoDispatch
;
273 PDEVICE_OBJECT Device
;
274 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
275 PSHARED_CACHE_MAP SharedCacheMap
;
278 * Offset == 0xffffffffffffffff indicates append to the end of file.
280 BOOLEAN FileOffsetAppend
= (FileOffset
->HighPart
== (LONG
)0xffffffff) &&
281 (FileOffset
->LowPart
== 0xffffffff);
283 BOOLEAN ResourceAquiredShared
= FALSE
;
284 BOOLEAN b_4GB
= FALSE
;
285 BOOLEAN FileSizeModified
= FALSE
;
286 LARGE_INTEGER OldFileSize
;
287 LARGE_INTEGER OldValidDataLength
;
288 LARGE_INTEGER NewSize
;
289 LARGE_INTEGER Offset
;
294 ASSERT(FileObject
->FsContext
);
296 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
297 /* Silence incorrect GCC 4.5.x warning */
298 OldFileSize
.LowPart
= 0;
301 /* Initialize some of the vars and pointers */
302 NewSize
.QuadPart
= 0;
303 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
304 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
307 * Check with Cc if we can write and check if the IO > 64kB (WDK macro).
309 if ( (CcCanIWrite(FileObject
, Length
,Wait
, FALSE
) == FALSE
) ||
310 (CcCopyWriteWontFlush(FileObject
,FileOffset
,Length
) == FALSE
) ||
311 ((FileObject
->Flags
& FO_WRITE_THROUGH
) == TRUE
))
319 IoStatus
->Status
= STATUS_SUCCESS
;
320 IoStatus
->Information
= Length
;
324 FsRtlEnterFileSystem();
327 * The CcFastCopyWrite doesn't deal with filesize beyond 4GB.
329 if (Wait
&& (FcbHeader
->AllocationSize
.HighPart
== 0))
331 /* If the file offset is not past the file size,
332 * then we can acquire the lock shared.
334 if ((FileOffsetAppend
== FALSE
) &&
335 (Offset
.LowPart
<= FcbHeader
->ValidDataLength
.LowPart
))
337 ExAcquireResourceSharedLite(FcbHeader
->Resource
,TRUE
);
338 ResourceAquiredShared
= TRUE
;
342 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
346 * If we append, use the file size as offset.
347 * Also, check that we aren't crossing the 4GB boundary.
349 if (FileOffsetAppend
== TRUE
)
351 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
;
352 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
353 b_4GB
= (NewSize
.LowPart
< FcbHeader
->FileSize
.LowPart
);
358 Offset
.LowPart
= FileOffset
->LowPart
;
359 NewSize
.LowPart
= FileOffset
->LowPart
+ Length
;
360 b_4GB
= (NewSize
.LowPart
< FileOffset
->LowPart
) ||
361 (FileOffset
->HighPart
!= 0);
365 * Make sure that caching is initated.
366 * That fast are allowed for this file stream.
367 * That we are not extending past the allocated size.
368 * That we are not creating a hole bigger than 8k.
369 * That we are not crossing the 4GB boundary.
371 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
372 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
373 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
374 (Offset
.LowPart
< FcbHeader
->ValidDataLength
.LowPart
+ 0x2000) &&
377 /* If we are extending past the file size, we need to
378 * release the lock and acquire it exclusively, because
379 * we are going to need to update the FcbHeader.
381 if (ResourceAquiredShared
&&
382 (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
+ 0x2000))
384 /* Then we need to acquire the resource exclusive */
385 ExReleaseResourceLite(FcbHeader
->Resource
);
386 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
387 if (FileOffsetAppend
== TRUE
)
389 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
; // ??
390 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
392 /* Make sure we don't cross the 4GB boundary */
393 b_4GB
= (NewSize
.LowPart
< Offset
.LowPart
);
396 /* Recheck some of the conditions since we let the lock go */
397 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
398 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
399 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
400 (FcbHeader
->AllocationSize
.HighPart
== 0) &&
417 /* Check if we need to find out if fast I/O is available */
418 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
420 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
423 ASSERT(!KeIsExecutingDpc());
425 /* Get the Fast I/O table */
426 Device
= IoGetRelatedDeviceObject(FileObject
);
427 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
430 ASSERT(FastIoDispatch
!= NULL
);
431 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
433 /* Ask the driver if we can do it */
434 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
436 &FcbHeader
->FileSize
:
442 &FastIoCheckIfPossibleStatus
,
450 /* If we are going to extend the file then save
451 * the old file size in case the operation fails.
453 if (NewSize
.LowPart
> FcbHeader
->FileSize
.LowPart
)
455 FileSizeModified
= TRUE
;
456 OldFileSize
.LowPart
= FcbHeader
->FileSize
.LowPart
;
457 OldValidDataLength
.LowPart
= FcbHeader
->ValidDataLength
.LowPart
;
458 FcbHeader
->FileSize
.LowPart
= NewSize
.LowPart
;
461 /* Set this as top-level IRP */
462 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
466 if (Offset
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
468 LARGE_INTEGER OffsetVar
;
469 OffsetVar
.LowPart
= Offset
.LowPart
;
470 OffsetVar
.HighPart
= 0;
471 CcZeroData(FileObject
,&FcbHeader
->ValidDataLength
,&OffsetVar
,TRUE
);
474 /* Call the cache manager */
475 CcFastCopyWrite(FileObject
,Offset
.LowPart
,Length
,Buffer
);
477 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
478 EXCEPTION_EXECUTE_HANDLER
:
479 EXCEPTION_CONTINUE_SEARCH
)
485 /* Remove ourselves at the top level component after the IO is done */
486 PsGetCurrentThread()->TopLevelIrp
= 0;
488 /* Did the operation succeed ? */
491 /* Update the valid file size if necessary */
492 if (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
)
494 FcbHeader
->ValidDataLength
.LowPart
= NewSize
.LowPart
;
497 /* Flag the file as modified */
498 FileObject
->Flags
|= FO_FILE_MODIFIED
;
500 /* Update the strucutres if the file size changed */
501 if (FileSizeModified
)
504 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
505 SharedCacheMap
->FileSize
.LowPart
= NewSize
.LowPart
;
506 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
509 /* Update the file object current file offset */
510 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.LowPart
;
515 /* Result == FALSE if we get here */
516 if (FileSizeModified
)
518 /* If the file size was modified then restore the old file size */
519 if (FcbHeader
->PagingIoResource
!= NULL
)
522 * Restore the old file size if operation didn't succeed.
524 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
,TRUE
);
525 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
526 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
527 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
531 /* If there is no lock and do it without */
532 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
533 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
546 LARGE_INTEGER OldFileSize
;
548 #if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ == 405)
549 /* Silence incorrect GCC 4.5.x warning */
550 OldFileSize
.QuadPart
= 0;
554 ASSERT(!KeIsExecutingDpc());
557 * Check if we need to acquire the resource exclusive.
559 if ( (FileOffsetAppend
== FALSE
) &&
560 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
562 /* Acquire the resource shared */
563 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, Wait
))
565 goto LeaveCriticalAndFail
;
567 ResourceAquiredShared
=TRUE
;
571 /* Acquire the resource exclusive */
572 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
, Wait
))
574 goto LeaveCriticalAndFail
;
578 /* Check if we are appending */
579 if (FileOffsetAppend
== TRUE
)
581 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
582 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
586 Offset
.QuadPart
= FileOffset
->QuadPart
;
587 NewSize
.QuadPart
+= FileOffset
->QuadPart
+ Length
;
591 * Make sure that caching is initated.
592 * That fast are allowed for this file stream.
593 * That we are not extending past the allocated size.
594 * That we are not creating a hole bigger than 8k.
596 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
597 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
598 (FcbHeader
->ValidDataLength
.QuadPart
+ 0x2000 > Offset
.QuadPart
) &&
599 (Length
<= MAXLONGLONG
- Offset
.QuadPart
) &&
600 (FcbHeader
->AllocationSize
.QuadPart
>= NewSize
.QuadPart
))
602 /* Check if we can keep the lock shared */
603 if (ResourceAquiredShared
&&
604 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
606 ExReleaseResourceLite(FcbHeader
->Resource
);
607 if(!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,Wait
))
609 goto LeaveCriticalAndFail
;
612 /* Compute the offset and the new filesize */
613 if (FileOffsetAppend
)
615 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
616 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
619 /* Recheck the above points since we released and reacquire the lock */
620 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
621 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
622 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
632 /* Check if we need to find out if fast I/O is available */
633 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
635 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
638 ASSERT(!KeIsExecutingDpc());
640 /* Get the Fast I/O table */
641 Device
= IoGetRelatedDeviceObject(FileObject
);
642 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
645 ASSERT(FastIoDispatch
!= NULL
);
646 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
648 /* Ask the driver if we can do it */
649 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
651 &FcbHeader
->FileSize
:
657 &FastIoCheckIfPossibleStatus
,
665 /* If we are going to modify the filesize,
666 * save the old fs in case the operation fails.
668 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
670 FileSizeModified
= TRUE
;
671 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
672 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
674 /* If the high part of the filesize is going
675 * to change, grab the Paging IoResouce.
677 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
678 FcbHeader
->PagingIoResource
)
680 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
681 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
682 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
686 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
691 * Set ourselves as top component.
693 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
697 BOOLEAN CallCc
= TRUE
;
699 /* Check if there is a gap between the end of the file
700 * and the offset. If yes, then we have to zero the data.
702 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
704 if (!(Result
= CcZeroData(FileObject
,
705 &FcbHeader
->ValidDataLength
,
709 /* If this operation fails, then we have to exit. We can jump
710 * outside the SEH, so I a using a variable to exit normally.
716 /* Unless the CcZeroData failed, call the cache manager */
719 Result
= CcCopyWrite(FileObject
,&Offset
,Length
, Wait
, Buffer
);
722 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
723 EXCEPTION_EXECUTE_HANDLER
:
724 EXCEPTION_CONTINUE_SEARCH
)
730 /* Reset the top component */
731 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
733 /* Did the operation suceeded */
736 /* Check if we need to update the filesize */
737 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
739 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
740 FcbHeader
->PagingIoResource
)
742 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
743 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
744 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
748 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
752 /* Flag the file as modified */
753 FileObject
->Flags
|= FO_FILE_MODIFIED
;
755 /* Check if the filesize has changed */
756 if (FileSizeModified
)
758 /* Update the file sizes */
760 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
761 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
762 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
765 /* Update the current FO byte offset */
766 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.QuadPart
;
770 /* The operation did not succeed.
771 * Reset the file size to what it should be.
773 if (FileSizeModified
)
775 if (FcbHeader
->PagingIoResource
)
777 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
778 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
779 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
780 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
784 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
785 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
798 LeaveCriticalAndFail
:
800 FsRtlExitFileSystem();
805 ExReleaseResourceLite(FcbHeader
->Resource
);
806 FsRtlExitFileSystem();
811 ExReleaseResourceLite(FcbHeader
->Resource
);
812 FsRtlExitFileSystem();
821 FsRtlGetFileSize(IN PFILE_OBJECT FileObject
,
822 IN OUT PLARGE_INTEGER FileSize
)
824 FILE_STANDARD_INFORMATION Info
;
826 IO_STATUS_BLOCK IoStatus
;
827 PDEVICE_OBJECT DeviceObject
;
828 PFAST_IO_DISPATCH FastDispatch
;
830 PIO_STACK_LOCATION IoStackLocation
;
832 BOOLEAN OldHardError
;
836 /* Get Device Object and Fast Calls */
837 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
838 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
840 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo.
841 * Call the function and see if it succeeds.
843 if ( !FastDispatch
||
844 !FastDispatch
->FastIoQueryStandardInfo
||
845 !FastDispatch
->FastIoQueryStandardInfo(FileObject
,
851 /* If any of the above failed, then we are going to send an
852 * IRP to the device object. Initialize the event for the IO.
854 KeInitializeEvent(&Event
,NotificationEvent
,FALSE
);
856 /* Allocate the IRP */
857 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,FALSE
);
861 return STATUS_INSUFFICIENT_RESOURCES
;
864 /* Don't process hard error */
865 OldHardError
= IoSetThreadHardErrorMode(FALSE
);
868 Irp
->UserIosb
= &IoStatus
;
869 Irp
->UserEvent
= &Event
;
870 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
871 Irp
->Flags
= IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
;
872 Irp
->RequestorMode
= KernelMode
;
873 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
874 Irp
->AssociatedIrp
.SystemBuffer
= &Info
;
876 /* Setup out stack location */
877 IoStackLocation
= Irp
->Tail
.Overlay
.CurrentStackLocation
;
879 IoStackLocation
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
880 IoStackLocation
->FileObject
= FileObject
;
881 IoStackLocation
->DeviceObject
= DeviceObject
;
882 IoStackLocation
->Parameters
.QueryFile
.Length
=
883 ALIGN_UP(sizeof(FILE_INFORMATION_CLASS
), ULONG
);
884 IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
=
885 FileStandardInformation
;
887 /* Send the IRP to the related device object */
888 Status
= IoCallDriver(DeviceObject
,Irp
);
890 /* Standard DDK IRP result processing */
891 if (Status
== STATUS_PENDING
)
893 KeWaitForSingleObject(&Event
,Executive
,KernelMode
,FALSE
,NULL
);
896 /* If there was a synchronous error, signal it */
897 if (!NT_SUCCESS(Status
))
899 IoStatus
.Status
= Status
;
902 IoSetThreadHardErrorMode(OldHardError
);
905 /* Check the sync/async IO result */
906 if (NT_SUCCESS(IoStatus
.Status
))
908 /* Was the request for a directory ? */
911 IoStatus
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
915 FileSize
->QuadPart
= Info
.EndOfFile
.QuadPart
;
919 return IoStatus
.Status
;
927 FsRtlMdlRead(IN PFILE_OBJECT FileObject
,
928 IN PLARGE_INTEGER FileOffset
,
932 OUT PIO_STATUS_BLOCK IoStatus
)
934 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
935 PFAST_IO_DISPATCH FastDispatch
;
937 /* Get Device Object and Fast Calls */
938 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
939 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
941 /* Check if we support Fast Calls, and check this one */
942 if (FastDispatch
&& FastDispatch
->MdlRead
)
944 /* Use the fast path */
945 return FastDispatch
->MdlRead(FileObject
,
954 /* Get the Base File System (Volume) and Fast Calls */
955 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
956 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
958 /* If the Base Device Object has its own FastDispatch Routine, fail */
959 if (FastDispatch
&& FastDispatch
->MdlRead
&& BaseDeviceObject
!= DeviceObject
)
964 /* No fast path, use slow path */
965 return FsRtlMdlReadDev(FileObject
,
979 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject
,
980 IN OUT PMDL MdlChain
)
982 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
983 PFAST_IO_DISPATCH FastDispatch
;
985 /* Get Device Object and Fast Calls */
986 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
987 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
989 /* Check if we support Fast Calls, and check this one */
990 if (FastDispatch
&& FastDispatch
->MdlReadComplete
)
992 /* Use the fast path */
993 return FastDispatch
->MdlReadComplete(FileObject
, MdlChain
, DeviceObject
);
996 /* Get the Base File System (Volume) and Fast Calls */
997 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
998 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1000 /* If the Base Device Object has its own FastDispatch Routine, fail */
1001 if ((BaseDeviceObject
!= DeviceObject
) &&
1003 FastDispatch
->MdlReadComplete
)
1008 /* No fast path, use slow path */
1009 return FsRtlMdlReadCompleteDev(FileObject
, MdlChain
, DeviceObject
);
1017 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject
,
1018 IN PMDL MemoryDescriptorList
,
1019 IN PDEVICE_OBJECT DeviceObject
)
1021 /* Call the Cache Manager */
1022 CcMdlReadComplete2(MemoryDescriptorList
, FileObject
);
1031 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject
,
1032 IN PLARGE_INTEGER FileOffset
,
1036 OUT PIO_STATUS_BLOCK IoStatus
,
1037 IN PDEVICE_OBJECT DeviceObject
)
1039 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1040 BOOLEAN Result
= TRUE
;
1041 LARGE_INTEGER Offset
;
1042 PFAST_IO_DISPATCH FastIoDispatch
;
1043 PDEVICE_OBJECT Device
;
1046 /* No actual read */
1049 /* Return success */
1050 IoStatus
->Status
= STATUS_SUCCESS
;
1051 IoStatus
->Information
= 0;
1056 ASSERT(MAXLONGLONG
- FileOffset
->QuadPart
>= (LONGLONG
)Length
);
1058 /* Get the offset and FCB header */
1059 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1060 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1063 FsRtlEnterFileSystem();
1064 CcFastMdlReadWait
++;
1067 ExAcquireResourceShared(FcbHeader
->Resource
, TRUE
);
1069 /* Check if this is a fast I/O cached file */
1070 if (!(FileObject
->PrivateCacheMap
) ||
1071 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
1073 /* It's not, so fail */
1074 CcFastMdlReadNotPossible
+= 1;
1079 /* Check if we need to find out if fast I/O is available */
1080 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1082 /* Get the Fast I/O table */
1083 Device
= IoGetRelatedDeviceObject(FileObject
);
1084 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1087 ASSERT(!KeIsExecutingDpc());
1088 ASSERT(FastIoDispatch
!= NULL
);
1089 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1091 /* Ask the driver if we can do it */
1092 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1101 /* It's not, fail */
1102 CcFastMdlReadNotPossible
+= 1;
1108 /* Check if we read too much */
1109 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1111 /* We did, check if the file offset is past the end */
1112 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
1114 /* Set end of file */
1115 IoStatus
->Status
= STATUS_END_OF_FILE
;
1116 IoStatus
->Information
= 0;
1120 /* Otherwise, just normalize the length */
1121 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
1124 /* Set this as top-level IRP */
1125 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1129 /* Attempt a read */
1130 CcMdlRead(FileObject
, FileOffset
, Length
, MdlChain
, IoStatus
);
1131 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
1133 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1134 EXCEPTION_EXECUTE_HANDLER
:
1135 EXCEPTION_CONTINUE_SEARCH
)
1142 /* Remove the top-level IRP flag */
1143 PsGetCurrentThread()->TopLevelIrp
= 0;
1145 /* Return to caller */
1148 ExReleaseResourceLite(FcbHeader
->Resource
);
1149 FsRtlExitFileSystem();
1159 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject
,
1160 IN PLARGE_INTEGER FileOffset
,
1163 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1164 PFAST_IO_DISPATCH FastDispatch
;
1166 /* Get Device Object and Fast Calls */
1167 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1168 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1170 /* Check if we support Fast Calls, and check this one */
1171 if (FastDispatch
&& FastDispatch
->MdlWriteComplete
)
1173 /* Use the fast path */
1174 return FastDispatch
->MdlWriteComplete(FileObject
,
1180 /* Get the Base File System (Volume) and Fast Calls */
1181 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1182 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1184 /* If the Base Device Object has its own FastDispatch Routine, fail */
1186 FastDispatch
->MdlWriteComplete
&&
1187 BaseDeviceObject
!= DeviceObject
)
1192 /* No fast path, use slow path */
1193 return FsRtlMdlWriteCompleteDev(FileObject
,
1204 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject
,
1205 IN PLARGE_INTEGER FileOffset
,
1207 IN PDEVICE_OBJECT DeviceObject
)
1209 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1214 /* Call the Cache Manager */
1215 CcMdlWriteComplete2(FileObject
,FileOffset
,MdlChain
);
1224 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject
,
1225 IN PLARGE_INTEGER FileOffset
,
1229 OUT PIO_STATUS_BLOCK IoStatus
)
1231 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1232 PFAST_IO_DISPATCH FastDispatch
;
1234 /* Get Device Object and Fast Calls */
1235 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1236 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1238 /* Check if we support Fast Calls, and check this one */
1239 if (FastDispatch
&& FastDispatch
->PrepareMdlWrite
)
1241 /* Use the fast path */
1242 return FastDispatch
->PrepareMdlWrite(FileObject
,
1251 /* Get the Base File System (Volume) and Fast Calls */
1252 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1253 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1255 /* If the Base Device Object has its own FastDispatch Routine, fail */
1257 FastDispatch
->PrepareMdlWrite
&&
1258 BaseDeviceObject
!= DeviceObject
)
1263 /* No fast path, use slow path */
1264 return FsRtlPrepareMdlWriteDev(FileObject
,
1278 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject
,
1279 IN PLARGE_INTEGER FileOffset
,
1283 OUT PIO_STATUS_BLOCK IoStatus
,
1284 IN PDEVICE_OBJECT DeviceObject
)
1286 BOOLEAN Result
= TRUE
;
1287 PFAST_IO_DISPATCH FastIoDispatch
;
1288 PDEVICE_OBJECT Device
;
1289 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1290 PSHARED_CACHE_MAP SharedCacheMap
;
1292 LARGE_INTEGER OldFileSize
;
1293 LARGE_INTEGER OldValidDataLength
;
1294 LARGE_INTEGER NewSize
;
1295 LARGE_INTEGER Offset
;
1298 * Offset == 0xffffffffffffffff indicates append to the end of file.
1300 BOOLEAN FileOffsetAppend
= (FileOffset
->HighPart
== (LONG
)0xffffffff) &&
1301 (FileOffset
->LowPart
== 0xffffffff);
1303 BOOLEAN FileSizeModified
= FALSE
;
1304 BOOLEAN ResourceAquiredShared
= FALSE
;
1306 /* Initialize some of the vars and pointers */
1307 OldFileSize
.QuadPart
= 0;
1308 OldValidDataLength
.QuadPart
= 0;
1312 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1315 * Check with Cc if we can write.
1317 if (!CcCanIWrite(FileObject
, Length
, TRUE
, FALSE
) ||
1318 (FileObject
->Flags
& FO_WRITE_THROUGH
))
1323 IoStatus
->Status
= STATUS_SUCCESS
;
1325 /* No actual read */
1331 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1332 FsRtlEnterFileSystem();
1334 /* Check we are going to extend the file */
1335 if ( (FileOffsetAppend
== FALSE
) &&
1336 (FileOffset
->QuadPart
+ Length
<= FcbHeader
->ValidDataLength
.QuadPart
))
1338 /* Acquire the resource shared */
1339 ExAcquireResourceSharedLite(FcbHeader
->Resource
,TRUE
);
1340 ResourceAquiredShared
=TRUE
;
1344 /* Acquire the resource exclusive */
1345 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
1348 /* Check if we are appending */
1349 if (FileOffsetAppend
== TRUE
)
1351 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1352 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1356 Offset
.QuadPart
= FileOffset
->QuadPart
;
1357 NewSize
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1360 if ( (FileObject
->PrivateCacheMap
) &&
1361 (FcbHeader
->IsFastIoPossible
) &&
1362 (Length
<= MAXLONGLONG
- FileOffset
->QuadPart
) &&
1363 (NewSize
.QuadPart
<= FcbHeader
->AllocationSize
.QuadPart
) )
1365 /* Check if we can keep the lock shared */
1366 if (ResourceAquiredShared
&&
1367 (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
))
1369 ExReleaseResourceLite(FcbHeader
->Resource
);
1370 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
1372 /* Compute the offset and the new filesize */
1373 if (FileOffsetAppend
)
1375 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1376 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1379 /* Recheck the above points since we released and reacquire the lock */
1380 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
1381 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
1382 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
))
1388 goto FailAndCleanup
;
1392 /* Check if we need to find out if fast I/O is available */
1393 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1396 /* ASSERT(!KeIsExecutingDpc()); */
1398 /* Get the Fast I/O table */
1399 Device
= IoGetRelatedDeviceObject(FileObject
);
1400 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1403 ASSERT(FastIoDispatch
!= NULL
);
1404 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1406 /* Ask the driver if we can do it */
1407 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1416 /* It's not, fail */
1417 goto FailAndCleanup
;
1421 /* If we are going to modify the filesize,
1422 * save the old fs in case the operation fails.
1424 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1426 FileSizeModified
= TRUE
;
1427 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1428 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
1430 /* If the high part of the filesize is going
1431 * to change, grab the Paging IoResouce.
1433 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&&
1434 FcbHeader
->PagingIoResource
)
1436 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1437 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1438 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1442 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1448 * Set ourselves as top component.
1450 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1453 /* Check if there is a gap between the end of the file and the offset.
1454 * If yes, then we have to zero the data.
1456 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1458 Result
= CcZeroData(FileObject
,
1459 &FcbHeader
->ValidDataLength
,
1464 CcPrepareMdlWrite(FileObject
,
1473 CcPrepareMdlWrite(FileObject
,&Offset
,Length
,MdlChain
,IoStatus
);
1477 _SEH2_EXCEPT(FsRtlIsNtstatusExpected(_SEH2_GetExceptionCode()) ?
1478 EXCEPTION_EXECUTE_HANDLER
:
1479 EXCEPTION_CONTINUE_SEARCH
)
1485 /* Reset the top component */
1486 PsGetCurrentThread()->TopLevelIrp
= 0;
1488 /* Did the operation suceeded */
1491 /* Check if we need to update the filesize */
1492 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
)
1494 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&&
1495 FcbHeader
->PagingIoResource
)
1497 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1498 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1499 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1503 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1507 /* Flag the file as modified */
1508 FileObject
->Flags
|= FO_FILE_MODIFIED
;
1510 /* Check if the filesize has changed */
1511 if (FileSizeModified
)
1514 (PSHARED_CACHE_MAP
)FileObject
->SectionObjectPointer
->SharedCacheMap
;
1515 SharedCacheMap
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1516 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
1521 /* The operation did not succeed.
1522 * Reset the file size to what it should be.
1524 if (FileSizeModified
)
1526 if (FcbHeader
->PagingIoResource
)
1528 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1529 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1530 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1531 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1535 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1536 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1545 goto FailAndCleanup
;
1550 ExReleaseResourceLite(FcbHeader
->Resource
);
1551 FsRtlExitFileSystem();
1556 ExReleaseResourceLite(FcbHeader
->Resource
);
1557 FsRtlExitFileSystem();
1566 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject
)
1569 /* FsRtlAcquireFileExclusiveCommon(FileObject, 0, 0); */
1570 KeBugCheck(FILE_SYSTEM
);
1578 FsRtlReleaseFile(IN PFILE_OBJECT FileObject
)
1580 KeBugCheck(FILE_SYSTEM
);
1584 * @name FsRtlRegisterFileSystemFilterCallbacks
1589 * @param FilterDriverObject
1602 FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject
,
1603 IN PFS_FILTER_CALLBACKS Callbacks
)
1606 return STATUS_NOT_IMPLEMENTED
;