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
)
57 _SEH_FILTER(FsRtlCcCopyFilter
)
59 LONG ExceptionDisposition
;
61 /* Check if this was an expected exception */
62 ExceptionDisposition
= FsRtlIsNtstatusExpected(_SEH_GetExceptionCode() ?
63 EXCEPTION_EXECUTE_HANDLER
:
64 EXCEPTION_CONTINUE_SEARCH
);
66 /* Continue execution if we expected it, otherwise fail the call */
67 return ExceptionDisposition
;
76 FsRtlCopyRead(IN PFILE_OBJECT FileObject
,
77 IN PLARGE_INTEGER FileOffset
,
82 OUT PIO_STATUS_BLOCK IoStatus
,
83 IN PDEVICE_OBJECT DeviceObject
)
86 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
88 PFAST_IO_DISPATCH FastIoDispatch
;
89 PDEVICE_OBJECT Device
;
90 BOOLEAN Result
= TRUE
;
91 ULONG PageCount
= COMPUTE_PAGES_SPANNED(FileOffset
,Length
);
95 ASSERT(FileObject
->FsContext
);
101 IoStatus
->Status
= STATUS_SUCCESS
;
102 IoStatus
->Information
= 0;
106 if (MAXLONGLONG
< (LONGLONG
) FileOffset
->QuadPart
+ Length
) {
107 IoStatus
->Status
= STATUS_INVALID_PARAMETER
;
108 IoStatus
->Information
= 0;
112 /* Get the offset and FCB header */
113 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
114 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
118 /* Use a Resource Acquire */
119 FsRtlEnterFileSystem();
121 ExAcquireResourceSharedLite(FcbHeader
->Resource
, TRUE
);
123 /* Acquire the resource without blocking */
124 /* Return false and the I/O manager will retry using the standard IRP method. */
125 /* Use a Resource Acquire */
126 FsRtlEnterFileSystem();
127 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
, FALSE
)) {
128 FsRtlExitFileSystem();
129 FsRtlIncrementCcFastReadResourceMiss();
135 /* Check if this is a fast I/O cached file */
136 if (!(FileObject
->PrivateCacheMap
) ||
137 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
)) {
138 /* It's not, so fail */
143 /* Check if we need to find out if fast I/O is available */
144 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
147 ASSERT(!KeIsExecutingDpc());
149 /* Get the Fast I/O table */
150 Device
= IoGetRelatedDeviceObject(FileObject
);
151 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
154 ASSERT(FastIoDispatch
!= NULL
);
155 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
157 /* Ask the driver if we can do it */
158 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
173 /* Check if we read too much */
174 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
){
175 /* We did, check if the file offset is past the end */
176 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
){
177 /* Set end of file */
178 IoStatus
->Status
= STATUS_END_OF_FILE
;
179 IoStatus
->Information
= 0;
183 /* Otherwise, just normalize the length */
184 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
187 /* Set this as top-level IRP */
188 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
192 /* Make sure the IO and file size is below 4GB */
193 if (Wait
&& !(Offset
.HighPart
| FcbHeader
->FileSize
.HighPart
)) {
195 /* Call the cache controller */
196 CcFastCopyRead (FileObject
,FileOffset
->LowPart
,Length
,PageCount
,Buffer
,IoStatus
);
197 /* File was accessed */
198 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
199 if (IoStatus
->Status
!= STATUS_END_OF_FILE
) {
200 ASSERT(( FcbHeader
->FileSize
.QuadPart
) >= (FileOffset
->QuadPart
+ IoStatus
->Information
));
205 /* Call the cache controller */
206 Result
= CcCopyRead(FileObject
, FileOffset
, Length
, Wait
,Buffer
, IoStatus
);
207 /* File was accessed */
208 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
209 if (Result
== TRUE
) {
210 ASSERT( (IoStatus
->Status
== STATUS_END_OF_FILE
) ||
211 ((LONGLONG
)(FileOffset
->QuadPart
+ IoStatus
->Information
) <= FcbHeader
->FileSize
.QuadPart
)
216 /* Update the current file offset */
217 if (Result
== TRUE
) {
218 FileObject
->CurrentByteOffset
.QuadPart
+= IoStatus
->Information
;
221 _SEH_EXCEPT(FsRtlCcCopyFilter
)
226 PsGetCurrentThread()->TopLevelIrp
= 0;
228 /* Return to caller */
231 ExReleaseResourceLite(FcbHeader
->Resource
);
232 FsRtlExitFileSystem();
234 if (Result
== FALSE
) {
235 CcFastReadNotPossible
+= 1;
248 FsRtlCopyWrite(IN PFILE_OBJECT FileObject
,
249 IN PLARGE_INTEGER FileOffset
,
254 OUT PIO_STATUS_BLOCK IoStatus
,
255 IN PDEVICE_OBJECT DeviceObject
)
258 BOOLEAN Result
= TRUE
;
259 PFAST_IO_DISPATCH FastIoDispatch
;
260 PDEVICE_OBJECT Device
;
261 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
263 /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
264 BOOLEAN FileOffsetAppend
= ((FileOffset
->HighPart
== 0xffffffff) && (FileOffset
->LowPart
== 0xffffffff));
265 BOOLEAN ResourceAquiredShared
= FALSE
;
267 BOOLEAN b_4GB
= FALSE
;
269 BOOLEAN FileSizeModified
= FALSE
;
270 LARGE_INTEGER OldFileSize
;
271 LARGE_INTEGER OldValidDataLength
;
273 LARGE_INTEGER NewSize
;
274 LARGE_INTEGER Offset
;
279 ASSERT(FileObject
->FsContext
);
281 /* Initialize some of the vars and pointers */
282 NewSize
.QuadPart
= 0;
283 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
284 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
286 /* Nagar p.544 -- Check with Cc if we can write and check if the IO > 64kB (WDK macro) */
287 if ( (CcCanIWrite(FileObject
, Length
,Wait
, FALSE
) == FALSE
) ||
288 (CcCopyWriteWontFlush(FileObject
,FileOffset
,Length
) == FALSE
) ||
289 ((FileObject
->Flags
& FO_WRITE_THROUGH
)== TRUE
)
298 IoStatus
->Status
= STATUS_SUCCESS
;
299 IoStatus
->Information
= Length
;
303 FsRtlEnterFileSystem();
305 /* Nagar p.544/545 -- The CcFastCopyWrite doesn't deal with filesize beyond 4GB*/
306 if (Wait
&& (FcbHeader
->AllocationSize
.HighPart
== 0))
308 /* If the file offset is not past the file size, then we can acquire the lock shared */
309 if ((FileOffsetAppend
== FALSE
) && (Offset
.LowPart
<= FcbHeader
->ValidDataLength
.LowPart
)){
310 ExAcquireResourceSharedLite(FcbHeader
->Resource
,TRUE
);
311 ResourceAquiredShared
= TRUE
;
313 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
316 /* Nagar p.544/545 -- If we append, use the file size as offset. Also, check that we aren't crossing the 4GB boundary */
317 if ((FileOffsetAppend
== TRUE
)) {
318 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
;
319 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
320 b_4GB
= (NewSize
.LowPart
< FcbHeader
->FileSize
.LowPart
);
323 Offset
.LowPart
= FileOffset
->LowPart
;
324 NewSize
.LowPart
= FileOffset
->LowPart
+ Length
;
325 b_4GB
= ((NewSize
.LowPart
< FileOffset
->LowPart
) || (FileOffset
->HighPart
!= 0));
329 Make sure that caching is initated.
330 That fast are allowed for this file stream.
331 That we are not extending past the allocated size
332 That we are not creating a hole bigger than 8k
333 That we are not crossing the 4GB boundary
335 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
336 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
337 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
338 (Offset
.LowPart
< (FcbHeader
->ValidDataLength
.LowPart
+ 0x2000) ) &&
342 /* If we are extending past the file size, we need to release the lock and acquire it
343 exclusively, because we are going to need to update the FcbHeader */
344 if (ResourceAquiredShared
&& (NewSize
.LowPart
> (FcbHeader
->ValidDataLength
.LowPart
+ 0x2000))) {
345 /* Then we need to acquire the resource exclusive */
346 ExReleaseResourceLite(FcbHeader
->Resource
);
347 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
348 if (FileOffsetAppend
== TRUE
) {
349 Offset
.LowPart
= FcbHeader
->FileSize
.LowPart
; // ??
350 NewSize
.LowPart
= FcbHeader
->FileSize
.LowPart
+ Length
;
351 /* Make sure we don't cross the 4GB boundary */
352 b_4GB
= (NewSize
.LowPart
< Offset
.LowPart
);
355 /* Recheck some of the conditions since we let the lock go */
356 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
357 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
358 (FcbHeader
->AllocationSize
.LowPart
>= NewSize
.LowPart
) &&
359 (FcbHeader
->AllocationSize
.HighPart
== 0) &&
374 /* Check if we need to find out if fast I/O is available */
375 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
377 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
380 ASSERT(!KeIsExecutingDpc());
382 /* Get the Fast I/O table */
383 Device
= IoGetRelatedDeviceObject(FileObject
);
384 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
387 ASSERT(FastIoDispatch
!= NULL
);
388 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
390 /* Ask the driver if we can do it */
391 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
392 FileOffsetAppend
? &FcbHeader
->FileSize
:FileOffset
,
397 &FastIoCheckIfPossibleStatus
,
405 /* If we are going to extend the file then save the old file size
406 in case the operation fails
408 if (NewSize
.LowPart
> FcbHeader
->FileSize
.LowPart
) {
409 FileSizeModified
= TRUE
;
410 OldFileSize
.LowPart
= FcbHeader
->FileSize
.LowPart
;
411 OldValidDataLength
.LowPart
= FcbHeader
->ValidDataLength
.LowPart
;
412 FcbHeader
->FileSize
.LowPart
= NewSize
.LowPart
;
415 /* Set this as top-level IRP */
416 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
420 if (Offset
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
) {
421 LARGE_INTEGER OffsetVar
;
422 OffsetVar
.LowPart
= Offset
.LowPart
;
423 OffsetVar
.HighPart
= 0;
424 CcZeroData(FileObject
,&FcbHeader
->ValidDataLength
,&OffsetVar
,TRUE
);
427 /* Call the cache manager */
428 CcFastCopyWrite(FileObject
,Offset
.LowPart
,Length
,Buffer
);
430 _SEH_EXCEPT(FsRtlCcCopyFilter
)
435 /* Remove ourselves at the top level component after the IO is done */
436 PsGetCurrentThread()->TopLevelIrp
= 0;
438 /* Did the operation succeed ? */
439 if (Result
== TRUE
) {
440 /* Update the valid file size if necessary */
441 if (NewSize
.LowPart
> FcbHeader
->ValidDataLength
.LowPart
){
442 FcbHeader
->ValidDataLength
.LowPart
= NewSize
.LowPart
;
445 /* Flag the file as modified */
446 FileObject
->Flags
|= FO_FILE_MODIFIED
;
448 /* Update the strucutres if the file size changed */
449 if (FileSizeModified
) {
450 ((SHARED_CACHE_MAP
*) FileObject
->SectionObjectPointer
->SharedCacheMap
)->FileSize
.LowPart
= NewSize
.LowPart
;
451 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
454 /* Update the file object current file offset */
455 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.LowPart
;
459 /* Result == FALSE if we get here. */
460 if (FileSizeModified
) {
461 /* If the file size was modified then restore the old file size */
462 if(FcbHeader
->PagingIoResource
!= NULL
) {
463 // Nagar P.544 Restore the old file size if operation didn't succeed.
464 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
,TRUE
);
465 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
466 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
467 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
469 /* If there is no lock and do it without */
470 FcbHeader
->FileSize
.LowPart
= OldFileSize
.LowPart
;
471 FcbHeader
->ValidDataLength
.LowPart
= OldValidDataLength
.LowPart
;
481 LARGE_INTEGER OldFileSize
;
484 ASSERT(!KeIsExecutingDpc());
487 /* Check if we need to acquire the resource exclusive */
488 if ( (FileOffsetAppend
== FALSE
) &&
489 ( (FileOffset
->QuadPart
+ Length
) <= FcbHeader
->ValidDataLength
.QuadPart
)
492 /* Acquire the resource shared */
493 if (!ExAcquireResourceSharedLite(FcbHeader
->Resource
,Wait
)) {
494 goto LeaveCriticalAndFail
;
496 ResourceAquiredShared
=TRUE
;
498 /* Acquire the resource exclusive */
499 if (!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,Wait
)) {
500 goto LeaveCriticalAndFail
;
504 /* Check if we are appending */
505 if (FileOffsetAppend
== TRUE
) {
506 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
507 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
509 Offset
.QuadPart
= FileOffset
->QuadPart
;
510 NewSize
.QuadPart
+= FileOffset
->QuadPart
+ Length
;
514 Make sure that caching is initated.
515 That fast are allowed for this file stream.
516 That we are not extending past the allocated size
517 That we are not creating a hole bigger than 8k
519 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
520 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
521 ((FcbHeader
->ValidDataLength
.QuadPart
+ 0x2000) > Offset
.QuadPart
) &&
522 (MAXLONGLONG
> (Offset
.QuadPart
+ Length
)) &&
523 (FcbHeader
->AllocationSize
.QuadPart
>= NewSize
.QuadPart
)
526 /* Check if we can keep the lock shared */
527 if (ResourceAquiredShared
&& (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) ) {
528 ExReleaseResourceLite(FcbHeader
->Resource
);
529 if(!ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,Wait
))
531 goto LeaveCriticalAndFail
;
534 /* Compute the offset and the new filesize */
535 if (FileOffsetAppend
) {
536 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
537 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
540 /* Recheck the above points since we released and reacquire the lock */
541 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
542 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
543 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
)
552 /* Check if we need to find out if fast I/O is available */
553 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
555 IO_STATUS_BLOCK FastIoCheckIfPossibleStatus
;
558 ASSERT(!KeIsExecutingDpc());
560 /* Get the Fast I/O table */
561 Device
= IoGetRelatedDeviceObject(FileObject
);
562 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
565 ASSERT(FastIoDispatch
!= NULL
);
566 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
568 /* Ask the driver if we can do it */
569 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
570 FileOffsetAppend
? &FcbHeader
->FileSize
:FileOffset
,
575 &FastIoCheckIfPossibleStatus
,
584 /* If we are going to modify the filesize, save the old fs in case the operation fails */
585 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
) {
586 FileSizeModified
= TRUE
;
587 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
588 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
590 /* If the high part of the filesize is going to change, grab the Paging IoResouce */
591 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&& FcbHeader
->PagingIoResource
) {
592 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
593 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
594 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
596 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
601 /* Set ourselves as top component */
602 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
605 BOOLEAN CallCc
= TRUE
;
606 /* Check if there is a gap between the end of the file and the offset
607 If yes, then we have to zero the data
609 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) {
610 if (!(Result
= CcZeroData(FileObject
,&FcbHeader
->ValidDataLength
,&Offset
,Wait
))) {
611 /* If this operation fails, then we have to exit
612 We can jump outside the SEH, so I a using a variable to exit
619 /* Unless the CcZeroData failed, call the cache manager */
621 Result
= CcCopyWrite(FileObject
,&Offset
,Length
, Wait
, Buffer
);
623 }_SEH_EXCEPT(FsRtlCcCopyFilter
)
628 /* Reset the top component */
629 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
631 /* Did the operation suceeded */
633 /* Check if we need to update the filesize */
634 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) {
635 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&& FcbHeader
->PagingIoResource
) {
636 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
637 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
638 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
640 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
644 /* Flag the file as modified */
645 FileObject
->Flags
|= FO_FILE_MODIFIED
;
646 /* Check if the filesize has changed */
647 if (FileSizeModified
) {
648 /* Update the file sizes */
649 ((SHARED_CACHE_MAP
*) FileObject
->SectionObjectPointer
->SharedCacheMap
)->FileSize
.QuadPart
= NewSize
.QuadPart
;
650 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
652 /* Update the current FO byte offset */
653 FileObject
->CurrentByteOffset
.QuadPart
= NewSize
.QuadPart
;
657 /* The operation did not succeed
658 Reset the file size to what it should be
660 if (FileSizeModified
) {
661 if (FcbHeader
->PagingIoResource
) {
662 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
663 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
664 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
665 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
667 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
668 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
680 LeaveCriticalAndFail
:
681 FsRtlExitFileSystem();
687 ExReleaseResourceLite(FcbHeader
->Resource
);
688 FsRtlExitFileSystem();
693 ExReleaseResourceLite(FcbHeader
->Resource
);
694 FsRtlExitFileSystem();
703 FsRtlGetFileSize(IN PFILE_OBJECT FileObject
,
704 IN OUT PLARGE_INTEGER FileSize
)
706 FILE_STANDARD_INFORMATION Info
;
708 IO_STATUS_BLOCK IoStatus
;
709 PDEVICE_OBJECT DeviceObject
;
710 PFAST_IO_DISPATCH FastDispatch
;
712 PIO_STACK_LOCATION IoStackLocation
;
714 BOOLEAN OldHardError
;
719 /* Get Device Object and Fast Calls */
720 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
721 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
723 /* Check if we support Fast Calls, and check FastIoQueryStandardInfo */
724 /* Call the function and see if it succeeds */
725 if ( !FastDispatch
||
726 !FastDispatch
->FastIoQueryStandardInfo
||
727 !FastDispatch
->FastIoQueryStandardInfo(FileObject
,TRUE
,
728 &Info
,&IoStatus
,DeviceObject
))
730 /* If any of the above failed, then we are going to send an IRP to the device object */
731 /* Initialize the even for the IO */
732 KeInitializeEvent(&Event
,NotificationEvent
,FALSE
);
733 /* Allocate the IRP */
734 Irp
= IoAllocateIrp(DeviceObject
->StackSize
,FALSE
);
737 return STATUS_INSUFFICIENT_RESOURCES
;
741 /* Don't process hard error */
742 OldHardError
= IoSetThreadHardErrorMode(FALSE
);
745 Irp
->UserIosb
= &IoStatus
;
746 Irp
->UserEvent
= &Event
;
747 Irp
->Tail
.Overlay
.Thread
= PsGetCurrentThread();
748 Irp
->Flags
= IRP_SYNCHRONOUS_PAGING_IO
| IRP_PAGING_IO
;
749 Irp
->RequestorMode
= KernelMode
;
750 Irp
->Tail
.Overlay
.OriginalFileObject
= FileObject
;
751 Irp
->AssociatedIrp
.SystemBuffer
= &Info
;
753 /* Setup out stack location */
754 IoStackLocation
= Irp
->Tail
.Overlay
.CurrentStackLocation
;
756 IoStackLocation
->MajorFunction
= IRP_MJ_QUERY_INFORMATION
;
757 IoStackLocation
->FileObject
= FileObject
;
758 IoStackLocation
->DeviceObject
= DeviceObject
;
759 IoStackLocation
->Parameters
.QueryFile
.Length
= ALIGN_UP(sizeof(FILE_INFORMATION_CLASS
),ULONG
);
760 IoStackLocation
->Parameters
.QueryFile
.FileInformationClass
= FileStandardInformation
;
762 /* Send the IRP to the related device object */
763 Status
= IofCallDriver(DeviceObject
,Irp
);
765 /* Standard DDK IRP result processing */
766 if (Status
== STATUS_PENDING
)
768 KeWaitForSingleObject(&Event
,Executive
,KernelMode
,FALSE
,NULL
);
771 /* If there was a synchronous error, signal it */
772 if (!NT_SUCCESS(Status
))
774 IoStatus
.Status
= Status
;
777 IoSetThreadHardErrorMode(OldHardError
);
780 /* Check the sync/async IO result */
781 if (NT_SUCCESS(IoStatus
.Status
))
783 /* Was the request for a directory ? */
786 IoStatus
.Status
= STATUS_FILE_IS_A_DIRECTORY
;
790 FileSize
->QuadPart
= Info
.EndOfFile
.QuadPart
;
794 return IoStatus
.Status
;
803 FsRtlMdlRead(IN PFILE_OBJECT FileObject
,
804 IN PLARGE_INTEGER FileOffset
,
808 OUT PIO_STATUS_BLOCK IoStatus
)
810 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
811 PFAST_IO_DISPATCH FastDispatch
;
813 /* Get Device Object and Fast Calls */
814 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
815 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
817 /* Check if we support Fast Calls, and check this one */
818 if (FastDispatch
&& FastDispatch
->MdlRead
)
820 /* Use the fast path */
821 return FastDispatch
->MdlRead(FileObject
,
830 /* Get the Base File System (Volume) and Fast Calls */
831 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
832 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
834 /* If the Base Device Object has its own FastDispatch Routine, fail */
835 if (FastDispatch
&& FastDispatch
->MdlRead
&&
836 BaseDeviceObject
!= DeviceObject
)
841 /* No fast path, use slow path */
842 return FsRtlMdlReadDev(FileObject
,
856 FsRtlMdlReadComplete(IN PFILE_OBJECT FileObject
,
857 IN OUT PMDL MdlChain
)
859 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
860 PFAST_IO_DISPATCH FastDispatch
;
862 /* Get Device Object and Fast Calls */
863 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
864 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
866 /* Check if we support Fast Calls, and check this one */
867 if (FastDispatch
&& FastDispatch
->MdlReadComplete
)
869 /* Use the fast path */
870 return FastDispatch
->MdlReadComplete(FileObject
,
875 /* Get the Base File System (Volume) and Fast Calls */
876 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
877 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
879 /* If the Base Device Object has its own FastDispatch Routine, fail */
880 if ((BaseDeviceObject
!= DeviceObject
) && FastDispatch
881 && FastDispatch
->MdlReadComplete
)
886 /* No fast path, use slow path */
887 return FsRtlMdlReadCompleteDev(FileObject
, MdlChain
, DeviceObject
);
895 FsRtlMdlReadCompleteDev(IN PFILE_OBJECT FileObject
,
896 IN PMDL MemoryDescriptorList
,
897 IN PDEVICE_OBJECT DeviceObject
)
899 /* Call the Cache Manager */
900 CcMdlReadComplete2(MemoryDescriptorList
, FileObject
);
910 FsRtlMdlReadDev(IN PFILE_OBJECT FileObject
,
911 IN PLARGE_INTEGER FileOffset
,
915 OUT PIO_STATUS_BLOCK IoStatus
,
916 IN PDEVICE_OBJECT DeviceObject
)
918 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
919 BOOLEAN Result
= TRUE
;
920 LARGE_INTEGER Offset
;
921 PFAST_IO_DISPATCH FastIoDispatch
;
922 PDEVICE_OBJECT Device
;
929 IoStatus
->Status
= STATUS_SUCCESS
;
930 IoStatus
->Information
= 0;
935 ASSERT(MAXLONGLONG
- FileOffset
->QuadPart
>= (LONGLONG
)Length
);
937 /* Get the offset and FCB header */
938 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
939 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
942 FsRtlEnterFileSystem();
946 ExAcquireResourceShared(FcbHeader
->Resource
, TRUE
);
948 /* Check if this is a fast I/O cached file */
949 if (!(FileObject
->PrivateCacheMap
) ||
950 (FcbHeader
->IsFastIoPossible
== FastIoIsNotPossible
))
952 /* It's not, so fail */
953 CcFastMdlReadNotPossible
+= 1;
958 /* Check if we need to find out if fast I/O is available */
959 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
961 /* Get the Fast I/O table */
962 Device
= IoGetRelatedDeviceObject(FileObject
);
963 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
966 ASSERT(!KeIsExecutingDpc());
967 ASSERT(FastIoDispatch
!= NULL
);
968 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
970 /* Ask the driver if we can do it */
971 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
981 CcFastMdlReadNotPossible
+= 1;
987 /* Check if we read too much */
988 if (Offset
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
990 /* We did, check if the file offset is past the end */
991 if (FileOffset
->QuadPart
>= FcbHeader
->FileSize
.QuadPart
)
993 /* Set end of file */
994 IoStatus
->Status
= STATUS_END_OF_FILE
;
995 IoStatus
->Information
= 0;
999 /* Otherwise, just normalize the length */
1000 Length
= (ULONG
)(FcbHeader
->FileSize
.QuadPart
- FileOffset
->QuadPart
);
1003 /* Set this as top-level IRP */
1004 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1008 /* Attempt a read */
1009 CcMdlRead(FileObject
, FileOffset
, Length
, MdlChain
, IoStatus
);
1010 FileObject
->Flags
|= FO_FILE_FAST_IO_READ
;
1012 _SEH_EXCEPT(FsRtlCcCopyFilter
)
1018 /* Remove the top-level IRP flag */
1019 PsGetCurrentThread()->TopLevelIrp
= 0;
1021 /* Return to caller */
1023 ExReleaseResourceLite(FcbHeader
->Resource
);
1024 FsRtlExitFileSystem();
1033 FsRtlMdlWriteComplete(IN PFILE_OBJECT FileObject
,
1034 IN PLARGE_INTEGER FileOffset
,
1037 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1038 PFAST_IO_DISPATCH FastDispatch
;
1040 /* Get Device Object and Fast Calls */
1041 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1042 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1044 /* Check if we support Fast Calls, and check this one */
1045 if (FastDispatch
&& FastDispatch
->MdlWriteComplete
)
1047 /* Use the fast path */
1048 return FastDispatch
->MdlWriteComplete(FileObject
,
1054 /* Get the Base File System (Volume) and Fast Calls */
1055 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1056 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1058 /* If the Base Device Object has its own FastDispatch Routine, fail */
1059 if (FastDispatch
&& FastDispatch
->MdlWriteComplete
&&
1060 BaseDeviceObject
!= DeviceObject
)
1065 /* No fast path, use slow path */
1066 return FsRtlMdlWriteCompleteDev(FileObject
,
1077 FsRtlMdlWriteCompleteDev(IN PFILE_OBJECT FileObject
,
1078 IN PLARGE_INTEGER FileOffset
,
1080 IN PDEVICE_OBJECT DeviceObject
)
1082 if (FileObject
->Flags
& FO_WRITE_THROUGH
)
1088 /* Call the Cache Manager */
1089 CcMdlWriteComplete2(FileObject
,FileOffset
,MdlChain
);
1098 FsRtlPrepareMdlWrite(IN PFILE_OBJECT FileObject
,
1099 IN PLARGE_INTEGER FileOffset
,
1103 OUT PIO_STATUS_BLOCK IoStatus
)
1105 PDEVICE_OBJECT DeviceObject
, BaseDeviceObject
;
1106 PFAST_IO_DISPATCH FastDispatch
;
1108 /* Get Device Object and Fast Calls */
1109 DeviceObject
= IoGetRelatedDeviceObject(FileObject
);
1110 FastDispatch
= DeviceObject
->DriverObject
->FastIoDispatch
;
1112 /* Check if we support Fast Calls, and check this one */
1113 if (FastDispatch
&& FastDispatch
->PrepareMdlWrite
)
1115 /* Use the fast path */
1116 return FastDispatch
->PrepareMdlWrite(FileObject
,
1125 /* Get the Base File System (Volume) and Fast Calls */
1126 BaseDeviceObject
= IoGetBaseFileSystemDeviceObject(FileObject
);
1127 FastDispatch
= BaseDeviceObject
->DriverObject
->FastIoDispatch
;
1129 /* If the Base Device Object has its own FastDispatch Routine, fail */
1130 if (FastDispatch
&& FastDispatch
->PrepareMdlWrite
&&
1131 BaseDeviceObject
!= DeviceObject
)
1136 /* No fast path, use slow path */
1137 return FsRtlPrepareMdlWriteDev(FileObject
,
1151 FsRtlPrepareMdlWriteDev(IN PFILE_OBJECT FileObject
,
1152 IN PLARGE_INTEGER FileOffset
,
1156 OUT PIO_STATUS_BLOCK IoStatus
,
1157 IN PDEVICE_OBJECT DeviceObject
)
1159 BOOLEAN Result
= TRUE
;
1160 PFAST_IO_DISPATCH FastIoDispatch
;
1161 PDEVICE_OBJECT Device
;
1162 PFSRTL_COMMON_FCB_HEADER FcbHeader
;
1164 LARGE_INTEGER OldFileSize
;
1165 LARGE_INTEGER OldValidDataLength
;
1166 LARGE_INTEGER NewSize
;
1167 LARGE_INTEGER Offset
;
1169 /* WDK doc. Offset=0xffffffffffffffff indicates append to the end of file */
1170 BOOLEAN FileOffsetAppend
= ((FileOffset
->HighPart
== 0xffffffff) && (FileOffset
->LowPart
== 0xffffffff));
1171 BOOLEAN FileSizeModified
= FALSE
;
1172 BOOLEAN ResourceAquiredShared
= FALSE
;
1174 /* Initialize some of the vars and pointers */
1175 OldFileSize
.QuadPart
= 0;
1176 OldValidDataLength
.QuadPart
= 0;
1180 Offset
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1182 /* Nagar p.544 -- Check with Cc if we can write */
1183 if ( (!CcCanIWrite(FileObject
, Length
,TRUE
,FALSE
))||
1184 (FileObject
->Flags
& FO_WRITE_THROUGH
))
1189 IoStatus
->Status
= STATUS_SUCCESS
;
1191 /* No actual read */
1197 FcbHeader
= (PFSRTL_COMMON_FCB_HEADER
)FileObject
->FsContext
;
1198 FsRtlEnterFileSystem();
1200 /* Check we are going to extend the file */
1201 if ( (FileOffsetAppend
== FALSE
) &&
1202 ( (FileOffset
->QuadPart
+ Length
) <= FcbHeader
->ValidDataLength
.QuadPart
)
1205 /* Acquire the resource shared */
1206 ExAcquireResourceSharedLite(FcbHeader
->Resource
,TRUE
);
1207 ResourceAquiredShared
=TRUE
;
1210 /* Acquire the resource exclusive */
1211 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
1214 /* Check if we are appending */
1215 if (FileOffsetAppend
== TRUE
) {
1216 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1217 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1220 Offset
.QuadPart
= FileOffset
->QuadPart
;
1221 NewSize
.QuadPart
= FileOffset
->QuadPart
+ Length
;
1224 if ( (FileObject
->PrivateCacheMap
) &&
1225 (FcbHeader
->IsFastIoPossible
) &&
1226 (MAXLONGLONG
>= (LONGLONG
) FileOffset
->QuadPart
+ Length
) &&
1227 (NewSize
.QuadPart
<= FcbHeader
->AllocationSize
.QuadPart
) )
1229 /* Check if we can keep the lock shared */
1230 if (ResourceAquiredShared
&& (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) ) {
1231 ExReleaseResourceLite(FcbHeader
->Resource
);
1232 ExAcquireResourceExclusiveLite(FcbHeader
->Resource
,TRUE
);
1234 /* Compute the offset and the new filesize */
1235 if (FileOffsetAppend
) {
1236 Offset
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1237 NewSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
+ Length
;
1240 /* Recheck the above points since we released and reacquire the lock */
1241 if ( (FileObject
->PrivateCacheMap
!= NULL
) &&
1242 (FcbHeader
->IsFastIoPossible
!= FastIoIsNotPossible
) &&
1243 (FcbHeader
->AllocationSize
.QuadPart
> NewSize
.QuadPart
)
1248 goto FailAndCleanup
;
1252 /* Check if we need to find out if fast I/O is available */
1253 if (FcbHeader
->IsFastIoPossible
== FastIoIsQuestionable
)
1256 /* ASSERT(!KeIsExecutingDpc()); */
1258 /* Get the Fast I/O table */
1259 Device
= IoGetRelatedDeviceObject(FileObject
);
1260 FastIoDispatch
= Device
->DriverObject
->FastIoDispatch
;
1263 ASSERT(FastIoDispatch
!= NULL
);
1264 ASSERT(FastIoDispatch
->FastIoCheckIfPossible
!= NULL
);
1266 /* Ask the driver if we can do it */
1267 if (!FastIoDispatch
->FastIoCheckIfPossible(FileObject
,
1276 /* It's not, fail */
1277 goto FailAndCleanup
;
1281 /* If we are going to modify the filesize, save the old fs in case the operation fails */
1282 if (NewSize
.QuadPart
> FcbHeader
->FileSize
.QuadPart
)
1284 FileSizeModified
= TRUE
;
1285 OldFileSize
.QuadPart
= FcbHeader
->FileSize
.QuadPart
;
1286 OldValidDataLength
.QuadPart
= FcbHeader
->ValidDataLength
.QuadPart
;
1288 /* If the high part of the filesize is going to change, grab the Paging IoResouce */
1289 if (NewSize
.HighPart
!= FcbHeader
->FileSize
.HighPart
&& FcbHeader
->PagingIoResource
)
1291 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1292 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1293 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1295 FcbHeader
->FileSize
.QuadPart
= NewSize
.QuadPart
;
1301 /* Set ourselves as top component */
1302 PsGetCurrentThread()->TopLevelIrp
= FSRTL_FAST_IO_TOP_LEVEL_IRP
;
1305 /* Check if there is a gap between the end of the file and the offset
1306 If yes, then we have to zero the data
1308 if (Offset
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) {
1309 Result
= CcZeroData(FileObject
,&FcbHeader
->ValidDataLength
,&Offset
,TRUE
);
1312 CcPrepareMdlWrite(FileObject
,&Offset
,Length
,MdlChain
,IoStatus
);
1315 CcPrepareMdlWrite(FileObject
,&Offset
,Length
,MdlChain
,IoStatus
);
1318 }_SEH_EXCEPT(FsRtlCcCopyFilter
)
1323 /* Reset the top component */
1324 PsGetCurrentThread()->TopLevelIrp
= 0;
1326 /* Did the operation suceeded */
1328 /* Check if we need to update the filesize */
1329 if (NewSize
.QuadPart
> FcbHeader
->ValidDataLength
.QuadPart
) {
1330 if (NewSize
.HighPart
!= FcbHeader
->ValidDataLength
.HighPart
&& FcbHeader
->PagingIoResource
) {
1331 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1332 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1333 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1335 FcbHeader
->ValidDataLength
.QuadPart
= NewSize
.QuadPart
;
1339 /* Flag the file as modified */
1340 FileObject
->Flags
|= FO_FILE_MODIFIED
;
1341 /* Check if the filesize has changed */
1342 if (FileSizeModified
) {
1343 /* Update the file sizes */
1344 ((SHARED_CACHE_MAP
*) FileObject
->SectionObjectPointer
->SharedCacheMap
)->FileSize
.QuadPart
= NewSize
.QuadPart
;
1345 FileObject
->Flags
|= FO_FILE_SIZE_CHANGED
;
1351 /* The operation did not succeed
1352 Reset the file size to what it should be
1354 if (FileSizeModified
) {
1355 if (FcbHeader
->PagingIoResource
) {
1356 ExAcquireResourceExclusiveLite(FcbHeader
->PagingIoResource
, TRUE
);
1357 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1358 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1359 ExReleaseResourceLite(FcbHeader
->PagingIoResource
);
1361 FcbHeader
->FileSize
.QuadPart
= OldFileSize
.QuadPart
;
1362 FcbHeader
->ValidDataLength
.QuadPart
= OldValidDataLength
.QuadPart
;
1372 goto FailAndCleanup
;
1378 ExReleaseResourceLite(FcbHeader
->Resource
);
1379 FsRtlExitFileSystem();
1384 ExReleaseResourceLite(FcbHeader
->Resource
);
1385 FsRtlExitFileSystem();
1395 FsRtlAcquireFileExclusive(IN PFILE_OBJECT FileObject
)
1399 FsRtlAcquireFileExclusiveCommon(FileObject,0,0);
1401 KeBugCheck(FILE_SYSTEM
);
1409 FsRtlReleaseFile(IN PFILE_OBJECT FileObject
)
1412 KeBugCheck(FILE_SYSTEM
);
1416 * @name FsRtlRegisterFileSystemFilterCallbacks
1421 * @param FilterDriverObject
1434 FsRtlRegisterFileSystemFilterCallbacks(IN PDRIVER_OBJECT FilterDriverObject
,
1435 IN PFS_FILTER_CALLBACKS Callbacks
)
1438 return STATUS_NOT_IMPLEMENTED
;